/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */ /* { dg-skip-if "requires hosted libstdc++ for stdlib malloc" { ! hostedlib } } */ /* There need to be at least two calls to a function for the call-summarization code to be used. TODO: add some kind of test that summarization *was* used. */ #include #include #include "../../gcc.dg/analyzer/analyzer-decls.h" int *malloc_int (int i) { int *res = (int *) malloc (sizeof (int)); if (!res) return NULL; *res = i; return res; } void test_malloc_int (int x) { int *p, *q; p = malloc_int (42); if (p) __analyzer_eval (*p == 42); /* { dg-warning "TRUE" } */ free (p); q = malloc_int (x); if (q) __analyzer_eval (*q == x); /* { dg-warning "TRUE" } */ free (q); } void test_leak (int x) { int *p = malloc_int (x); /* { dg-message "when 'malloc_int' returns pointer to heap-allocated buffer" "" { target c } } */ /* { dg-message "when 'int\\* malloc_int\\(int\\)' returns pointer to heap-allocated buffer" "" { target c++ } .-1 } */ } /* { dg-message "leak of 'p'" } */ void *wrapped_malloc (size_t sz) { return malloc (sz); } void wrapped_free (void *p) { free (p); } void test_wrapped_malloc_and_free (size_t sz) { void *p = wrapped_malloc (100); void *q = wrapped_malloc (sz); __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(\[^\n\r\]*\\)100'" } */ __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'INIT_VAL\\(sz_\[^\n\r\]*\\)'" } */ wrapped_free (p); wrapped_free (q); } void test_use_after_free (void) { // TODO } void test_use_without_check (size_t sz) { char *buf = (char *) wrapped_malloc (sz); /* { dg-message "this call could return NULL" } */ memset (buf, 'x', 4); /* { dg-warning "use of possibly-NULL 'buf' where non-null expected" } */ wrapped_free (buf); } void test_out_of_bounds (size_t sz) { char *buf = (char *) wrapped_malloc (sz); if (!buf) return; memset (buf, 'x', sz); buf[sz] = '\0'; /* { dg-warning "heap-based buffer overflow" } */ wrapped_free (buf); }