1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

Improve JsonLexContext's freeability

Previously, the JSON code didn't have to worry too much about freeing
JsonLexContext, because it was never too long-lived.  With new features
being added for SQL/JSON this is no longer the case.  Add a routine
that knows how to free this struct and apply that to a few places, to
prevent this from becoming problematic.

At the same time, we change the API of makeJsonLexContextCstringLen to
make it receive a pointer to JsonLexContext for callers that want it to
be stack-allocated; it can also be passed as NULL to get the original
behavior of a palloc'ed one.

This also causes an ABI break due to the addition of flags to
JsonLexContext, so we can't easily backpatch it.  AFAICS that's not much
of a problem; apparently some leaks might exist in JSON usage of
text-search, for example via json_to_tsvector, but I haven't seen any
complaints about that.

Per Coverity complaint about datum_to_jsonb_internal().

Discussion: https://postgr.es/m/20230808174110.oq3iymllsv6amkih@alvherre.pgsql
This commit is contained in:
Alvaro Herrera
2023-10-05 10:59:08 +02:00
parent a8a968a821
commit 1c99cde2f3
7 changed files with 153 additions and 86 deletions

View File

@@ -252,13 +252,13 @@ jsonb_typeof(PG_FUNCTION_ARGS)
static inline Datum
jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext)
{
JsonLexContext *lex;
JsonLexContext lex;
JsonbInState state;
JsonSemAction sem;
memset(&state, 0, sizeof(state));
memset(&sem, 0, sizeof(sem));
lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
makeJsonLexContextCstringLen(&lex, json, len, GetDatabaseEncoding(), true);
state.unique_keys = unique_keys;
state.escontext = escontext;
@@ -271,7 +271,7 @@ jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext)
sem.scalar = jsonb_in_scalar;
sem.object_field_start = jsonb_in_object_field_start;
if (!pg_parse_json_or_errsave(lex, &sem, escontext))
if (!pg_parse_json_or_errsave(&lex, &sem, escontext))
return (Datum) 0;
/* after parsing, the item member has the composed jsonb structure */
@@ -755,11 +755,11 @@ datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
case JSONTYPE_JSON:
{
/* parse the json right into the existing result object */
JsonLexContext *lex;
JsonLexContext lex;
JsonSemAction sem;
text *json = DatumGetTextPP(val);
lex = makeJsonLexContext(json, true);
makeJsonLexContext(&lex, json, true);
memset(&sem, 0, sizeof(sem));
@@ -772,7 +772,8 @@ datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
sem.scalar = jsonb_in_scalar;
sem.object_field_start = jsonb_in_object_field_start;
pg_parse_json_or_ereport(lex, &sem);
pg_parse_json_or_ereport(&lex, &sem);
freeJsonLexContext(&lex);
}
break;
case JSONTYPE_JSONB: