mirror of
https://github.com/postgres/postgres.git
synced 2025-09-11 00:12:06 +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:
@@ -70,7 +70,11 @@ typedef enum JsonParseErrorType
|
||||
* token_terminator and prev_token_terminator point to the character
|
||||
* AFTER the end of the token, i.e. where there would be a nul byte
|
||||
* if we were using nul-terminated strings.
|
||||
*
|
||||
* JSONLEX_FREE_STRUCT/STRVAL are used to drive freeJsonLexContext.
|
||||
*/
|
||||
#define JSONLEX_FREE_STRUCT (1 << 0)
|
||||
#define JSONLEX_FREE_STRVAL (1 << 1)
|
||||
typedef struct JsonLexContext
|
||||
{
|
||||
char *input;
|
||||
@@ -81,6 +85,7 @@ typedef struct JsonLexContext
|
||||
char *prev_token_terminator;
|
||||
JsonTokenType token_type;
|
||||
int lex_level;
|
||||
bits32 flags;
|
||||
int line_number; /* line number, starting from 1 */
|
||||
char *line_start; /* where that line starts within input */
|
||||
StringInfo strval;
|
||||
@@ -151,15 +156,26 @@ extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex,
|
||||
int *elements);
|
||||
|
||||
/*
|
||||
* constructor for JsonLexContext, with or without strval element.
|
||||
* If supplied, the strval element will contain a de-escaped version of
|
||||
* the lexeme. However, doing this imposes a performance penalty, so
|
||||
* it should be avoided if the de-escaped lexeme is not required.
|
||||
* initializer for JsonLexContext.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 the caller is
|
||||
* responsible for freeing the returned struct, either by calling
|
||||
* freeJsonLexContext() or (in backend environment) via memory context
|
||||
* cleanup.
|
||||
*/
|
||||
extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
|
||||
extern JsonLexContext *makeJsonLexContextCstringLen(JsonLexContext *lex,
|
||||
char *json,
|
||||
int len,
|
||||
int encoding,
|
||||
bool need_escapes);
|
||||
extern void freeJsonLexContext(JsonLexContext *lex);
|
||||
|
||||
/* lex one token */
|
||||
extern JsonParseErrorType json_lex(JsonLexContext *lex);
|
||||
|
@@ -36,8 +36,8 @@ typedef void (*JsonIterateStringValuesAction) (void *state, char *elem_value, in
|
||||
/* an action that will be applied to each value in transform_json(b)_values functions */
|
||||
typedef text *(*JsonTransformStringValuesAction) (void *state, char *elem_value, int elem_len);
|
||||
|
||||
/* build a JsonLexContext from a text datum */
|
||||
extern JsonLexContext *makeJsonLexContext(text *json, bool need_escapes);
|
||||
/* build a JsonLexContext from a text datum; see also freeJsonLexContext */
|
||||
extern JsonLexContext *makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes);
|
||||
|
||||
/* try to parse json, and errsave(escontext) on failure */
|
||||
extern bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem,
|
||||
|
Reference in New Issue
Block a user