From: David Malcolm Date: Thu, 29 Oct 2020 00:10:39 +0000 (-0400) Subject: analyzer: fix false leak diagnostic on offsets from malloc [PR97608] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a9af271275f4893e28c789c8f1964025694eda1;p=gcc.git analyzer: fix false leak diagnostic on offsets from malloc [PR97608] gcc/analyzer/ChangeLog: PR analyzer/97608 * region-model-reachability.cc (reachable_regions::handle_sval): Operands of reachable reversible operations are reachable. gcc/testsuite/ChangeLog: PR analyzer/97608 * gcc.dg/analyzer/malloc-1.c (test_42d): New. * gcc.dg/analyzer/pr97608.c: New test. --- diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc index 52525e1144b..f6f25cc9177 100644 --- a/gcc/analyzer/region-model-reachability.cc +++ b/gcc/analyzer/region-model-reachability.cc @@ -181,6 +181,40 @@ reachable_regions::handle_sval (const svalue *sval) } if (const svalue *cast = sval->maybe_undo_cast ()) handle_sval (cast); + + /* If SVAL is the result of a reversible operation, then the operands + are reachable. */ + switch (sval->get_kind ()) + { + default: + break; + case SK_UNARYOP: + { + const unaryop_svalue *unaryop_sval = (const unaryop_svalue *)sval; + switch (unaryop_sval->get_op ()) + { + default: + break; + case NEGATE_EXPR: + handle_sval (unaryop_sval->get_arg ()); + break; + } + } + break; + case SK_BINOP: + { + const binop_svalue *binop_sval = (const binop_svalue *)sval; + switch (binop_sval->get_op ()) + { + default: + break; + case POINTER_PLUS_EXPR: + handle_sval (binop_sval->get_arg0 ()); + handle_sval (binop_sval->get_arg1 ()); + break; + } + } + } } /* Add SVAL. If it is a pointer, add the pointed-to region. diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c index c3e1330ec6a..38ce1a52987 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c @@ -509,6 +509,14 @@ void test_42c (void) free (q - 64); /* this is probably OK. */ } /* { dg-bogus "leak of 'p'" } */ +void * +test_42d (void) +{ + void *p = malloc (1024); + void *q = p + 64; + return q; +} /* { dg-bogus "leak of 'p'" } */ + #if 0 void test_31 (void *p) { diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97608.c b/gcc/testsuite/gcc.dg/analyzer/pr97608.c new file mode 100644 index 00000000000..a2bc1301097 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr97608.c @@ -0,0 +1,17 @@ +#include + +void *f (void) +{ + void *p = malloc (8); + if (p == NULL) + abort (); + return (void *) ((char *) p + 0); +} + +void *g (void) +{ + void *p = malloc (8); + if (p == NULL) + abort (); + return (void *) ((char *) p + 1); +}