https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123420

            Bug ID: 123420
           Summary: incorrect -Wfree-nonheap-object
           Product: gcc
           Version: 15.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stefan11111 at shitposting dot expert
  Target Milestone: ---

This bug happens with tinyX.

$ cat gcc-bug-2.c
/* Version with original tinyX types */

#include <stdlib.h>

#define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)

typedef struct _Region RegionRec, *RegionPtr;

typedef struct _Box {
    short x1, y1, x2, y2;
} BoxRec;

typedef struct _RegData {
    long    size;
    long    numRects;
/*  BoxRec  rects[size];   in memory but not explicitly declared */
} RegDataRec, *RegDataPtr;

struct _Region {
    BoxRec  extents;
    RegDataPtr data;
};

/* static or not doesn't matter */
static RegDataRec miBrokenData = {0, 0};

int main()
{
    /* Original tinyX bug */
    RegionRec region = {{0, 0, 0, 0}, &miBrokenData};
    xfreeData(&region);
}

Compile:
$ gcc gcc-bug-2.c -o gcc-bug -O
gcc-bug-2.c: In function 'main':
gcc-bug-2.c:5:62: warning: 'free' called on unallocated object 'miBrokenData'
[-Wfree-nonheap-object]
    5 | #define xfreeData(reg) if ((reg)->data && (reg)->data->size)
free((reg)->data)
      |                                                             
^~~~~~~~~~~~~~~~~
gcc-bug-2.c:31:5: note: in expansion of macro 'xfreeData'
   31 |     xfreeData(&region);
      |     ^~~~~~~~~
gcc-bug-2.c:25:19: note: declared here
   25 | static RegDataRec miBrokenData = {0, 0};
      |                   ^~~~~~~~~~~


$ cat gcc-bug-3.c
/* Simplified version */

#include <stdlib.h>

#define Free(data) if ((data) && (data)->size) free(data)

struct foo {
    int size;
};

/* static or not doesn't matter */
static struct foo foo = {0};

int main()
{
    Free(&foo);
}

$ gcc gcc-bug-3.c -o gcc-bug
gcc-bug-3.c: In function 'main':
gcc-bug-3.c:5:48: warning: 'free' called on unallocated object 'foo'
[-Wfree-nonheap-object]
    5 | #define Free(data) if ((data) && (data)->size) free(data)
      |                                                ^~~~~~~~~~
gcc-bug-3.c:16:5: note: in expansion of macro 'Free'
   16 |     Free(&foo);
      |     ^~~~
gcc-bug-3.c:12:19: note: declared here
   12 | static struct foo foo = {0};
      |                   ^~~


In both cases, free is never called, since size is 0.

Also, even with -O3, the branch does not get optimized out:
$ objdump -d gcc-bug | less
<snip>
0000000000001050 <main>:
    1050:       8b 0d be 2f 00 00       mov    ecx,DWORD PTR [rip+0x2fbe]      
 # 4014 <foo>
    1056:       85 c9                   test   ecx,ecx
    1058:       75 03                   jne    105d <main+0xd>
    105a:       31 c0                   xor    eax,eax
    105c:       c3                      ret
    105d:       50                      push   rax
    105e:       48 8d 3d af 2f 00 00    lea    rdi,[rip+0x2faf]        # 4014
<foo>
    1065:       e8 c6 ff ff ff          call   1030 <free@plt>
    106a:       31 c0                   xor    eax,eax
    106c:       5a                      pop    rdx
    106d:       c3                      ret
    106e:       66 90                   xchg   ax,ax
<snip>
  • [Bug c/123420] New: inc... stefan11111 at shitposting dot expert via Gcc-bugs

Reply via email to