@@ -161,6 +161,7 @@ struct JsonParserStack
161
161
*/
162
162
struct JsonIncrementalState
163
163
{
164
+ bool started ;
164
165
bool is_last_chunk ;
165
166
bool partial_completed ;
166
167
jsonapi_StrValType partial_token ;
@@ -280,6 +281,7 @@ static JsonParseErrorType parse_array_element(JsonLexContext *lex, const JsonSem
280
281
static JsonParseErrorType parse_array (JsonLexContext * lex , const JsonSemAction * sem );
281
282
static JsonParseErrorType report_parse_error (JsonParseContext ctx , JsonLexContext * lex );
282
283
static bool allocate_incremental_state (JsonLexContext * lex );
284
+ static inline void set_fname (JsonLexContext * lex , char * fname );
283
285
284
286
/* the null action object used for pure validation */
285
287
const JsonSemAction nullSemAction =
@@ -437,7 +439,7 @@ allocate_incremental_state(JsonLexContext *lex)
437
439
* fnull ;
438
440
439
441
lex -> inc_state = ALLOC0 (sizeof (JsonIncrementalState ));
440
- pstack = ALLOC (sizeof (JsonParserStack ));
442
+ pstack = ALLOC0 (sizeof (JsonParserStack ));
441
443
prediction = ALLOC (JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN );
442
444
fnames = ALLOC (JS_STACK_CHUNK_SIZE * sizeof (char * ));
443
445
fnull = ALLOC (JS_STACK_CHUNK_SIZE * sizeof (bool ));
@@ -464,10 +466,17 @@ allocate_incremental_state(JsonLexContext *lex)
464
466
lex -> pstack = pstack ;
465
467
lex -> pstack -> stack_size = JS_STACK_CHUNK_SIZE ;
466
468
lex -> pstack -> prediction = prediction ;
467
- lex -> pstack -> pred_index = 0 ;
468
469
lex -> pstack -> fnames = fnames ;
469
470
lex -> pstack -> fnull = fnull ;
470
471
472
+ /*
473
+ * fnames between 0 and lex_level must always be defined so that
474
+ * freeJsonLexContext() can handle them safely. inc/dec_lex_level() handle
475
+ * the rest.
476
+ */
477
+ Assert (lex -> lex_level == 0 );
478
+ lex -> pstack -> fnames [0 ] = NULL ;
479
+
471
480
lex -> incremental = true;
472
481
return true;
473
482
}
@@ -530,6 +539,25 @@ makeJsonLexContextIncremental(JsonLexContext *lex, int encoding,
530
539
return lex ;
531
540
}
532
541
542
+ void
543
+ setJsonLexContextOwnsTokens (JsonLexContext * lex , bool owned_by_context )
544
+ {
545
+ if (lex -> incremental && lex -> inc_state -> started )
546
+ {
547
+ /*
548
+ * Switching this flag after parsing has already started is a
549
+ * programming error.
550
+ */
551
+ Assert (false);
552
+ return ;
553
+ }
554
+
555
+ if (owned_by_context )
556
+ lex -> flags |= JSONLEX_CTX_OWNS_TOKENS ;
557
+ else
558
+ lex -> flags &= ~JSONLEX_CTX_OWNS_TOKENS ;
559
+ }
560
+
533
561
static inline bool
534
562
inc_lex_level (JsonLexContext * lex )
535
563
{
@@ -569,12 +597,23 @@ inc_lex_level(JsonLexContext *lex)
569
597
}
570
598
571
599
lex -> lex_level += 1 ;
600
+
601
+ if (lex -> incremental )
602
+ {
603
+ /*
604
+ * Ensure freeJsonLexContext() remains safe even if no fname is
605
+ * assigned at this level.
606
+ */
607
+ lex -> pstack -> fnames [lex -> lex_level ] = NULL ;
608
+ }
609
+
572
610
return true;
573
611
}
574
612
575
613
static inline void
576
614
dec_lex_level (JsonLexContext * lex )
577
615
{
616
+ set_fname (lex , NULL ); /* free the current level's fname, if needed */
578
617
lex -> lex_level -= 1 ;
579
618
}
580
619
@@ -608,6 +647,15 @@ have_prediction(JsonParserStack *pstack)
608
647
static inline void
609
648
set_fname (JsonLexContext * lex , char * fname )
610
649
{
650
+ if (lex -> flags & JSONLEX_CTX_OWNS_TOKENS )
651
+ {
652
+ /*
653
+ * Don't leak prior fnames. If one hasn't been assigned yet,
654
+ * inc_lex_level ensured that it's NULL (and therefore safe to free).
655
+ */
656
+ FREE (lex -> pstack -> fnames [lex -> lex_level ]);
657
+ }
658
+
611
659
lex -> pstack -> fnames [lex -> lex_level ] = fname ;
612
660
}
613
661
@@ -655,8 +703,19 @@ freeJsonLexContext(JsonLexContext *lex)
655
703
jsonapi_termStringInfo (& lex -> inc_state -> partial_token );
656
704
FREE (lex -> inc_state );
657
705
FREE (lex -> pstack -> prediction );
706
+
707
+ if (lex -> flags & JSONLEX_CTX_OWNS_TOKENS )
708
+ {
709
+ int i ;
710
+
711
+ /* Clean up any tokens that were left behind. */
712
+ for (i = 0 ; i <= lex -> lex_level ; i ++ )
713
+ FREE (lex -> pstack -> fnames [i ]);
714
+ }
715
+
658
716
FREE (lex -> pstack -> fnames );
659
717
FREE (lex -> pstack -> fnull );
718
+ FREE (lex -> pstack -> scalar_val );
660
719
FREE (lex -> pstack );
661
720
}
662
721
@@ -826,6 +885,7 @@ pg_parse_json_incremental(JsonLexContext *lex,
826
885
lex -> input = lex -> token_terminator = lex -> line_start = json ;
827
886
lex -> input_length = len ;
828
887
lex -> inc_state -> is_last_chunk = is_last ;
888
+ lex -> inc_state -> started = true;
829
889
830
890
/* get the initial token */
831
891
result = json_lex (lex );
@@ -1086,6 +1146,17 @@ pg_parse_json_incremental(JsonLexContext *lex,
1086
1146
if (sfunc != NULL )
1087
1147
{
1088
1148
result = (* sfunc ) (sem -> semstate , pstack -> scalar_val , pstack -> scalar_tok );
1149
+
1150
+ /*
1151
+ * Either ownership of the token passed to the
1152
+ * callback, or we need to free it now. Either
1153
+ * way, clear our pointer to it so it doesn't get
1154
+ * freed in the future.
1155
+ */
1156
+ if (lex -> flags & JSONLEX_CTX_OWNS_TOKENS )
1157
+ FREE (pstack -> scalar_val );
1158
+ pstack -> scalar_val = NULL ;
1159
+
1089
1160
if (result != JSON_SUCCESS )
1090
1161
return result ;
1091
1162
}
@@ -1221,11 +1292,17 @@ parse_scalar(JsonLexContext *lex, const JsonSemAction *sem)
1221
1292
/* consume the token */
1222
1293
result = json_lex (lex );
1223
1294
if (result != JSON_SUCCESS )
1295
+ {
1296
+ FREE (val );
1224
1297
return result ;
1298
+ }
1225
1299
1226
- /* invoke the callback */
1300
+ /* invoke the callback, which may take ownership of val */
1227
1301
result = (* sfunc ) (sem -> semstate , val , tok );
1228
1302
1303
+ if (lex -> flags & JSONLEX_CTX_OWNS_TOKENS )
1304
+ FREE (val );
1305
+
1229
1306
return result ;
1230
1307
}
1231
1308
@@ -1238,7 +1315,7 @@ parse_object_field(JsonLexContext *lex, const JsonSemAction *sem)
1238
1315
* generally call a field name a "key".
1239
1316
*/
1240
1317
1241
- char * fname = NULL ; /* keep compiler quiet */
1318
+ char * fname = NULL ;
1242
1319
json_ofield_action ostart = sem -> object_field_start ;
1243
1320
json_ofield_action oend = sem -> object_field_end ;
1244
1321
bool isnull ;
@@ -1255,11 +1332,17 @@ parse_object_field(JsonLexContext *lex, const JsonSemAction *sem)
1255
1332
}
1256
1333
result = json_lex (lex );
1257
1334
if (result != JSON_SUCCESS )
1335
+ {
1336
+ FREE (fname );
1258
1337
return result ;
1338
+ }
1259
1339
1260
1340
result = lex_expect (JSON_PARSE_OBJECT_LABEL , lex , JSON_TOKEN_COLON );
1261
1341
if (result != JSON_SUCCESS )
1342
+ {
1343
+ FREE (fname );
1262
1344
return result ;
1345
+ }
1263
1346
1264
1347
tok = lex_peek (lex );
1265
1348
isnull = tok == JSON_TOKEN_NULL ;
@@ -1268,7 +1351,7 @@ parse_object_field(JsonLexContext *lex, const JsonSemAction *sem)
1268
1351
{
1269
1352
result = (* ostart ) (sem -> semstate , fname , isnull );
1270
1353
if (result != JSON_SUCCESS )
1271
- return result ;
1354
+ goto ofield_cleanup ;
1272
1355
}
1273
1356
1274
1357
switch (tok )
@@ -1283,16 +1366,19 @@ parse_object_field(JsonLexContext *lex, const JsonSemAction *sem)
1283
1366
result = parse_scalar (lex , sem );
1284
1367
}
1285
1368
if (result != JSON_SUCCESS )
1286
- return result ;
1369
+ goto ofield_cleanup ;
1287
1370
1288
1371
if (oend != NULL )
1289
1372
{
1290
1373
result = (* oend ) (sem -> semstate , fname , isnull );
1291
1374
if (result != JSON_SUCCESS )
1292
- return result ;
1375
+ goto ofield_cleanup ;
1293
1376
}
1294
1377
1295
- return JSON_SUCCESS ;
1378
+ ofield_cleanup :
1379
+ if (lex -> flags & JSONLEX_CTX_OWNS_TOKENS )
1380
+ FREE (fname );
1381
+ return result ;
1296
1382
}
1297
1383
1298
1384
static JsonParseErrorType
0 commit comments