Viewing file: unknown-fns.c (2.67 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* Verify that the analyzer correctly purges state when it sees a call to an unknown function. */
#include <stdlib.h>
/* Verify fix for false-positive when checking for CVE-2005-1689. */
typedef struct _krb5_data { char *data; } krb5_data;
extern void krb5_read_message(krb5_data *buf);
void test_1 (krb5_data inbuf) { free(inbuf.data); krb5_read_message(&inbuf); free(inbuf.data); /* { dg-bogus "double-'free'" } */ }
/* Verify that __pure__ functions are treated as not having side-effects. */
extern int called_by_test_1a (void *) __attribute__ ((__pure__)); void test_1a (krb5_data inbuf) { free (inbuf.data); called_by_test_1a (&inbuf); free (inbuf.data); /* { dg-warning "double-'free'" } */ }
/* Verify that global pointers can be affected by an unknown function. */
void *global_ptr; extern void unknown_side_effects (void);
void test_2 (void) { free (global_ptr); unknown_side_effects (); free (global_ptr); }
extern void called_by_test_3 (void *);
void test_3a (void) { void *ptr = malloc (1024); called_by_test_3 (ptr); } /* { dg-bogus "leak" } */
void test_3b (void) { krb5_data k; k.data = malloc (1024); called_by_test_3 (&k); } /* { dg-bogus "leak" } */
/* Verify that we traverse the graph of regions that are reachable from the call. */
struct foo { struct foo *next; int *ptr; };
/* First, without a call to an unknown function. */
void test_4a (void) { struct foo node_a; struct foo node_b; node_a.next = &node_b; node_b.ptr = malloc (sizeof (int)); global_ptr = &node_a; *node_b.ptr = 42; /* { dg-warning "possibly-NULL" "possibly-NULL" } */ /* Although there's a chain of pointers to the allocation, pointed to by global_ptr, the chain goes through the stack frame and thus there's a leak when it is popped. */ } /* { dg-warning "leak of 'node_b.ptr'" } */
/* With a call to an unknown function. */
void test_4b (void) { struct foo node_a; struct foo node_b; node_a.next = &node_b; node_b.ptr = malloc (sizeof (int)); global_ptr = &node_a; unknown_side_effects (); /* everything potentially visible through global_ptr. */ *node_b.ptr = 42; /* { dg-bogus "possibly-NULL" } */ } /* { dg-bogus "leak" } */
extern void called_by_test_5 (const char *); void test_5 (void) { called_by_test_5 ("???"); }
extern void called_by_test_6 (const struct foo *); void test_6 (void) { struct foo node; node.next = NULL; node.ptr = malloc (sizeof (int));
/* This is a const ptr, but struct foo's ptr is non-const, so we ought to assume it could be written to. */ called_by_test_6 (&node); } /* { dg-bogus "leak" } */
/* TODO: things reachable from "outside" i.e. by params to caller to entrypoint. */
|