1  // TODO: remove need for this option:
       2  /* { dg-additional-options "-fanalyzer-checker=taint" } */
       3  
       4  #include "analyzer-decls.h"
       5  #include <stdio.h>
       6  #include <stdlib.h>
       7  #include <string.h>
       8  
       9  struct foo
      10  {
      11    size_t sz;
      12  };
      13  
      14  char buf[100];
      15  char buf2[100];
      16  
      17  /* memset with tainted size.  */
      18  
      19  void test_1 (FILE *f)
      20  {
      21    struct foo tmp;
      22    if (1 == fread(&tmp, sizeof(tmp), 1, f)) { /* { dg-message "\\(\[0-9\]+\\) 'tmp' gets an unchecked value here" "event: tmp gets unchecked value" { xfail *-*-* } } */
      23                                               /* { dg-message "\\(\[0-9\]+\\) following 'true' branch\\.\\.\\." "event: following true branch" { target *-*-* } .-1 } */
      24      __analyzer_dump_state ("taint", tmp.sz); /* { dg-warning "state: 'tainted'" } */
      25      /* { dg-message "\\(\[0-9\]+\\) \\.\\.\\.to here" "event: to here" { target *-*-* } .-1 } */
      26  
      27      memset (buf, 0, tmp.sz); /* { dg-warning "use of attacker-controlled value 'tmp\\.sz' as size without upper-bounds checking" "warning" } */
      28      /* { dg-message "23: \\(\[0-9\]+\\) 'tmp.i' has an unchecked value here \\(from 'tmp'\\)" "event: tmp.i has an unchecked value" { xfail *-*-* } .-1 } */
      29      /* { dg-message "\\(\[0-9\]+\\) use of attacker-controlled value 'tmp\\.sz' as size without upper-bounds checking" "final event" { target *-*-* } .-2 } */
      30      
      31      // TOOD: better messages for state changes
      32    }
      33  }
      34  
      35  /* memcpy with tainted size.  */
      36  
      37  void __attribute__((tainted_args))
      38  test_2 (size_t sz)
      39  {
      40    memcpy (buf, buf2, sz); /* { dg-warning "use of attacker-controlled value 'sz' as size without upper-bounds checking" } */
      41  }