gcc 15 "array subscript 0" warning at level -O3

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: gcc 15 "array subscript 0" warning at level -O3
Date: 2025-04-25 17:37:15
Message-ID: 1985046.1745602635@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Whilst poking at Erik Rijkers' nearby report, I found that
Fedora 42's gcc 15.0.1 will produce this complaint if you
select optimization level -O3:

In file included from ../../../../src/include/access/htup_details.h:22,
from pl_exec.c:21:
In function 'assign_simple_var',
inlined from 'exec_set_found' at pl_exec.c:8609:2:
../../../../src/include/varatt.h:230:36: warning: array subscript 0 is outside array bounds of 'char[0]' [-Warray-bounds=]
230 | (((varattrib_1b_e *) (PTR))->va_tag)
| ^
../../../../src/include/varatt.h:94:12: note: in definition of macro 'VARTAG_IS_EXPANDED'
94 | (((tag) & ~1) == VARTAG_EXPANDED_RO)
| ^~~
../../../../src/include/varatt.h:284:57: note: in expansion of macro 'VARTAG_1B_E'
284 | #define VARTAG_EXTERNAL(PTR) VARTAG_1B_E(PTR)
| ^~~~~~~~~~~
../../../../src/include/varatt.h:301:57: note: in expansion of macro 'VARTAG_EXTERNAL'
301 | (VARATT_IS_EXTERNAL(PTR) && !VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR)))
| ^~~~~~~~~~~~~~~
pl_exec.c:8797:17: note: in expansion of macro 'VARATT_IS_EXTERNAL_NON_EXPANDED'
8797 | VARATT_IS_EXTERNAL_NON_EXPANDED(DatumGetPointer(newvalue)))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function 'exec_set_found':
cc1: note: source object is likely at address zero

Buildfarm member serinus has been producing the identical warning for
some time. I'd been ignoring that because it runs "experimental gcc",
but I guess the experiment has leaked out to production distros.

What seems to be happening here is that after inlining
assign_simple_var into exec_set_found, the compiler decides that
"newvalue" might be zero (since it's a BoolGetDatum result),
and then it warns -- in a rather strange way -- about the
potential null dereference. The dereference is not reachable
because of the preceding "var->datatype->typlen == -1" check,
but that's not stopping the optimizer from bitching.

I experimented with modifying exec_set_found thus:

var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
+ Assert(var->datatype->typlen == 1);
assign_simple_var(estate, var, BoolGetDatum(state), false, false);

which should be OK since we're expecting the "found" variable to
be boolean. That does silence the warning, but of course only
in --enable-cassert builds.

Anybody have an idea about how to silence it more effectively?
There are going to be more people seeing this as gcc 15 propagates.

regards, tom lane

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2025-04-25 17:43:03 Re: Allow io_combine_limit up to 1MB
Previous Message Andres Freund 2025-04-25 17:35:30 Re: Allow io_combine_limit up to 1MB