https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118220
Bug ID: 118220 Summary: Optimization of malloc/free Produces Undefined Behavior Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: jonathan.gruber.jg at gmail dot com Target Milestone: --- Created attachment 59988 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59988&action=edit Preprocessed minimal test case. Optimization of malloc and free calls can produce undefined behavior. Consider this minimal test case (preprocessed version attached): #include <stddef.h> #include <stdint.h> /* Declare these explicitly to avoid including <stdlib.h>. */ extern void *malloc(size_t size); extern void free(void *ptr); #define TOO_LARGE_SIZE ((size_t)PTRDIFF_MAX + 1) /* Request size greater than PTRDIFF_MAX. */ ptrdiff_t test(void) { char *const p = malloc(TOO_LARGE_SIZE); if (!p) { return 0; } char *const q = p + TOO_LARGE_SIZE; const ptrdiff_t ret = q - p; free(p); return ret; } Critically, glibc's malloc unconditionally fails for requests larger than PTRDIFF_MAX, so, with glibc, the above function test would always return 0. However, on all nonzero optimization levels, GCC assumes that the call to malloc will unconditionally succeed, effectively deleting the if-statement. As a result, the function invokes undefined behavior by computing a pointer subtraction whose result overflows (since TOO_LARGE_SIZE > PTRDIFF_MAX). If the if-statement were not deleted, the body of the if-statement would always be executed, thereby avoiding invoking undefined behavior. On all nonzero optimization levels, GCC generates (x86_64, Intel syntax) assembly similar to the following: test: movabs rax, -9223372036854775808 ret Host system type: Arch Linux, x86_64 (with glibc, of course). GCC information: gcc version: 15.0.0 20241227 (experimental). Configured with: ../gcc/configure