https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116060
Bug ID: 116060 Summary: -fanalyzer -fdiagnostics-text-art-charset=unicode replaces typedef'ed type with "int" in some cases Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: azoff at gcc dot gnu.org Target Milestone: --- For some targets, the type int32_t is a simple typedef to "int", others can typedef to for example "long". When running the c-c++-common/analyzer/out-of-bounds-diagram-8.c with glibc (x86_64-linux-gnu), the test passes, but running it with newlib (arm-none-eabi) fails. On newlib, int32_t is typedef'ed to "long int". In the c-c++-common/analyzer/out-of-bounds-diagram-8.c file, the expected output is suppose to contain "int" and not "int32_t". Consider the following small test case (simplified out-of-bounds-diagram-8.c): $ cat foo.c typedef INT32_TYPE int32_t; typedef unsigned long size_t; void test2 (size_t size) { int32_t *buf = (int32_t *) __builtin_malloc (size * sizeof(int32_t)); if (!buf) return; buf[size + 1] = 42; __builtin_free (buf); } $ gcc foo.c -fdiagnostics-plain-output -fanalyzer -fdiagnostics-text-art-charset=unicode -S -o /dev/null -DINT32_TYPE=long foo.c: In function 'test2': foo.c:15:17: warning: heap-based buffer overflow [CWE-122] [-Wanalyzer-out-of-bounds] foo.c:11:30: note: (1) capacity: 'size * 4' bytes foo.c:13:6: note: (2) following 'false' branch (when 'buf' is non-NULL)... foo.c:15:6: note: (3) ...to here foo.c:15:17: note: (4) write of 4 bytes at offset 'size * 4 + 4' exceeds the buffer ┌───────────────────────┐ │write of '(int32_t) 42'│ └───────────────────────┘ │ │ v ┌───────────────────────────────┐ ┌───────────────────────┐ │buffer allocated on heap at (1)│ │ after valid range │ └───────────────────────────────┘ └───────────────────────┘ ├───────────────┬───────────────┤├─────┬──────┤├───────────┬───────────┤ │ │ │ ╭─────────────┴────────────╮ ╭───┴───╮ ╭─────────┴─────────╮ │capacity: 'size * 4' bytes│ │4 bytes│ │overflow of 4 bytes│ ╰──────────────────────────╯ ╰───────╯ ╰───────────────────╯ As can be seen above, the "write of" box mentions "int32_t", and I think this is the correct behavior. $ gcc foo.c -fdiagnostics-plain-output -fanalyzer -fdiagnostics-text-art-charset=unicode -S -o /dev/null -DINT32_TYPE=int foo.c: In function 'test2': foo.c:15:17: warning: heap-based buffer overflow [CWE-122] [-Wanalyzer-out-of-bounds] foo.c:11:30: note: (1) capacity: 'size * 4' bytes foo.c:13:6: note: (2) following 'false' branch (when 'buf' is non-NULL)... foo.c:15:6: note: (3) ...to here foo.c:15:17: note: (4) write of 4 bytes at offset 'size * 4 + 4' exceeds the buffer ┌───────────────────┐ │write of '(int) 42'│ └───────────────────┘ │ │ v ┌───────────────────────────────┐ ┌───────────────────┐ │buffer allocated on heap at (1)│ │ after valid range │ └───────────────────────────────┘ └───────────────────┘ ├───────────────┬───────────────┤├───────┬────────┤├─────────┬─────────┤ │ │ │ ╭─────────────┴────────────╮ ╭───┴───╮ ╭─────────┴─────────╮ │capacity: 'size * 4' bytes│ │4 bytes│ │overflow of 4 bytes│ ╰──────────────────────────╯ ╰───────╯ ╰───────────────────╯ So, by simply changing the base type from "long" to "int", we now suddenly have different content in the "write of" box. Wouldn't it make more sense if the box would always mention "int32_t" as that's the type used in the code? If the current implementation is correct, how can the test case be adapted to PASS when int32_t is not typedef'ed to "int"? Note: out-of-bounds-diagram-8.c is just one of many test cases that fail for newlib/arm-none-eabi.