v2-0001-WIP-fix-leak-of-scalar-value-on-lex-failure.patch

application/octet-stream

Filename: v2-0001-WIP-fix-leak-of-scalar-value-on-lex-failure.patch
Type: application/octet-stream
Part: 0
Message: Re: pg_parse_json() should not leak token copies on failure

Patch

Format: format-patch
Series: patch v2-0001
Subject: WIP: fix leak of scalar value on lex failure
File+
src/common/jsonapi.c 15 3
From f1883b933e106fc4dd0d3fac5b3d6a2cf3d9167d Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Thu, 25 Apr 2024 15:26:40 -0700
Subject: [PATCH v2] WIP: fix leak of scalar value on lex failure

TODO: field names
---
 src/common/jsonapi.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/common/jsonapi.c b/src/common/jsonapi.c
index a8764302e4..b108b80ad4 100644
--- a/src/common/jsonapi.c
+++ b/src/common/jsonapi.c
@@ -380,10 +380,9 @@ makeJsonLexContextIncremental(JsonLexContext *lex, int encoding,
 	lex->incremental = true;
 	lex->inc_state = palloc0(sizeof(JsonIncrementalState));
 	initStringInfo(&(lex->inc_state->partial_token));
-	lex->pstack = palloc(sizeof(JsonParserStack));
+	lex->pstack = palloc0(sizeof(JsonParserStack));
 	lex->pstack->stack_size = JS_STACK_CHUNK_SIZE;
 	lex->pstack->prediction = palloc(JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN);
-	lex->pstack->pred_index = 0;
 	lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *));
 	lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool));
 	if (need_escapes)
@@ -495,6 +494,8 @@ freeJsonLexContext(JsonLexContext *lex)
 		pfree(lex->pstack->prediction);
 		pfree(lex->pstack->fnames);
 		pfree(lex->pstack->fnull);
+		if (lex->pstack->scalar_val)
+			pfree(lex->pstack->scalar_val);
 		pfree(lex->pstack);
 	}
 
@@ -912,6 +913,13 @@ pg_parse_json_incremental(JsonLexContext *lex,
 						if (sfunc != NULL)
 						{
 							result = (*sfunc) (sem->semstate, pstack->scalar_val, pstack->scalar_tok);
+
+							/*
+							 * Ownership of the token allocation has passed to
+							 * the callback; don't free it later.
+							 */
+							pstack->scalar_val = NULL;
+
 							if (result != JSON_SUCCESS)
 								return result;
 						}
@@ -1040,9 +1048,13 @@ parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
 	/* consume the token */
 	result = json_lex(lex);
 	if (result != JSON_SUCCESS)
+	{
+		if (val)
+			pfree(val);
 		return result;
+	}
 
-	/* invoke the callback */
+	/* invoke the callback, which takes ownership of val */
 	result = (*sfunc) (sem->semstate, val, tok);
 
 	return result;
-- 
2.34.1