Subject: jsonapi: scary new warnings with LTO enabled

From: Tom Lane <[email-masked]>
Date: Wed, 16 Apr 2025 17:42:41 -0400

I noticed some new warnings from buildfarm member chafer,
which I'm able to reproduce locally on a Fedora 41 box
by building with "meson setup build -Db_lto=true":

ninja: Entering directory `build'
[1515/2472] Linking target src/interfaces/libpq/libpq.so.5.18
In function 'freeJsonLexContext',
    inlined from 'freeJsonLexContext' at ../src/common/jsonapi.c:688:1,
    inlined from 'handle_oauth_sasl_error' at ../src/interfaces/libpq/fe-auth-oauth.c:547:2:
../src/common/jsonapi.c:723:17: warning: 'free' called on unallocated object 'lex' [-Wfree-nonheap-object]
  723 |                 FREE(lex);
      |                 ^
../src/interfaces/libpq/fe-auth-oauth.c: In function 'handle_oauth_sasl_error':
../src/interfaces/libpq/fe-auth-oauth.c:479:24: note: declared here
  479 |         JsonLexContext lex = {0};
      |                        ^
[2407/2472] Linking target src/test/modules/test_json_parser/test_json_parser_incremental_shlib
In function 'freeJsonLexContext',
    inlined from 'freeJsonLexContext' at ../src/common/jsonapi.c:688:1,
    inlined from 'main' at ../src/test/modules/test_json_parser/test_json_parser_incremental.c:198:2:
../src/common/jsonapi.c:723:17: warning: 'free' called on unallocated object 'lex' [-Wfree-nonheap-object]
  723 |                 FREE(lex);
      |                 ^
../src/test/modules/test_json_parser/test_json_parser_incremental.c: In function 'main':
../src/test/modules/test_json_parser/test_json_parser_incremental.c:87:24: note: declared here
   87 |         JsonLexContext lex;
      |                        ^
[2426/2472] Linking target src/test/modules/test_json_parser/test_json_parser_incremental
In function 'pg_free',
    inlined from 'pfree' at ../src/common/fe_memutils.c:135:2,
    inlined from 'freeJsonLexContext' at ../src/common/jsonapi.c:723:3,
    inlined from 'freeJsonLexContext' at ../src/common/jsonapi.c:688:1,
    inlined from 'main' at ../src/test/modules/test_json_parser/test_json_parser_incremental.c:198:2:
../src/common/fe_memutils.c:107:9: warning: 'free' called on unallocated object 'lex' [-Wfree-nonheap-object]
  107 |         free(ptr);
      |         ^
../src/test/modules/test_json_parser/test_json_parser_incremental.c: In function 'main':
../src/test/modules/test_json_parser/test_json_parser_incremental.c:87:24: note: declared here
   87 |         JsonLexContext lex;
      |                        ^

AFAICT there is no actual bug here: the FREE() call is reached only if
the JSONLEX_FREE_STRUCT flag is set, which it should not be for these
call sites.  But evidently the LTO optimizer is not quite smart enough
to realize that.

It seems fairly dangerous to ignore -Wfree-nonheap-object warnings.
I feel like we ought to move to prevent these somehow.  I'm not sure
how other than giving up on stack allocation of JsonLexContexts,
though, especially if we consider the jsonapi API frozen.  But seeing
that there are only three such call sites and none of them seem in the
least performance-critical, maybe we should just do that?

			regards, tom lane

---

From: Ranier Vilela <[email-masked]>
Date: Wed, 16 Apr 2025 19:17:34 -0300

Em qua., 16 de abr. de 2025 às 18:42, Tom Lane <[email-masked]> escreveu:

>     inlined from 'handle_oauth_sasl_error' at
> ../src/interfaces/libpq/fe-auth-oauth.c:547:2:
> [2407/2472] Linking target
> src/test/modules/test_json_parser/test_json_parser_incremental_shlib
>     inlined from 'main' at
> ../src/test/modules/test_json_parser/test_json_parser_incremental.c:198:2:
> [2426/2472] Linking target
> src/test/modules/test_json_parser/test_json_parser_incremental
> In function 'pg_free',
>     inlined from 'main' at
> ../src/test/modules/test_json_parser/test_json_parser_incremental.c:198:2:
> call sites.

See the function *makeJsonLexContextCstringLen* (line 400)
The JSONLEX_FREE_STRUCT  is enabled, no?

fe-auth-oauth.c (line 507)
makeJsonLexContextCstringLen(&lex, msg, msglen, PG_UTF8, true);

Worst, on a second call, with lex not NULL, the flags is reseted
and the struct will no longer be released?

best regards,
Ranier Vilela