| // TODO: remove need for this option |
| /* { dg-additional-options "-fanalyzer-checker=taint" } */ |
| |
| #include "analyzer-decls.h" |
| |
| struct arg_buf |
| { |
| int i; |
| int j; |
| }; |
| |
| /* Example of marking a function as tainted. */ |
| |
| void __attribute__((tainted_args)) |
| test_1 (int i, void *p, char *q) |
| { |
| /* There should be a single enode, |
| for the "tainted" entry to the function. */ |
| __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ |
| |
| __analyzer_dump_state ("taint", i); /* { dg-warning "state: 'tainted'" } */ |
| __analyzer_dump_state ("taint", p); /* { dg-warning "state: 'tainted'" } */ |
| __analyzer_dump_state ("taint", q); /* { dg-warning "state: 'tainted'" } */ |
| __analyzer_dump_state ("taint", *q); /* { dg-warning "state: 'tainted'" } */ |
| |
| struct arg_buf *args = p; |
| __analyzer_dump_state ("taint", args->i); /* { dg-warning "state: 'tainted'" } */ |
| __analyzer_dump_state ("taint", args->j); /* { dg-warning "state: 'tainted'" } */ |
| } |
| |
| /* Example of marking a callback field as tainted. */ |
| |
| struct s2 |
| { |
| void (*cb) (int, void *, char *) |
| __attribute__((tainted_args)); |
| }; |
| |
| /* Function not marked as tainted. */ |
| |
| void |
| test_2a (int i, void *p, char *q) |
| { |
| /* There should be a single enode, |
| for the normal entry to the function. */ |
| __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ |
| |
| __analyzer_dump_state ("taint", i); /* { dg-warning "state: 'start'" } */ |
| __analyzer_dump_state ("taint", p); /* { dg-warning "state: 'start'" } */ |
| __analyzer_dump_state ("taint", q); /* { dg-warning "state: 'start'" } */ |
| |
| struct arg_buf *args = p; |
| __analyzer_dump_state ("taint", args->i); /* { dg-warning "state: 'start'" } */ |
| __analyzer_dump_state ("taint", args->j); /* { dg-warning "state: 'start'" } */ |
| } |
| |
| /* Function referenced via t2b.cb, marked as "tainted". */ |
| |
| void |
| test_2b (int i, void *p, char *q) |
| { |
| /* There should be two enodes |
| for the direct call, and the "tainted" entry to the function. */ |
| __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */ |
| } |
| |
| /* Callback used via t2c.cb, marked as "tainted". */ |
| void |
| __analyzer_test_2c (int i, void *p, char *q) |
| { |
| /* There should be a single enode, |
| for the "tainted" entry to the function. */ |
| __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */ |
| |
| __analyzer_dump_state ("taint", i); /* { dg-warning "state: 'tainted'" } */ |
| __analyzer_dump_state ("taint", p); /* { dg-warning "state: 'tainted'" } */ |
| __analyzer_dump_state ("taint", q); /* { dg-warning "state: 'tainted'" } */ |
| } |
| |
| struct s2 t2b = |
| { |
| .cb = test_2b |
| }; |
| |
| struct s2 t2c = |
| { |
| .cb = __analyzer_test_2c |
| }; |