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

Reply via email to