analyzer: fix further overzealous state purging [PR108733]
PR analyzer/108733 reports various false positives in qemu from -Wanalyzer-use-of-uninitialized-value with __attribute__((cleanup)) at -O1 and above. Root cause is that the state-purging code was failing to treat: _25 = MEM[(void * *)&val]; as a usage of "val", leading to it erroneously purging the initialization of "val" along an execution path that didn't otherwise use "val", apart from the __attribute__((cleanup)). Fixed thusly. Integration testing on the patch show this change in the number of diagnostics: -Wanalyzer-use-of-uninitialized-value coreutils-9.1: 18 -> 16 (-2) qemu-7.2.0: 87 -> 80 (-7) where all that I investigated appear to have been false positives, hence an improvement. gcc/analyzer/ChangeLog: PR analyzer/108733 * state-purge.cc (get_candidate_for_purging): Add ADDR_EXPR and MEM_REF. gcc/testsuite/ChangeLog: PR analyzer/108733 * gcc.dg/analyzer/torture/uninit-pr108733.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
10827a92f1
commit
125b57aa67
2 changed files with 67 additions and 0 deletions
|
@ -63,6 +63,8 @@ get_candidate_for_purging (tree node)
|
|||
default:
|
||||
return NULL_TREE;
|
||||
|
||||
case ADDR_EXPR:
|
||||
case MEM_REF:
|
||||
case COMPONENT_REF:
|
||||
iter = TREE_OPERAND (iter, 0);
|
||||
continue;
|
||||
|
|
65
gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr108733.c
Normal file
65
gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr108733.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned char __uint8_t;
|
||||
typedef __uint8_t uint8_t;
|
||||
typedef char gchar;
|
||||
typedef void* gpointer;
|
||||
|
||||
extern void g_free(gpointer mem);
|
||||
extern gchar* g_strdup(const gchar* str) __attribute__((__malloc__));
|
||||
|
||||
static inline void
|
||||
g_autoptr_cleanup_generic_gfree(void* p)
|
||||
{
|
||||
void** pp = (void**)p;
|
||||
g_free(*pp); /* { dg-bogus "use of uninitialized value" } */
|
||||
}
|
||||
|
||||
typedef struct Object Object;
|
||||
|
||||
void
|
||||
error_setg_internal(const char* fmt,
|
||||
...) __attribute__((__format__(gnu_printf, 1, 2)));
|
||||
void
|
||||
visit_type_str(const char* name, char** obj);
|
||||
typedef struct SpaprMachineState SpaprMachineState;
|
||||
|
||||
extern uint8_t
|
||||
spapr_get_cap(SpaprMachineState* spapr, int cap);
|
||||
|
||||
typedef struct SpaprCapPossible
|
||||
{
|
||||
int num;
|
||||
/* [...snip...] */
|
||||
const char* vals[];
|
||||
} SpaprCapPossible;
|
||||
|
||||
typedef struct SpaprCapabilityInfo
|
||||
{
|
||||
const char* name;
|
||||
/* [...snip...] */
|
||||
int index;
|
||||
/* [...snip...] */
|
||||
SpaprCapPossible* possible;
|
||||
/* [...snip...] */
|
||||
} SpaprCapabilityInfo;
|
||||
|
||||
void
|
||||
spapr_cap_get_string(SpaprMachineState* spapr,
|
||||
const char* name,
|
||||
SpaprCapabilityInfo* cap)
|
||||
{
|
||||
__attribute__((cleanup(g_autoptr_cleanup_generic_gfree))) char* val = NULL;
|
||||
uint8_t value = spapr_get_cap(spapr, cap->index);
|
||||
|
||||
if (value >= cap->possible->num) {
|
||||
error_setg_internal("Invalid value (%d) for cap-%s",
|
||||
value,
|
||||
cap->name);
|
||||
return;
|
||||
}
|
||||
|
||||
val = g_strdup(cap->possible->vals[value]);
|
||||
|
||||
visit_type_str(name, &val);
|
||||
}
|
Loading…
Add table
Reference in a new issue