mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +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:
@ -135,26 +135,62 @@ IsValidJsonNumber(const char *str, int len)
|
||||
|
||||
/*
|
||||
* makeJsonLexContextCstringLen
|
||||
* Initialize the given JsonLexContext object, or create one
|
||||
*
|
||||
* lex constructor, with or without StringInfo object for de-escaped lexemes.
|
||||
* If a valid 'lex' pointer is given, it is initialized. This can
|
||||
* be used for stack-allocated structs, saving overhead. If NULL is
|
||||
* given, a new struct is allocated.
|
||||
*
|
||||
* Without is better as it makes the processing faster, so only make one
|
||||
* if really required.
|
||||
* If need_escapes is true, ->strval stores the unescaped lexemes.
|
||||
* Unescaping is expensive, so only request it when necessary.
|
||||
*
|
||||
* If need_escapes is true or lex was given as NULL, then caller is
|
||||
* responsible for freeing the returned struct, either by calling
|
||||
* freeJsonLexContext() or (in backend environment) via memory context
|
||||
* cleanup.
|
||||
*/
|
||||
JsonLexContext *
|
||||
makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
|
||||
makeJsonLexContextCstringLen(JsonLexContext *lex, char *json,
|
||||
int len, int encoding, bool need_escapes)
|
||||
{
|
||||
JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
|
||||
if (lex == NULL)
|
||||
{
|
||||
lex = palloc0(sizeof(JsonLexContext));
|
||||
lex->flags |= JSONLEX_FREE_STRUCT;
|
||||
}
|
||||
else
|
||||
memset(lex, 0, sizeof(JsonLexContext));
|
||||
|
||||
lex->input = lex->token_terminator = lex->line_start = json;
|
||||
lex->line_number = 1;
|
||||
lex->input_length = len;
|
||||
lex->input_encoding = encoding;
|
||||
if (need_escapes)
|
||||
{
|
||||
lex->strval = makeStringInfo();
|
||||
lex->flags |= JSONLEX_FREE_STRVAL;
|
||||
}
|
||||
|
||||
return lex;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free memory in a JsonLexContext. There's no need for this if a *lex
|
||||
* pointer was given when the object was made and need_escapes was false,
|
||||
* or (in backend environment) a memory context delete/reset is imminent.
|
||||
*/
|
||||
void
|
||||
freeJsonLexContext(JsonLexContext *lex)
|
||||
{
|
||||
if (lex->flags & JSONLEX_FREE_STRVAL)
|
||||
{
|
||||
pfree(lex->strval->data);
|
||||
pfree(lex->strval);
|
||||
}
|
||||
if (lex->flags & JSONLEX_FREE_STRUCT)
|
||||
pfree(lex);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_parse_json
|
||||
*
|
||||
|
Reference in New Issue
Block a user