Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * jsonapi.c
4 : : * JSON parser and lexer interfaces
5 : : *
6 : : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : * IDENTIFICATION
10 : : * src/common/jsonapi.c
11 : : *
12 : : *-------------------------------------------------------------------------
13 : : */
14 : : #ifndef FRONTEND
15 : : #include "postgres.h"
16 : : #else
17 : : #include "postgres_fe.h"
18 : : #endif
19 : :
20 : : #include "common/jsonapi.h"
21 : : #include "mb/pg_wchar.h"
22 : : #include "port/pg_lfind.h"
23 : :
24 : : #ifndef FRONTEND
25 : : #include "miscadmin.h"
26 : : #endif
27 : :
28 : : /*
29 : : * The context of the parser is maintained by the recursive descent
30 : : * mechanism, but is passed explicitly to the error reporting routine
31 : : * for better diagnostics.
32 : : */
33 : : typedef enum /* contexts of JSON parser */
34 : : {
35 : : JSON_PARSE_VALUE, /* expecting a value */
36 : : JSON_PARSE_STRING, /* expecting a string (for a field name) */
37 : : JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
38 : : JSON_PARSE_ARRAY_NEXT, /* saw array element, expecting ',' or ']' */
39 : : JSON_PARSE_OBJECT_START, /* saw '{', expecting label or '}' */
40 : : JSON_PARSE_OBJECT_LABEL, /* saw object label, expecting ':' */
41 : : JSON_PARSE_OBJECT_NEXT, /* saw object value, expecting ',' or '}' */
42 : : JSON_PARSE_OBJECT_COMMA, /* saw object ',', expecting next label */
43 : : JSON_PARSE_END, /* saw the end of a document, expect nothing */
44 : : } JsonParseContext;
45 : :
46 : : /*
47 : : * Setup for table-driven parser.
48 : : * These enums need to be separate from the JsonTokenType and from each other
49 : : * so we can have all of them on the prediction stack, which consists of
50 : : * tokens, non-terminals, and semantic action markers.
51 : : */
52 : :
53 : : typedef enum
54 : : {
55 : : JSON_NT_JSON = 32,
56 : : JSON_NT_ARRAY_ELEMENTS,
57 : : JSON_NT_MORE_ARRAY_ELEMENTS,
58 : : JSON_NT_KEY_PAIRS,
59 : : JSON_NT_MORE_KEY_PAIRS,
60 : : } JsonNonTerminal;
61 : :
62 : : typedef enum
63 : : {
64 : : JSON_SEM_OSTART = 64,
65 : : JSON_SEM_OEND,
66 : : JSON_SEM_ASTART,
67 : : JSON_SEM_AEND,
68 : : JSON_SEM_OFIELD_INIT,
69 : : JSON_SEM_OFIELD_START,
70 : : JSON_SEM_OFIELD_END,
71 : : JSON_SEM_AELEM_START,
72 : : JSON_SEM_AELEM_END,
73 : : JSON_SEM_SCALAR_INIT,
74 : : JSON_SEM_SCALAR_CALL,
75 : : } JsonParserSem;
76 : :
77 : : /*
78 : : * struct containing the 3 stacks used in non-recursive parsing,
79 : : * and the token and value for scalars that need to be preserved
80 : : * across calls.
81 : : *
82 : : * typedef appears in jsonapi.h
83 : : */
84 : : struct JsonParserStack
85 : : {
86 : : int stack_size;
87 : : char *prediction;
88 : : int pred_index;
89 : : /* these two are indexed by lex_level */
90 : : char **fnames;
91 : : bool *fnull;
92 : : JsonTokenType scalar_tok;
93 : : char *scalar_val;
94 : : };
95 : :
96 : : /*
97 : : * struct containing state used when there is a possible partial token at the
98 : : * end of a json chunk when we are doing incremental parsing.
99 : : *
100 : : * typedef appears in jsonapi.h
101 : : */
102 : : struct JsonIncrementalState
103 : : {
104 : : bool is_last_chunk;
105 : : bool partial_completed;
106 : : StringInfoData partial_token;
107 : : };
108 : :
109 : : /*
110 : : * constants and macros used in the nonrecursive parser
111 : : */
112 : : #define JSON_NUM_TERMINALS 13
113 : : #define JSON_NUM_NONTERMINALS 5
114 : : #define JSON_NT_OFFSET JSON_NT_JSON
115 : : /* for indexing the table */
116 : : #define OFS(NT) (NT) - JSON_NT_OFFSET
117 : : /* classify items we get off the stack */
118 : : #define IS_SEM(x) ((x) & 0x40)
119 : : #define IS_NT(x) ((x) & 0x20)
120 : :
121 : : /*
122 : : * These productions are stored in reverse order right to left so that when
123 : : * they are pushed on the stack what we expect next is at the top of the stack.
124 : : */
125 : : static char JSON_PROD_EPSILON[] = {0}; /* epsilon - an empty production */
126 : :
127 : : /* JSON -> string */
128 : : static char JSON_PROD_SCALAR_STRING[] = {JSON_SEM_SCALAR_CALL, JSON_TOKEN_STRING, JSON_SEM_SCALAR_INIT, 0};
129 : :
130 : : /* JSON -> number */
131 : : static char JSON_PROD_SCALAR_NUMBER[] = {JSON_SEM_SCALAR_CALL, JSON_TOKEN_NUMBER, JSON_SEM_SCALAR_INIT, 0};
132 : :
133 : : /* JSON -> 'true' */
134 : : static char JSON_PROD_SCALAR_TRUE[] = {JSON_SEM_SCALAR_CALL, JSON_TOKEN_TRUE, JSON_SEM_SCALAR_INIT, 0};
135 : :
136 : : /* JSON -> 'false' */
137 : : static char JSON_PROD_SCALAR_FALSE[] = {JSON_SEM_SCALAR_CALL, JSON_TOKEN_FALSE, JSON_SEM_SCALAR_INIT, 0};
138 : :
139 : : /* JSON -> 'null' */
140 : : static char JSON_PROD_SCALAR_NULL[] = {JSON_SEM_SCALAR_CALL, JSON_TOKEN_NULL, JSON_SEM_SCALAR_INIT, 0};
141 : :
142 : : /* JSON -> '{' KEY_PAIRS '}' */
143 : : static char JSON_PROD_OBJECT[] = {JSON_SEM_OEND, JSON_TOKEN_OBJECT_END, JSON_NT_KEY_PAIRS, JSON_TOKEN_OBJECT_START, JSON_SEM_OSTART, 0};
144 : :
145 : : /* JSON -> '[' ARRAY_ELEMENTS ']' */
146 : : static char JSON_PROD_ARRAY[] = {JSON_SEM_AEND, JSON_TOKEN_ARRAY_END, JSON_NT_ARRAY_ELEMENTS, JSON_TOKEN_ARRAY_START, JSON_SEM_ASTART, 0};
147 : :
148 : : /* ARRAY_ELEMENTS -> JSON MORE_ARRAY_ELEMENTS */
149 : : static char JSON_PROD_ARRAY_ELEMENTS[] = {JSON_NT_MORE_ARRAY_ELEMENTS, JSON_SEM_AELEM_END, JSON_NT_JSON, JSON_SEM_AELEM_START, 0};
150 : :
151 : : /* MORE_ARRAY_ELEMENTS -> ',' JSON MORE_ARRAY_ELEMENTS */
152 : : static char JSON_PROD_MORE_ARRAY_ELEMENTS[] = {JSON_NT_MORE_ARRAY_ELEMENTS, JSON_SEM_AELEM_END, JSON_NT_JSON, JSON_SEM_AELEM_START, JSON_TOKEN_COMMA, 0};
153 : :
154 : : /* KEY_PAIRS -> string ':' JSON MORE_KEY_PAIRS */
155 : : static char JSON_PROD_KEY_PAIRS[] = {JSON_NT_MORE_KEY_PAIRS, JSON_SEM_OFIELD_END, JSON_NT_JSON, JSON_SEM_OFIELD_START, JSON_TOKEN_COLON, JSON_TOKEN_STRING, JSON_SEM_OFIELD_INIT, 0};
156 : :
157 : : /* MORE_KEY_PAIRS -> ',' string ':' JSON MORE_KEY_PAIRS */
158 : : static char JSON_PROD_MORE_KEY_PAIRS[] = {JSON_NT_MORE_KEY_PAIRS, JSON_SEM_OFIELD_END, JSON_NT_JSON, JSON_SEM_OFIELD_START, JSON_TOKEN_COLON, JSON_TOKEN_STRING, JSON_SEM_OFIELD_INIT, JSON_TOKEN_COMMA, 0};
159 : :
160 : : /*
161 : : * Note: there are also epsilon productions for ARRAY_ELEMENTS,
162 : : * MORE_ARRAY_ELEMENTS, KEY_PAIRS and MORE_KEY_PAIRS
163 : : * They are all the same as none require any semantic actions.
164 : : */
165 : :
166 : : /*
167 : : * Table connecting the productions with their director sets of
168 : : * terminal symbols.
169 : : * Any combination not specified here represents an error.
170 : : */
171 : :
172 : : typedef struct
173 : : {
174 : : size_t len;
175 : : char *prod;
176 : : } td_entry;
177 : :
178 : : #define TD_ENTRY(PROD) { sizeof(PROD) - 1, (PROD) }
179 : :
180 : : static td_entry td_parser_table[JSON_NUM_NONTERMINALS][JSON_NUM_TERMINALS] =
181 : : {
182 : : /* JSON */
183 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_STRING] = TD_ENTRY(JSON_PROD_SCALAR_STRING),
184 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_NUMBER] = TD_ENTRY(JSON_PROD_SCALAR_NUMBER),
185 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_TRUE] = TD_ENTRY(JSON_PROD_SCALAR_TRUE),
186 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_FALSE] = TD_ENTRY(JSON_PROD_SCALAR_FALSE),
187 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_NULL] = TD_ENTRY(JSON_PROD_SCALAR_NULL),
188 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_ARRAY_START] = TD_ENTRY(JSON_PROD_ARRAY),
189 : : [OFS(JSON_NT_JSON)][JSON_TOKEN_OBJECT_START] = TD_ENTRY(JSON_PROD_OBJECT),
190 : : /* ARRAY_ELEMENTS */
191 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_ARRAY_START] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
192 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_OBJECT_START] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
193 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_STRING] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
194 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_NUMBER] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
195 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_TRUE] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
196 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_FALSE] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
197 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_NULL] = TD_ENTRY(JSON_PROD_ARRAY_ELEMENTS),
198 : : [OFS(JSON_NT_ARRAY_ELEMENTS)][JSON_TOKEN_ARRAY_END] = TD_ENTRY(JSON_PROD_EPSILON),
199 : : /* MORE_ARRAY_ELEMENTS */
200 : : [OFS(JSON_NT_MORE_ARRAY_ELEMENTS)][JSON_TOKEN_COMMA] = TD_ENTRY(JSON_PROD_MORE_ARRAY_ELEMENTS),
201 : : [OFS(JSON_NT_MORE_ARRAY_ELEMENTS)][JSON_TOKEN_ARRAY_END] = TD_ENTRY(JSON_PROD_EPSILON),
202 : : /* KEY_PAIRS */
203 : : [OFS(JSON_NT_KEY_PAIRS)][JSON_TOKEN_STRING] = TD_ENTRY(JSON_PROD_KEY_PAIRS),
204 : : [OFS(JSON_NT_KEY_PAIRS)][JSON_TOKEN_OBJECT_END] = TD_ENTRY(JSON_PROD_EPSILON),
205 : : /* MORE_KEY_PAIRS */
206 : : [OFS(JSON_NT_MORE_KEY_PAIRS)][JSON_TOKEN_COMMA] = TD_ENTRY(JSON_PROD_MORE_KEY_PAIRS),
207 : : [OFS(JSON_NT_MORE_KEY_PAIRS)][JSON_TOKEN_OBJECT_END] = TD_ENTRY(JSON_PROD_EPSILON),
208 : : };
209 : :
210 : : /* the GOAL production. Not stored in the table, but will be the initial contents of the prediction stack */
211 : : static char JSON_PROD_GOAL[] = {JSON_TOKEN_END, JSON_NT_JSON, 0};
212 : :
213 : : static inline JsonParseErrorType json_lex_string(JsonLexContext *lex);
214 : : static inline JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s,
215 : : bool *num_err, int *total_len);
216 : : static inline JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem);
217 : : static JsonParseErrorType parse_object_field(JsonLexContext *lex, JsonSemAction *sem);
218 : : static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem);
219 : : static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem);
220 : : static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem);
221 : : static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex);
222 : :
223 : : /* the null action object used for pure validation */
224 : : JsonSemAction nullSemAction =
225 : : {
226 : : NULL, NULL, NULL, NULL, NULL,
227 : : NULL, NULL, NULL, NULL, NULL
228 : : };
229 : :
230 : : /* Parser support routines */
231 : :
232 : : /*
233 : : * lex_peek
234 : : *
235 : : * what is the current look_ahead token?
236 : : */
237 : : static inline JsonTokenType
1542 rhaas@postgresql.org 238 :CBC 3819938 : lex_peek(JsonLexContext *lex)
239 : : {
240 : 3819938 : return lex->token_type;
241 : : }
242 : :
243 : : /*
244 : : * lex_expect
245 : : *
246 : : * move the lexer to the next token if the current look_ahead token matches
247 : : * the parameter token. Otherwise, report an error.
248 : : */
249 : : static inline JsonParseErrorType
250 : 178794 : lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
251 : : {
1549 252 [ + + ]: 178794 : if (lex_peek(lex) == token)
1539 253 : 178740 : return json_lex(lex);
254 : : else
255 : 54 : return report_parse_error(ctx, lex);
256 : : }
257 : :
258 : : /* chars to consider as part of an alphanumeric token */
259 : : #define JSON_ALPHANUMERIC_CHAR(c) \
260 : : (((c) >= 'a' && (c) <= 'z') || \
261 : : ((c) >= 'A' && (c) <= 'Z') || \
262 : : ((c) >= '0' && (c) <= '9') || \
263 : : (c) == '_' || \
264 : : IS_HIGHBIT_SET(c))
265 : :
266 : : /*
267 : : * Utility function to check if a string is a valid JSON number.
268 : : *
269 : : * str is of length len, and need not be null-terminated.
270 : : */
271 : : bool
1542 272 : 23 : IsValidJsonNumber(const char *str, int len)
273 : : {
274 : : bool numeric_error;
275 : : int total_len;
276 : : JsonLexContext dummy_lex;
277 : :
278 [ - + ]: 23 : if (len <= 0)
1542 rhaas@postgresql.org 279 :UBC 0 : return false;
280 : :
35 andrew@dunslane.net 281 :GNC 23 : dummy_lex.incremental = false;
9 282 : 23 : dummy_lex.inc_state = NULL;
283 : 23 : dummy_lex.pstack = NULL;
284 : :
285 : : /*
286 : : * json_lex_number expects a leading '-' to have been eaten already.
287 : : *
288 : : * having to cast away the constness of str is ugly, but there's not much
289 : : * easy alternative.
290 : : */
1542 rhaas@postgresql.org 291 [ + + ]:CBC 23 : if (*str == '-')
292 : : {
1429 tgl@sss.pgh.pa.us 293 : 2 : dummy_lex.input = unconstify(char *, str) + 1;
1542 rhaas@postgresql.org 294 : 2 : dummy_lex.input_length = len - 1;
295 : : }
296 : : else
297 : : {
298 : 21 : dummy_lex.input = unconstify(char *, str);
299 : 21 : dummy_lex.input_length = len;
300 : : }
301 : :
9 andrew@dunslane.net 302 :GNC 23 : dummy_lex.token_start = dummy_lex.input;
303 : :
1542 rhaas@postgresql.org 304 :CBC 23 : json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
305 : :
306 [ + + + + ]: 23 : return (!numeric_error) && (total_len == dummy_lex.input_length);
307 : : }
308 : :
309 : : /*
310 : : * makeJsonLexContextCstringLen
311 : : * Initialize the given JsonLexContext object, or create one
312 : : *
313 : : * If a valid 'lex' pointer is given, it is initialized. This can
314 : : * be used for stack-allocated structs, saving overhead. If NULL is
315 : : * given, a new struct is allocated.
316 : : *
317 : : * If need_escapes is true, ->strval stores the unescaped lexemes.
318 : : * Unescaping is expensive, so only request it when necessary.
319 : : *
320 : : * If need_escapes is true or lex was given as NULL, then caller is
321 : : * responsible for freeing the returned struct, either by calling
322 : : * freeJsonLexContext() or (in backend environment) via memory context
323 : : * cleanup.
324 : : */
325 : : JsonLexContext *
192 alvherre@alvh.no-ip. 326 :GNC 18012 : makeJsonLexContextCstringLen(JsonLexContext *lex, char *json,
327 : : int len, int encoding, bool need_escapes)
328 : : {
329 [ + + ]: 18012 : if (lex == NULL)
330 : : {
331 : 2769 : lex = palloc0(sizeof(JsonLexContext));
332 : 2769 : lex->flags |= JSONLEX_FREE_STRUCT;
333 : : }
334 : : else
335 : 15243 : memset(lex, 0, sizeof(JsonLexContext));
336 : :
28 dgustafsson@postgres 337 : 18012 : lex->errormsg = NULL;
1542 rhaas@postgresql.org 338 :CBC 18012 : lex->input = lex->token_terminator = lex->line_start = json;
339 : 18012 : lex->line_number = 1;
340 : 18012 : lex->input_length = len;
1537 341 : 18012 : lex->input_encoding = encoding;
1542 342 [ + + ]: 18012 : if (need_escapes)
343 : : {
344 : 14080 : lex->strval = makeStringInfo();
192 alvherre@alvh.no-ip. 345 :GNC 14080 : lex->flags |= JSONLEX_FREE_STRVAL;
346 : : }
347 : :
1542 rhaas@postgresql.org 348 :CBC 18012 : return lex;
349 : : }
350 : :
351 : :
352 : : /*
353 : : * makeJsonLexContextIncremental
354 : : *
355 : : * Similar to above but set up for use in incremental parsing. That means we
356 : : * need explicit stacks for predictions, field names and null indicators, but
357 : : * we don't need the input, that will be handed in bit by bit to the
358 : : * parse routine. We also need an accumulator for partial tokens in case
359 : : * the boundary between chunks happens to fall in the middle of a token.
360 : : */
361 : : #define JS_STACK_CHUNK_SIZE 64
362 : : #define JS_MAX_PROD_LEN 10 /* more than we need */
363 : : #define JSON_TD_MAX_STACK 6400 /* hard coded for now - this is a REALLY high
364 : : * number */
365 : :
366 : : JsonLexContext *
35 andrew@dunslane.net 367 :GNC 585 : makeJsonLexContextIncremental(JsonLexContext *lex, int encoding,
368 : : bool need_escapes)
369 : : {
370 [ + + ]: 585 : if (lex == NULL)
371 : : {
372 : 1 : lex = palloc0(sizeof(JsonLexContext));
373 : 1 : lex->flags |= JSONLEX_FREE_STRUCT;
374 : : }
375 : : else
376 : 584 : memset(lex, 0, sizeof(JsonLexContext));
377 : :
378 : 585 : lex->line_number = 1;
379 : 585 : lex->input_encoding = encoding;
380 : 585 : lex->incremental = true;
381 : 585 : lex->inc_state = palloc0(sizeof(JsonIncrementalState));
382 : 585 : initStringInfo(&(lex->inc_state->partial_token));
383 : 585 : lex->pstack = palloc(sizeof(JsonParserStack));
384 : 585 : lex->pstack->stack_size = JS_STACK_CHUNK_SIZE;
385 : 585 : lex->pstack->prediction = palloc(JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN);
386 : 585 : lex->pstack->pred_index = 0;
387 : 585 : lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *));
388 : 585 : lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool));
389 [ + + ]: 585 : if (need_escapes)
390 : : {
391 : 98 : lex->strval = makeStringInfo();
392 : 98 : lex->flags |= JSONLEX_FREE_STRVAL;
393 : : }
394 : 585 : return lex;
395 : : }
396 : :
397 : : static inline void
398 : 712984 : inc_lex_level(JsonLexContext *lex)
399 : : {
400 : 712984 : lex->lex_level += 1;
401 : :
402 [ + - + + ]: 712984 : if (lex->incremental && lex->lex_level >= lex->pstack->stack_size)
403 : : {
404 : 9600 : lex->pstack->stack_size += JS_STACK_CHUNK_SIZE;
405 : 19200 : lex->pstack->prediction =
406 : 9600 : repalloc(lex->pstack->prediction,
407 : 9600 : lex->pstack->stack_size * JS_MAX_PROD_LEN);
408 [ + - ]: 9600 : if (lex->pstack->fnames)
409 : 9600 : lex->pstack->fnames =
410 : 9600 : repalloc(lex->pstack->fnames,
411 : 9600 : lex->pstack->stack_size * sizeof(char *));
412 [ + - ]: 9600 : if (lex->pstack->fnull)
413 : 9600 : lex->pstack->fnull =
414 : 9600 : repalloc(lex->pstack->fnull, lex->pstack->stack_size * sizeof(bool));
415 : : }
416 : 712984 : }
417 : :
418 : : static inline void
419 : 303258 : dec_lex_level(JsonLexContext *lex)
420 : : {
421 : 303258 : lex->lex_level -= 1;
422 : 303258 : }
423 : :
424 : : static inline void
425 : 2695424 : push_prediction(JsonParserStack *pstack, td_entry entry)
426 : : {
427 : 2695424 : memcpy(pstack->prediction + pstack->pred_index, entry.prod, entry.len);
428 : 2695424 : pstack->pred_index += entry.len;
429 : 2695424 : }
430 : :
431 : : static inline char
432 : 10094610 : pop_prediction(JsonParserStack *pstack)
433 : : {
434 [ - + ]: 10094610 : Assert(pstack->pred_index > 0);
435 : 10094610 : return pstack->prediction[--pstack->pred_index];
436 : : }
437 : :
438 : : static inline char
439 : 19 : next_prediction(JsonParserStack *pstack)
440 : : {
441 [ - + ]: 19 : Assert(pstack->pred_index > 0);
442 : 19 : return pstack->prediction[pstack->pred_index - 1];
443 : : }
444 : :
445 : : static inline bool
446 : 10170223 : have_prediction(JsonParserStack *pstack)
447 : : {
448 : 10170223 : return pstack->pred_index > 0;
449 : : }
450 : :
451 : : static inline void
452 : 484422 : set_fname(JsonLexContext *lex, char *fname)
453 : : {
454 : 484422 : lex->pstack->fnames[lex->lex_level] = fname;
455 : 484422 : }
456 : :
457 : : static inline char *
458 : 474546 : get_fname(JsonLexContext *lex)
459 : : {
460 : 474546 : return lex->pstack->fnames[lex->lex_level];
461 : : }
462 : :
463 : : static inline void
464 : 1195530 : set_fnull(JsonLexContext *lex, bool fnull)
465 : : {
466 : 1195530 : lex->pstack->fnull[lex->lex_level] = fnull;
467 : 1195530 : }
468 : :
469 : : static inline bool
470 : 185 : get_fnull(JsonLexContext *lex)
471 : : {
472 : 185 : return lex->pstack->fnull[lex->lex_level];
473 : : }
474 : :
475 : : /*
476 : : * Free memory in a JsonLexContext.
477 : : *
478 : : * There's no need for this if a *lex pointer was given when the object was
479 : : * made, need_escapes was false, and json_errdetail() was not called; or if (in
480 : : * backend environment) a memory context delete/reset is imminent.
481 : : */
482 : : void
192 alvherre@alvh.no-ip. 483 : 3243 : freeJsonLexContext(JsonLexContext *lex)
484 : : {
485 [ + + ]: 3243 : if (lex->flags & JSONLEX_FREE_STRVAL)
28 dgustafsson@postgres 486 : 3046 : destroyStringInfo(lex->strval);
487 : :
488 [ - + ]: 3243 : if (lex->errormsg)
28 dgustafsson@postgres 489 :UNC 0 : destroyStringInfo(lex->errormsg);
490 : :
5 andrew@dunslane.net 491 [ + + ]:GNC 3243 : if (lex->incremental)
492 : : {
493 : 96 : pfree(lex->inc_state->partial_token.data);
494 : 96 : pfree(lex->inc_state);
495 : 96 : pfree(lex->pstack->prediction);
496 : 96 : pfree(lex->pstack->fnames);
497 : 96 : pfree(lex->pstack->fnull);
498 : 96 : pfree(lex->pstack);
499 : : }
500 : :
501 [ + + ]: 3243 : if (lex->flags & JSONLEX_FREE_STRUCT)
502 : 2659 : pfree(lex);
192 alvherre@alvh.no-ip. 503 : 3243 : }
504 : :
505 : : /*
506 : : * pg_parse_json
507 : : *
508 : : * Publicly visible entry point for the JSON parser.
509 : : *
510 : : * lex is a lexing context, set up for the json to be processed by calling
511 : : * makeJsonLexContext(). sem is a structure of function pointers to semantic
512 : : * action routines to be called at appropriate spots during parsing, and a
513 : : * pointer to a state object to be passed to those routines.
514 : : *
515 : : * If FORCE_JSON_PSTACK is defined then the routine will call the non-recursive
516 : : * JSON parser. This is a useful way to validate that it's doing the right
517 : : * think at least for non-incremental cases. If this is on we expect to see
518 : : * regression diffs relating to error messages about stack depth, but no
519 : : * other differences.
520 : : */
521 : : JsonParseErrorType
1542 rhaas@postgresql.org 522 :CBC 17646 : pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
523 : : {
524 : : #ifdef FORCE_JSON_PSTACK
525 : :
526 : : lex->incremental = true;
527 : : lex->inc_state = palloc0(sizeof(JsonIncrementalState));
528 : :
529 : : /*
530 : : * We don't need partial token processing, there is only one chunk. But we
531 : : * still need to init the partial token string so that freeJsonLexContext
532 : : * works.
533 : : */
534 : : initStringInfo(&(lex->inc_state->partial_token));
535 : : lex->pstack = palloc(sizeof(JsonParserStack));
536 : : lex->pstack->stack_size = JS_STACK_CHUNK_SIZE;
537 : : lex->pstack->prediction = palloc(JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN);
538 : : lex->pstack->pred_index = 0;
539 : : lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *));
540 : : lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool));
541 : :
542 : : return pg_parse_json_incremental(lex, sem, lex->input, lex->input_length, true);
543 : :
544 : : #else
545 : :
546 : : JsonTokenType tok;
547 : : JsonParseErrorType result;
548 : :
35 andrew@dunslane.net 549 [ - + ]:GNC 17646 : if (lex->incremental)
35 andrew@dunslane.net 550 :UNC 0 : return JSON_INVALID_LEXER_TYPE;
551 : :
552 : : /* get the initial token */
1539 rhaas@postgresql.org 553 :CBC 17646 : result = json_lex(lex);
554 [ + + ]: 17646 : if (result != JSON_SUCCESS)
555 : 123 : return result;
556 : :
1542 557 : 17523 : tok = lex_peek(lex);
558 : :
559 : : /* parse by recursive descent */
560 [ + + + ]: 17523 : switch (tok)
561 : : {
562 : 9936 : case JSON_TOKEN_OBJECT_START:
1539 563 : 9936 : result = parse_object(lex, sem);
1542 564 : 9902 : break;
565 : 3170 : case JSON_TOKEN_ARRAY_START:
1539 566 : 3170 : result = parse_array(lex, sem);
1542 567 : 3118 : break;
568 : 4417 : default:
1431 tgl@sss.pgh.pa.us 569 : 4417 : result = parse_scalar(lex, sem); /* json can be a bare scalar */
570 : : }
571 : :
1539 rhaas@postgresql.org 572 [ + + ]: 17401 : if (result == JSON_SUCCESS)
573 : 17180 : result = lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
574 : :
575 : 17401 : return result;
576 : : #endif
577 : : }
578 : :
579 : : /*
580 : : * json_count_array_elements
581 : : *
582 : : * Returns number of array elements in lex context at start of array token
583 : : * until end of array token at same nesting level.
584 : : *
585 : : * Designed to be called from array_start routines.
586 : : */
587 : : JsonParseErrorType
588 : 3 : json_count_array_elements(JsonLexContext *lex, int *elements)
589 : : {
590 : : JsonLexContext copylex;
591 : : int count;
592 : : JsonParseErrorType result;
593 : :
594 : : /*
595 : : * It's safe to do this with a shallow copy because the lexical routines
596 : : * don't scribble on the input. They do scribble on the other pointers
597 : : * etc, so doing this with a copy makes that safe.
598 : : */
1542 599 : 3 : memcpy(©lex, lex, sizeof(JsonLexContext));
600 : 3 : copylex.strval = NULL; /* not interested in values here */
601 : 3 : copylex.lex_level++;
602 : :
603 : 3 : count = 0;
1539 604 : 3 : result = lex_expect(JSON_PARSE_ARRAY_START, ©lex,
605 : : JSON_TOKEN_ARRAY_START);
606 [ - + ]: 3 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 607 :UBC 0 : return result;
1542 rhaas@postgresql.org 608 [ + - ]:CBC 3 : if (lex_peek(©lex) != JSON_TOKEN_ARRAY_END)
609 : : {
610 : : while (1)
611 : : {
612 : 24 : count++;
1539 613 : 24 : result = parse_array_element(©lex, &nullSemAction);
614 [ - + ]: 24 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 615 :UBC 0 : return result;
1549 rhaas@postgresql.org 616 [ + + ]:CBC 24 : if (copylex.token_type != JSON_TOKEN_COMMA)
617 : 3 : break;
1539 618 : 21 : result = json_lex(©lex);
619 [ - + ]: 21 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 620 :UBC 0 : return result;
621 : : }
622 : : }
1539 rhaas@postgresql.org 623 :CBC 3 : result = lex_expect(JSON_PARSE_ARRAY_NEXT, ©lex,
624 : : JSON_TOKEN_ARRAY_END);
625 [ - + ]: 3 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 626 :UBC 0 : return result;
627 : :
1539 rhaas@postgresql.org 628 :CBC 3 : *elements = count;
629 : 3 : return JSON_SUCCESS;
630 : : }
631 : :
632 : : /*
633 : : * pg_parse_json_incremental
634 : : *
635 : : * Routine for incremental parsing of json. This uses the non-recursive top
636 : : * down method of the Dragon Book Algorithm 4.3. It's somewhat slower than
637 : : * the Recursive Descent pattern used above, so we only use it for incremental
638 : : * parsing of JSON.
639 : : *
640 : : * The lexing context needs to be set up by a call to
641 : : * makeJsonLexContextIncremental(). sem is a structure of function pointers
642 : : * to semantic action routines, which should function exactly as those used
643 : : * in the recursive descent parser.
644 : : *
645 : : * This routine can be called repeatedly with chunks of JSON. On the final
646 : : * chunk is_last must be set to true. len is the length of the json chunk,
647 : : * which does not need to be null terminated.
648 : : */
649 : : JsonParseErrorType
35 andrew@dunslane.net 650 :GNC 93168 : pg_parse_json_incremental(JsonLexContext *lex,
651 : : JsonSemAction *sem,
652 : : char *json,
653 : : int len,
654 : : bool is_last)
655 : : {
656 : : JsonTokenType tok;
657 : : JsonParseErrorType result;
658 : 93168 : JsonParseContext ctx = JSON_PARSE_VALUE;
659 : 93168 : JsonParserStack *pstack = lex->pstack;
660 : :
661 : :
662 [ - + ]: 93168 : if (!lex->incremental)
35 andrew@dunslane.net 663 :UNC 0 : return JSON_INVALID_LEXER_TYPE;
664 : :
35 andrew@dunslane.net 665 :GNC 93168 : lex->input = lex->token_terminator = lex->line_start = json;
666 : 93168 : lex->input_length = len;
667 : 93168 : lex->inc_state->is_last_chunk = is_last;
668 : :
669 : : /* get the initial token */
670 : 93168 : result = json_lex(lex);
671 [ + + ]: 93168 : if (result != JSON_SUCCESS)
672 : 17903 : return result;
673 : :
674 : 75265 : tok = lex_peek(lex);
675 : :
676 : : /* use prediction stack for incremental parsing */
677 : :
678 [ + + ]: 75265 : if (!have_prediction(pstack))
679 : : {
680 : 542 : td_entry goal = TD_ENTRY(JSON_PROD_GOAL);
681 : :
682 : 542 : push_prediction(pstack, goal);
683 : : }
684 : :
685 [ + + ]: 10094958 : while (have_prediction(pstack))
686 : : {
687 : 10094610 : char top = pop_prediction(pstack);
688 : : td_entry entry;
689 : :
690 : : /*
691 : : * these first two branches are the guts of the Table Driven method
692 : : */
693 [ + + ]: 10094610 : if (top == tok)
694 : : {
695 : : /*
696 : : * tok can only be a terminal symbol, so top must be too. the
697 : : * token matches the top of the stack, so get the next token.
698 : : */
699 [ + + ]: 2951411 : if (tok < JSON_TOKEN_END)
700 : : {
701 : 2951063 : result = json_lex(lex);
702 [ + + ]: 2951063 : if (result != JSON_SUCCESS)
703 : 74916 : return result;
704 : 2876322 : tok = lex_peek(lex);
705 : : }
706 : : }
707 [ + + + + ]: 7143199 : else if (IS_NT(top) && (entry = td_parser_table[OFS(top)][tok]).prod != NULL)
708 : : {
709 : : /*
710 : : * the token is in the director set for a production of the
711 : : * non-terminal at the top of the stack, so push the reversed RHS
712 : : * of the production onto the stack.
713 : : */
714 : 2694882 : push_prediction(pstack, entry);
715 : : }
716 [ + + ]: 4448317 : else if (IS_SEM(top))
717 : : {
718 : : /*
719 : : * top is a semantic action marker, so take action accordingly.
720 : : * It's important to have these markers in the prediction stack
721 : : * before any token they might need so we don't advance the token
722 : : * prematurely. Note in a couple of cases we need to do something
723 : : * both before and after the token.
724 : : */
725 [ + + + + : 4448206 : switch (top)
+ + + + +
+ + - ]
726 : : {
727 : 97596 : case JSON_SEM_OSTART:
728 : : {
729 : 97596 : json_struct_action ostart = sem->object_start;
730 : :
731 [ - + ]: 97596 : if (lex->lex_level >= JSON_TD_MAX_STACK)
35 andrew@dunslane.net 732 :UNC 0 : return JSON_NESTING_TOO_DEEP;
733 : :
35 andrew@dunslane.net 734 [ + + ]:GNC 97596 : if (ostart != NULL)
735 : : {
736 : 94927 : result = (*ostart) (sem->semstate);
737 [ - + ]: 94927 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 738 :UNC 0 : return result;
739 : : }
35 andrew@dunslane.net 740 :GNC 97596 : inc_lex_level(lex);
741 : : }
742 : 97596 : break;
743 : 97504 : case JSON_SEM_OEND:
744 : : {
745 : 97504 : json_struct_action oend = sem->object_end;
746 : :
747 : 97504 : dec_lex_level(lex);
748 [ + + ]: 97504 : if (oend != NULL)
749 : : {
750 : 94926 : result = (*oend) (sem->semstate);
751 [ - + ]: 94926 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 752 :UNC 0 : return result;
753 : : }
754 : : }
35 andrew@dunslane.net 755 :GNC 97504 : break;
756 : 615452 : case JSON_SEM_ASTART:
757 : : {
758 : 615452 : json_struct_action astart = sem->array_start;
759 : :
760 [ + + ]: 615452 : if (lex->lex_level >= JSON_TD_MAX_STACK)
761 : 64 : return JSON_NESTING_TOO_DEEP;
762 : :
763 [ + + ]: 615388 : if (astart != NULL)
764 : : {
765 : 203 : result = (*astart) (sem->semstate);
766 [ - + ]: 203 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 767 :UNC 0 : return result;
768 : : }
35 andrew@dunslane.net 769 :GNC 615388 : inc_lex_level(lex);
770 : : }
771 : 615388 : break;
772 : 205754 : case JSON_SEM_AEND:
773 : : {
774 : 205754 : json_struct_action aend = sem->array_end;
775 : :
776 : 205754 : dec_lex_level(lex);
777 [ + + ]: 205754 : if (aend != NULL)
778 : : {
779 : 203 : result = (*aend) (sem->semstate);
780 [ - + ]: 203 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 781 :UNC 0 : return result;
782 : : }
783 : : }
35 andrew@dunslane.net 784 :GNC 205754 : break;
785 : 484422 : case JSON_SEM_OFIELD_INIT:
786 : : {
787 : : /*
788 : : * all we do here is save out the field name. We have
789 : : * to wait to get past the ':' to see if the next
790 : : * value is null so we can call the semantic routine
791 : : */
792 : 484422 : char *fname = NULL;
793 : 484422 : json_ofield_action ostart = sem->object_field_start;
794 : 484422 : json_ofield_action oend = sem->object_field_end;
795 : :
796 [ + + - + : 484422 : if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
+ - ]
797 : : {
798 : 474391 : fname = pstrdup(lex->strval->data);
799 : : }
800 : 484422 : set_fname(lex, fname);
801 : : }
802 : 484422 : break;
803 : 484390 : case JSON_SEM_OFIELD_START:
804 : : {
805 : : /*
806 : : * the current token should be the first token of the
807 : : * value
808 : : */
809 : 484390 : bool isnull = tok == JSON_TOKEN_NULL;
810 : 484390 : json_ofield_action ostart = sem->object_field_start;
811 : :
812 : 484390 : set_fnull(lex, isnull);
813 : :
814 [ + + ]: 484390 : if (ostart != NULL)
815 : : {
816 : 474391 : char *fname = get_fname(lex);
817 : :
818 : 474391 : result = (*ostart) (sem->semstate, fname, isnull);
819 [ - + ]: 474391 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 820 :UNC 0 : return result;
821 : : }
822 : : }
35 andrew@dunslane.net 823 :GNC 484390 : break;
824 : 484380 : case JSON_SEM_OFIELD_END:
825 : : {
826 : 484380 : json_ofield_action oend = sem->object_field_end;
827 : :
828 [ + + ]: 484380 : if (oend != NULL)
829 : : {
830 : 155 : char *fname = get_fname(lex);
831 : 155 : bool isnull = get_fnull(lex);
832 : :
833 : 155 : result = (*oend) (sem->semstate, fname, isnull);
834 [ - + ]: 155 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 835 :UNC 0 : return result;
836 : : }
837 : : }
35 andrew@dunslane.net 838 :GNC 484380 : break;
839 : 711140 : case JSON_SEM_AELEM_START:
840 : : {
841 : 711140 : json_aelem_action astart = sem->array_element_start;
842 : 711140 : bool isnull = tok == JSON_TOKEN_NULL;
843 : :
844 : 711140 : set_fnull(lex, isnull);
845 : :
846 [ + + ]: 711140 : if (astart != NULL)
847 : : {
848 : 30 : result = (*astart) (sem->semstate, isnull);
849 [ - + ]: 30 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 850 :UNC 0 : return result;
851 : : }
852 : : }
35 andrew@dunslane.net 853 :GNC 711140 : break;
854 : 301540 : case JSON_SEM_AELEM_END:
855 : : {
856 : 301540 : json_aelem_action aend = sem->array_element_end;
857 : :
858 [ + + ]: 301540 : if (aend != NULL)
859 : : {
860 : 30 : bool isnull = get_fnull(lex);
861 : :
862 : 30 : result = (*aend) (sem->semstate, isnull);
863 [ - + ]: 30 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 864 :UNC 0 : return result;
865 : : }
866 : : }
35 andrew@dunslane.net 867 :GNC 301540 : break;
868 : 483014 : case JSON_SEM_SCALAR_INIT:
869 : : {
870 : 483014 : json_scalar_action sfunc = sem->scalar;
871 : :
872 : 483014 : pstack->scalar_val = NULL;
873 : :
874 [ + + ]: 483014 : if (sfunc != NULL)
875 : : {
876 : : /*
877 : : * extract the de-escaped string value, or the raw
878 : : * lexeme
879 : : */
880 : : /*
881 : : * XXX copied from RD parser but looks like a
882 : : * buglet
883 : : */
884 [ + + ]: 474179 : if (tok == JSON_TOKEN_STRING)
885 : : {
886 [ + - ]: 379165 : if (lex->strval != NULL)
887 : 379165 : pstack->scalar_val = pstrdup(lex->strval->data);
888 : : }
889 : : else
890 : : {
891 : 95014 : int tlen = (lex->token_terminator - lex->token_start);
892 : :
893 : 95014 : pstack->scalar_val = palloc(tlen + 1);
894 : 95014 : memcpy(pstack->scalar_val, lex->token_start, tlen);
895 : 95014 : pstack->scalar_val[tlen] = '\0';
896 : : }
897 : 474179 : pstack->scalar_tok = tok;
898 : : }
899 : : }
900 : 483014 : break;
901 : 483014 : case JSON_SEM_SCALAR_CALL:
902 : : {
903 : : /*
904 : : * We'd like to be able to get rid of this business of
905 : : * two bits of scalar action, but we can't. It breaks
906 : : * certain semantic actions which expect that when
907 : : * called the lexer has consumed the item. See for
908 : : * example get_scalar() in jsonfuncs.c.
909 : : */
910 : 483014 : json_scalar_action sfunc = sem->scalar;
911 : :
912 [ + + ]: 483014 : if (sfunc != NULL)
913 : : {
914 : 474179 : result = (*sfunc) (sem->semstate, pstack->scalar_val, pstack->scalar_tok);
915 [ - + ]: 474178 : if (result != JSON_SUCCESS)
35 andrew@dunslane.net 916 :UNC 0 : return result;
917 : : }
918 : : }
35 andrew@dunslane.net 919 :GNC 483013 : break;
35 andrew@dunslane.net 920 :UNC 0 : default:
921 : : /* should not happen */
922 : 0 : break;
923 : : }
924 : : }
925 : : else
926 : : {
927 : : /*
928 : : * The token didn't match the stack top if it's a terminal nor a
929 : : * production for the stack top if it's a non-terminal.
930 : : *
931 : : * Various cases here are Asserted to be not possible, as the
932 : : * token would not appear at the top of the prediction stack
933 : : * unless the lookahead matched.
934 : : */
35 andrew@dunslane.net 935 [ + - - - :GNC 111 : switch (top)
- + + + +
+ + + ]
936 : : {
937 : 19 : case JSON_TOKEN_STRING:
938 [ + - ]: 19 : if (next_prediction(pstack) == JSON_TOKEN_COLON)
939 : 19 : ctx = JSON_PARSE_STRING;
940 : : else
941 : : {
35 andrew@dunslane.net 942 :UNC 0 : Assert(false);
943 : : ctx = JSON_PARSE_VALUE;
944 : : }
35 andrew@dunslane.net 945 :GNC 19 : break;
35 andrew@dunslane.net 946 :UNC 0 : case JSON_TOKEN_NUMBER:
947 : : case JSON_TOKEN_TRUE:
948 : : case JSON_TOKEN_FALSE:
949 : : case JSON_TOKEN_NULL:
950 : : case JSON_TOKEN_ARRAY_START:
951 : : case JSON_TOKEN_OBJECT_START:
952 : 0 : Assert(false);
953 : : ctx = JSON_PARSE_VALUE;
954 : : break;
955 : 0 : case JSON_TOKEN_ARRAY_END:
956 : 0 : Assert(false);
957 : : ctx = JSON_PARSE_ARRAY_NEXT;
958 : : break;
959 : 0 : case JSON_TOKEN_OBJECT_END:
960 : 0 : Assert(false);
961 : : ctx = JSON_PARSE_OBJECT_NEXT;
962 : : break;
963 : 0 : case JSON_TOKEN_COMMA:
964 : 0 : Assert(false);
965 : : if (next_prediction(pstack) == JSON_TOKEN_STRING)
966 : : ctx = JSON_PARSE_OBJECT_NEXT;
967 : : else
968 : : ctx = JSON_PARSE_ARRAY_NEXT;
969 : : break;
35 andrew@dunslane.net 970 :GNC 13 : case JSON_TOKEN_COLON:
971 : 13 : ctx = JSON_PARSE_OBJECT_LABEL;
972 : 13 : break;
973 : 3 : case JSON_TOKEN_END:
974 : 3 : ctx = JSON_PARSE_END;
975 : 3 : break;
976 : 9 : case JSON_NT_MORE_ARRAY_ELEMENTS:
977 : 9 : ctx = JSON_PARSE_ARRAY_NEXT;
978 : 9 : break;
979 : 7 : case JSON_NT_ARRAY_ELEMENTS:
980 : 7 : ctx = JSON_PARSE_ARRAY_START;
981 : 7 : break;
982 : 35 : case JSON_NT_MORE_KEY_PAIRS:
983 : 35 : ctx = JSON_PARSE_OBJECT_NEXT;
984 : 35 : break;
985 : 15 : case JSON_NT_KEY_PAIRS:
986 : 15 : ctx = JSON_PARSE_OBJECT_START;
987 : 15 : break;
988 : 10 : default:
989 : 10 : ctx = JSON_PARSE_VALUE;
990 : : }
991 : 111 : return report_parse_error(ctx, lex);
992 : : }
993 : : }
994 : :
995 : 348 : return JSON_SUCCESS;
996 : : }
997 : :
998 : : /*
999 : : * Recursive Descent parse routines. There is one for each structural
1000 : : * element in a json document:
1001 : : * - scalar (string, number, true, false, null)
1002 : : * - array ( [ ] )
1003 : : * - array element
1004 : : * - object ( { } )
1005 : : * - object field
1006 : : */
1007 : : static inline JsonParseErrorType
1542 rhaas@postgresql.org 1008 :CBC 115639 : parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
1009 : : {
1010 : 115639 : char *val = NULL;
1011 : 115639 : json_scalar_action sfunc = sem->scalar;
1012 : 115639 : JsonTokenType tok = lex_peek(lex);
1013 : : JsonParseErrorType result;
1014 : :
1015 : : /* a scalar must be a string, a number, true, false, or null */
1549 1016 [ + + + + : 115639 : if (tok != JSON_TOKEN_STRING && tok != JSON_TOKEN_NUMBER &&
+ + ]
1017 [ + + + + ]: 12108 : tok != JSON_TOKEN_TRUE && tok != JSON_TOKEN_FALSE &&
1018 : : tok != JSON_TOKEN_NULL)
1539 1019 : 94 : return report_parse_error(JSON_PARSE_VALUE, lex);
1020 : :
1021 : : /* if no semantic function, just consume the token */
1549 1022 [ + + ]: 115545 : if (sfunc == NULL)
1539 1023 : 5522 : return json_lex(lex);
1024 : :
1025 : : /* extract the de-escaped string value, or the raw lexeme */
1549 1026 [ + + ]: 110023 : if (lex_peek(lex) == JSON_TOKEN_STRING)
1027 : : {
1028 [ + + ]: 35509 : if (lex->strval != NULL)
1029 : 32605 : val = pstrdup(lex->strval->data);
1030 : : }
1031 : : else
1032 : : {
1033 : 74514 : int len = (lex->token_terminator - lex->token_start);
1034 : :
1035 : 74514 : val = palloc(len + 1);
1036 : 74514 : memcpy(val, lex->token_start, len);
1037 : 74514 : val[len] = '\0';
1038 : : }
1039 : :
1040 : : /* consume the token */
1539 1041 : 110023 : result = json_lex(lex);
1042 [ - + ]: 110023 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 1043 :UBC 0 : return result;
1044 : :
1045 : : /* invoke the callback */
490 tgl@sss.pgh.pa.us 1046 :CBC 110023 : result = (*sfunc) (sem->semstate, val, tok);
1047 : :
1048 : 109975 : return result;
1049 : : }
1050 : :
1051 : : static JsonParseErrorType
1542 rhaas@postgresql.org 1052 : 112868 : parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
1053 : : {
1054 : : /*
1055 : : * An object field is "fieldname" : value where value can be a scalar,
1056 : : * object or array. Note: in user-facing docs and error messages, we
1057 : : * generally call a field name a "key".
1058 : : */
1059 : :
1060 : 112868 : char *fname = NULL; /* keep compiler quiet */
1061 : 112868 : json_ofield_action ostart = sem->object_field_start;
1062 : 112868 : json_ofield_action oend = sem->object_field_end;
1063 : : bool isnull;
1064 : : JsonTokenType tok;
1065 : : JsonParseErrorType result;
1066 : :
1549 1067 [ + + ]: 112868 : if (lex_peek(lex) != JSON_TOKEN_STRING)
1539 1068 : 6 : return report_parse_error(JSON_PARSE_STRING, lex);
1549 1069 [ + + - + : 112862 : if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
+ - ]
1070 : 89841 : fname = pstrdup(lex->strval->data);
1539 1071 : 112862 : result = json_lex(lex);
1072 [ + + ]: 112862 : if (result != JSON_SUCCESS)
1073 : 6 : return result;
1074 : :
1075 : 112856 : result = lex_expect(JSON_PARSE_OBJECT_LABEL, lex, JSON_TOKEN_COLON);
1076 [ + + ]: 112856 : if (result != JSON_SUCCESS)
1077 : 45 : return result;
1078 : :
1542 1079 : 112811 : tok = lex_peek(lex);
1080 : 112811 : isnull = tok == JSON_TOKEN_NULL;
1081 : :
1082 [ + + ]: 112811 : if (ostart != NULL)
1083 : : {
490 tgl@sss.pgh.pa.us 1084 : 89799 : result = (*ostart) (sem->semstate, fname, isnull);
1085 [ - + ]: 89795 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1086 :UBC 0 : return result;
1087 : : }
1088 : :
1542 rhaas@postgresql.org 1089 [ + + + ]:CBC 112807 : switch (tok)
1090 : : {
1091 : 5874 : case JSON_TOKEN_OBJECT_START:
1539 1092 : 5874 : result = parse_object(lex, sem);
1542 1093 : 1958 : break;
1094 : 7478 : case JSON_TOKEN_ARRAY_START:
1539 1095 : 7478 : result = parse_array(lex, sem);
1542 1096 : 7461 : break;
1097 : 99455 : default:
1539 1098 : 99455 : result = parse_scalar(lex, sem);
1099 : : }
1100 [ + + ]: 108871 : if (result != JSON_SUCCESS)
1101 : 21 : return result;
1102 : :
1542 1103 [ + + ]: 108850 : if (oend != NULL)
1104 : : {
490 tgl@sss.pgh.pa.us 1105 : 56699 : result = (*oend) (sem->semstate, fname, isnull);
1106 [ - + ]: 56699 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1107 :UBC 0 : return result;
1108 : : }
1109 : :
1539 rhaas@postgresql.org 1110 :CBC 108850 : return JSON_SUCCESS;
1111 : : }
1112 : :
1113 : : static JsonParseErrorType
1542 1114 : 23920 : parse_object(JsonLexContext *lex, JsonSemAction *sem)
1115 : : {
1116 : : /*
1117 : : * an object is a possibly empty sequence of object fields, separated by
1118 : : * commas and surrounded by curly braces.
1119 : : */
1120 : 23920 : json_struct_action ostart = sem->object_start;
1121 : 23920 : json_struct_action oend = sem->object_end;
1122 : : JsonTokenType tok;
1123 : : JsonParseErrorType result;
1124 : :
1125 : : #ifndef FRONTEND
1126 : 21934 : check_stack_depth();
1127 : : #endif
1128 : :
1129 [ + + ]: 23914 : if (ostart != NULL)
1130 : : {
490 tgl@sss.pgh.pa.us 1131 : 14111 : result = (*ostart) (sem->semstate);
1132 [ - + ]: 14101 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1133 :UBC 0 : return result;
1134 : : }
1135 : :
1136 : : /*
1137 : : * Data inside an object is at a higher nesting level than the object
1138 : : * itself. Note that we increment this after we call the semantic routine
1139 : : * for the object start and restore it before we call the routine for the
1140 : : * object end.
1141 : : */
1542 rhaas@postgresql.org 1142 :CBC 23904 : lex->lex_level++;
1143 : :
1549 1144 [ - + ]: 23904 : Assert(lex_peek(lex) == JSON_TOKEN_OBJECT_START);
1539 1145 : 23904 : result = json_lex(lex);
1146 [ + + ]: 23904 : if (result != JSON_SUCCESS)
1147 : 30 : return result;
1148 : :
1542 1149 : 23874 : tok = lex_peek(lex);
1150 [ + + + ]: 23874 : switch (tok)
1151 : : {
1152 : 22504 : case JSON_TOKEN_STRING:
1539 1153 : 22504 : result = parse_object_field(lex, sem);
1154 [ + + + + ]: 108928 : while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
1155 : : {
1156 : 90364 : result = json_lex(lex);
1157 [ - + ]: 90364 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 1158 :UBC 0 : break;
1539 rhaas@postgresql.org 1159 :CBC 90364 : result = parse_object_field(lex, sem);
1160 : : }
1542 1161 : 18564 : break;
1162 : 1363 : case JSON_TOKEN_OBJECT_END:
1163 : 1363 : break;
1164 : 7 : default:
1165 : : /* case of an invalid initial token inside the object */
1539 1166 : 7 : result = report_parse_error(JSON_PARSE_OBJECT_START, lex);
1167 : : }
1168 [ + + ]: 19934 : if (result != JSON_SUCCESS)
1169 : 85 : return result;
1170 : :
1171 : 19849 : result = lex_expect(JSON_PARSE_OBJECT_NEXT, lex, JSON_TOKEN_OBJECT_END);
1172 [ + + ]: 19849 : if (result != JSON_SUCCESS)
1173 : 18 : return result;
1174 : :
1542 1175 : 19831 : lex->lex_level--;
1176 : :
1177 [ + + ]: 19831 : if (oend != NULL)
1178 : : {
490 tgl@sss.pgh.pa.us 1179 : 10880 : result = (*oend) (sem->semstate);
1180 [ - + ]: 10857 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1181 :UBC 0 : return result;
1182 : : }
1183 : :
1539 rhaas@postgresql.org 1184 :CBC 19808 : return JSON_SUCCESS;
1185 : : }
1186 : :
1187 : : static JsonParseErrorType
1542 1188 : 25941 : parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
1189 : : {
1190 : 25941 : json_aelem_action astart = sem->array_element_start;
1191 : 25941 : json_aelem_action aend = sem->array_element_end;
1192 : 25941 : JsonTokenType tok = lex_peek(lex);
1193 : : JsonParseErrorType result;
1194 : : bool isnull;
1195 : :
1196 : 25941 : isnull = tok == JSON_TOKEN_NULL;
1197 : :
1198 [ + + ]: 25941 : if (astart != NULL)
1199 : : {
490 tgl@sss.pgh.pa.us 1200 : 3890 : result = (*astart) (sem->semstate, isnull);
1201 [ - + ]: 3890 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1202 :UBC 0 : return result;
1203 : : }
1204 : :
1205 : : /* an array element is any object, array or scalar */
1542 rhaas@postgresql.org 1206 [ + + + ]:CBC 25941 : switch (tok)
1207 : : {
1208 : 8110 : case JSON_TOKEN_OBJECT_START:
1539 1209 : 8110 : result = parse_object(lex, sem);
1542 1210 : 8081 : break;
1211 : 6064 : case JSON_TOKEN_ARRAY_START:
1539 1212 : 6064 : result = parse_array(lex, sem);
1542 1213 : 1646 : break;
1214 : 11767 : default:
1539 1215 : 11767 : result = parse_scalar(lex, sem);
1216 : : }
1217 : :
1218 [ + + ]: 21485 : if (result != JSON_SUCCESS)
1219 : 33 : return result;
1220 : :
1542 1221 [ + + ]: 21452 : if (aend != NULL)
1222 : : {
490 tgl@sss.pgh.pa.us 1223 : 3635 : result = (*aend) (sem->semstate, isnull);
1224 [ - + ]: 3629 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1225 :UBC 0 : return result;
1226 : : }
1227 : :
1539 rhaas@postgresql.org 1228 :CBC 21446 : return JSON_SUCCESS;
1229 : : }
1230 : :
1231 : : static JsonParseErrorType
1542 1232 : 16712 : parse_array(JsonLexContext *lex, JsonSemAction *sem)
1233 : : {
1234 : : /*
1235 : : * an array is a possibly empty sequence of array elements, separated by
1236 : : * commas and surrounded by square brackets.
1237 : : */
1238 : 16712 : json_struct_action astart = sem->array_start;
1239 : 16712 : json_struct_action aend = sem->array_end;
1240 : : JsonParseErrorType result;
1241 : :
1242 : : #ifndef FRONTEND
1243 : 16686 : check_stack_depth();
1244 : : #endif
1245 : :
1246 [ + + ]: 16706 : if (astart != NULL)
1247 : : {
490 tgl@sss.pgh.pa.us 1248 : 7608 : result = (*astart) (sem->semstate);
1249 [ - + ]: 7601 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1250 :UBC 0 : return result;
1251 : : }
1252 : :
1253 : : /*
1254 : : * Data inside an array is at a higher nesting level than the array
1255 : : * itself. Note that we increment this after we call the semantic routine
1256 : : * for the array start and restore it before we call the routine for the
1257 : : * array end.
1258 : : */
1542 rhaas@postgresql.org 1259 :CBC 16699 : lex->lex_level++;
1260 : :
1539 1261 : 16699 : result = lex_expect(JSON_PARSE_ARRAY_START, lex, JSON_TOKEN_ARRAY_START);
1262 [ + - + + ]: 16699 : if (result == JSON_SUCCESS && lex_peek(lex) != JSON_TOKEN_ARRAY_END)
1263 : : {
1264 : 13131 : result = parse_array_element(lex, sem);
1265 : :
1266 [ + + + + ]: 21455 : while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
1267 : : {
1268 : 12786 : result = json_lex(lex);
1269 [ - + ]: 12786 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 1270 :UBC 0 : break;
1539 rhaas@postgresql.org 1271 :CBC 12786 : result = parse_array_element(lex, sem);
1272 : : }
1273 : : }
1274 [ + + ]: 12237 : if (result != JSON_SUCCESS)
1275 : 33 : return result;
1276 : :
1277 : 12204 : result = lex_expect(JSON_PARSE_ARRAY_NEXT, lex, JSON_TOKEN_ARRAY_END);
1278 [ + + ]: 12204 : if (result != JSON_SUCCESS)
1279 : 12 : return result;
1280 : :
1542 1281 : 12192 : lex->lex_level--;
1282 : :
1283 [ + + ]: 12192 : if (aend != NULL)
1284 : : {
490 tgl@sss.pgh.pa.us 1285 : 4290 : result = (*aend) (sem->semstate);
1286 [ - + ]: 4278 : if (result != JSON_SUCCESS)
490 tgl@sss.pgh.pa.us 1287 :UBC 0 : return result;
1288 : : }
1289 : :
1539 rhaas@postgresql.org 1290 :CBC 12180 : return JSON_SUCCESS;
1291 : : }
1292 : :
1293 : : /*
1294 : : * Lex one token from the input stream.
1295 : : *
1296 : : * When doing incremental parsing, we can reach the end of the input string
1297 : : * without having (or knowing we have) a complete token. If it's not the
1298 : : * final chunk of input, the partial token is then saved to the lex
1299 : : * structure's ptok StringInfo. On subsequent calls input is appended to this
1300 : : * buffer until we have something that we think is a complete token,
1301 : : * which is then lexed using a recursive call to json_lex. Processing then
1302 : : * continues as normal on subsequent calls.
1303 : : *
1304 : : * Note than when doing incremental processing, the lex.prev_token_terminator
1305 : : * should not be relied on. It could point into a previous input chunk or
1306 : : * worse.
1307 : : */
1308 : : JsonParseErrorType
1542 1309 : 3605152 : json_lex(JsonLexContext *lex)
1310 : : {
1311 : : char *s;
646 john.naylor@postgres 1312 : 3605152 : char *const end = lex->input + lex->input_length;
1313 : : JsonParseErrorType result;
1314 : :
35 andrew@dunslane.net 1315 [ + + + + ]:GNC 3605152 : if (lex->incremental && lex->inc_state->partial_completed)
1316 : : {
1317 : : /*
1318 : : * We just lexed a completed partial token on the last call, so reset
1319 : : * everything
1320 : : */
1321 : 8613 : resetStringInfo(&(lex->inc_state->partial_token));
1322 : 8613 : lex->token_terminator = lex->input;
1323 : 8613 : lex->inc_state->partial_completed = false;
1324 : : }
1325 : :
1542 rhaas@postgresql.org 1326 :CBC 3605152 : s = lex->token_terminator;
1327 : :
35 andrew@dunslane.net 1328 [ + + + + ]:GNC 3605152 : if (lex->incremental && lex->inc_state->partial_token.len)
1329 : : {
1330 : : /*
1331 : : * We have a partial token. Extend it and if completed lex it by a
1332 : : * recursive call
1333 : : */
1334 : 20748 : StringInfo ptok = &(lex->inc_state->partial_token);
1335 : 20748 : int added = 0;
1336 : 20748 : bool tok_done = false;
1337 : : JsonLexContext dummy_lex;
1338 : : JsonParseErrorType partial_result;
1339 : :
1340 [ + + ]: 20748 : if (ptok->data[0] == '"')
1341 : : {
1342 : : /*
1343 : : * It's a string. Accumulate characters until we reach an
1344 : : * unescaped '"'.
1345 : : */
1346 : 19907 : int escapes = 0;
1347 : :
1348 [ + + ]: 20195 : for (int i = ptok->len - 1; i > 0; i--)
1349 : : {
1350 : : /* count the trailing backslashes on the partial token */
1351 [ + + ]: 18874 : if (ptok->data[i] == '\\')
1352 : 288 : escapes++;
1353 : : else
1354 : 18586 : break;
1355 : : }
1356 : :
1357 [ + + ]: 150844 : for (int i = 0; i < lex->input_length; i++)
1358 : : {
1359 : 139008 : char c = lex->input[i];
1360 : :
1361 [ - + ]: 139008 : appendStringInfoCharMacro(ptok, c);
1362 : 139008 : added++;
1363 [ + + + + ]: 139008 : if (c == '"' && escapes % 2 == 0)
1364 : : {
1365 : 8071 : tok_done = true;
1366 : 8071 : break;
1367 : : }
1368 [ + + ]: 130937 : if (c == '\\')
1369 : 316 : escapes++;
1370 : : else
1371 : 130621 : escapes = 0;
1372 : : }
1373 : : }
1374 : : else
1375 : : {
1376 : : /* not a string */
1377 : 841 : char c = ptok->data[0];
1378 : :
1379 [ + - + - : 841 : if (c == '-' || (c >= '0' && c <= '9'))
+ + ]
1380 : : {
1381 : : /* for numbers look for possible numeric continuations */
1382 : :
1383 : 187 : bool numend = false;
1384 : :
1385 [ + + + + ]: 550 : for (int i = 0; i < lex->input_length && !numend; i++)
1386 : : {
1387 : 363 : char cc = lex->input[i];
1388 : :
1389 [ + + ]: 363 : switch (cc)
1390 : : {
1391 : 243 : case '+':
1392 : : case '-':
1393 : : case 'e':
1394 : : case 'E':
1395 : : case '0':
1396 : : case '1':
1397 : : case '2':
1398 : : case '3':
1399 : : case '4':
1400 : : case '5':
1401 : : case '6':
1402 : : case '7':
1403 : : case '8':
1404 : : case '9':
1405 : : {
1406 [ - + ]: 243 : appendStringInfoCharMacro(ptok, cc);
1407 : 243 : added++;
1408 : : }
1409 : 243 : break;
1410 : 120 : default:
1411 : 120 : numend = true;
1412 : : }
1413 : : }
1414 : : }
1415 : :
1416 : : /*
1417 : : * Add any remaining alphanumeric chars. This takes care of the
1418 : : * {null, false, true} literals as well as any trailing
1419 : : * alphanumeric junk on non-string tokens.
1420 : : */
1421 [ + + ]: 1722 : for (int i = added; i < lex->input_length; i++)
1422 : : {
1423 : 1478 : char cc = lex->input[i];
1424 : :
1425 [ + + + + : 1478 : if (JSON_ALPHANUMERIC_CHAR(cc))
+ + + - +
+ + - + -
- + ]
1426 : : {
1427 [ - + ]: 881 : appendStringInfoCharMacro(ptok, cc);
1428 : 881 : added++;
1429 : : }
1430 : : else
1431 : : {
1432 : 597 : tok_done = true;
1433 : 597 : break;
1434 : : }
1435 : : }
1436 [ + + ]: 841 : if (added == lex->input_length &&
1437 [ + + ]: 244 : lex->inc_state->is_last_chunk)
1438 : : {
1439 : 19 : tok_done = true;
1440 : : }
1441 : : }
1442 : :
1443 [ + + ]: 20748 : if (!tok_done)
1444 : : {
1445 : : /* We should have consumed the whole chunk in this case. */
1446 [ - + ]: 12061 : Assert(added == lex->input_length);
1447 : :
1448 [ + + ]: 12061 : if (!lex->inc_state->is_last_chunk)
1449 : 12053 : return JSON_INCOMPLETE;
1450 : :
1451 : : /* json_errdetail() needs access to the accumulated token. */
1452 : 8 : lex->token_start = ptok->data;
1453 : 8 : lex->token_terminator = ptok->data + ptok->len;
1454 : 8 : return JSON_INVALID_TOKEN;
1455 : : }
1456 : :
1457 : : /*
1458 : : * Everything up to lex->input[added] has been added to the partial
1459 : : * token, so move the input past it.
1460 : : */
1461 : 8687 : lex->input += added;
1462 : 8687 : lex->input_length -= added;
1463 : :
1464 : 8687 : dummy_lex.input = dummy_lex.token_terminator =
1465 : 8687 : dummy_lex.line_start = ptok->data;
1466 : 8687 : dummy_lex.line_number = lex->line_number;
1467 : 8687 : dummy_lex.input_length = ptok->len;
1468 : 8687 : dummy_lex.input_encoding = lex->input_encoding;
1469 : 8687 : dummy_lex.incremental = false;
1470 : 8687 : dummy_lex.strval = lex->strval;
1471 : :
1472 : 8687 : partial_result = json_lex(&dummy_lex);
1473 : :
1474 : : /*
1475 : : * We either have a complete token or an error. In either case we need
1476 : : * to point to the partial token data for the semantic or error
1477 : : * routines. If it's not an error we'll readjust on the next call to
1478 : : * json_lex.
1479 : : */
1480 : 8687 : lex->token_type = dummy_lex.token_type;
1481 : 8687 : lex->line_number = dummy_lex.line_number;
1482 : :
1483 : : /*
1484 : : * We know the prev_token_terminator must be back in some previous
1485 : : * piece of input, so we just make it NULL.
1486 : : */
1487 : 8687 : lex->prev_token_terminator = NULL;
1488 : :
1489 : : /*
1490 : : * Normally token_start would be ptok->data, but it could be later,
1491 : : * see json_lex_string's handling of invalid escapes.
1492 : : */
1493 : 8687 : lex->token_start = dummy_lex.token_start;
1494 : 8687 : lex->token_terminator = dummy_lex.token_terminator;
1495 [ + + ]: 8687 : if (partial_result == JSON_SUCCESS)
1496 : : {
1497 : : /* make sure we've used all the input */
1498 [ - + ]: 8660 : if (lex->token_terminator - lex->token_start != ptok->len)
1499 : : {
35 andrew@dunslane.net 1500 :UNC 0 : Assert(false);
1501 : : return JSON_INVALID_TOKEN;
1502 : : }
1503 : :
35 andrew@dunslane.net 1504 :GNC 8660 : lex->inc_state->partial_completed = true;
1505 : : }
1506 : 8687 : return partial_result;
1507 : : /* end of partial token processing */
1508 : : }
1509 : :
1510 : : /* Skip leading whitespace. */
646 john.naylor@postgres 1511 [ + + + + :CBC 6482258 : while (s < end && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
+ + + + -
+ ]
1512 : : {
1140 tgl@sss.pgh.pa.us 1513 [ + + ]: 2897854 : if (*s++ == '\n')
1514 : : {
1542 rhaas@postgresql.org 1515 : 192127 : ++lex->line_number;
1140 tgl@sss.pgh.pa.us 1516 : 192127 : lex->line_start = s;
1517 : : }
1518 : : }
1542 rhaas@postgresql.org 1519 : 3584404 : lex->token_start = s;
1520 : :
1521 : : /* Determine token type. */
646 john.naylor@postgres 1522 [ + + ]: 3584404 : if (s >= end)
1523 : : {
1542 rhaas@postgresql.org 1524 : 106654 : lex->token_start = NULL;
1525 : 106654 : lex->prev_token_terminator = lex->token_terminator;
1526 : 106654 : lex->token_terminator = s;
1527 : 106654 : lex->token_type = JSON_TOKEN_END;
1528 : : }
1529 : : else
1530 : : {
1531 [ + + + + : 3477750 : switch (*s)
+ + + + +
+ ]
1532 : : {
1533 : : /* Single-character token, some kind of punctuation mark. */
1534 : 121674 : case '{':
1535 : 121674 : lex->prev_token_terminator = lex->token_terminator;
1536 : 121674 : lex->token_terminator = s + 1;
1537 : 121674 : lex->token_type = JSON_TOKEN_OBJECT_START;
1538 : 121674 : break;
1539 : 117369 : case '}':
1540 : 117369 : lex->prev_token_terminator = lex->token_terminator;
1541 : 117369 : lex->token_terminator = s + 1;
1542 : 117369 : lex->token_type = JSON_TOKEN_OBJECT_END;
1543 : 117369 : break;
1544 : 632233 : case '[':
1545 : 632233 : lex->prev_token_terminator = lex->token_terminator;
1546 : 632233 : lex->token_terminator = s + 1;
1547 : 632233 : lex->token_type = JSON_TOKEN_ARRAY_START;
1548 : 632233 : break;
1549 : 218024 : case ']':
1550 : 218024 : lex->prev_token_terminator = lex->token_terminator;
1551 : 218024 : lex->token_terminator = s + 1;
1552 : 218024 : lex->token_type = JSON_TOKEN_ARRAY_END;
1553 : 218024 : break;
1554 : 586213 : case ',':
1555 : 586213 : lex->prev_token_terminator = lex->token_terminator;
1556 : 586213 : lex->token_terminator = s + 1;
1557 : 586213 : lex->token_type = JSON_TOKEN_COMMA;
1558 : 586213 : break;
1559 : 597246 : case ':':
1560 : 597246 : lex->prev_token_terminator = lex->token_terminator;
1561 : 597246 : lex->token_terminator = s + 1;
1562 : 597246 : lex->token_type = JSON_TOKEN_COLON;
1563 : 597246 : break;
1564 : 1028572 : case '"':
1565 : : /* string */
1539 1566 : 1028572 : result = json_lex_string(lex);
1567 [ + + ]: 1028572 : if (result != JSON_SUCCESS)
1568 : 8179 : return result;
1542 1569 : 1020393 : lex->token_type = JSON_TOKEN_STRING;
1570 : 1020393 : break;
1571 : 92 : case '-':
1572 : : /* Negative number. */
1539 1573 : 92 : result = json_lex_number(lex, s + 1, NULL, NULL);
1574 [ - + ]: 92 : if (result != JSON_SUCCESS)
1539 rhaas@postgresql.org 1575 :UBC 0 : return result;
1542 rhaas@postgresql.org 1576 :CBC 92 : lex->token_type = JSON_TOKEN_NUMBER;
1577 : 92 : break;
1578 : 157986 : case '0':
1579 : : case '1':
1580 : : case '2':
1581 : : case '3':
1582 : : case '4':
1583 : : case '5':
1584 : : case '6':
1585 : : case '7':
1586 : : case '8':
1587 : : case '9':
1588 : : /* Positive number. */
1539 1589 : 157986 : result = json_lex_number(lex, s, NULL, NULL);
1590 [ + + ]: 157986 : if (result != JSON_SUCCESS)
1591 : 154 : return result;
1542 1592 : 157832 : lex->token_type = JSON_TOKEN_NUMBER;
1593 : 157832 : break;
1594 : 18341 : default:
1595 : : {
1596 : : char *p;
1597 : :
1598 : : /*
1599 : : * We're not dealing with a string, number, legal
1600 : : * punctuation mark, or end of string. The only legal
1601 : : * tokens we might find here are true, false, and null,
1602 : : * but for error reporting purposes we scan until we see a
1603 : : * non-alphanumeric character. That way, we can report
1604 : : * the whole word as an unexpected token, rather than just
1605 : : * some unintuitive prefix thereof.
1606 : : */
646 john.naylor@postgres 1607 [ + + + + : 100578 : for (p = s; p < end && JSON_ALPHANUMERIC_CHAR(*p); p++)
+ + + + -
+ + + - +
- + - + ]
1608 : : /* skip */ ;
1609 : :
1610 : : /*
1611 : : * We got some sort of unexpected punctuation or an
1612 : : * otherwise unexpected character, so just complain about
1613 : : * that one character.
1614 : : */
1542 rhaas@postgresql.org 1615 [ + + ]: 18341 : if (p == s)
1616 : : {
1617 : 19 : lex->prev_token_terminator = lex->token_terminator;
1618 : 19 : lex->token_terminator = s + 1;
1539 1619 : 19 : return JSON_INVALID_TOKEN;
1620 : : }
1621 : :
35 andrew@dunslane.net 1622 [ + + + + ]:GNC 18322 : if (lex->incremental && !lex->inc_state->is_last_chunk &&
1623 [ + + ]: 1962 : p == lex->input + lex->input_length)
1624 : : {
1625 : 496 : appendBinaryStringInfo(
1626 : 496 : &(lex->inc_state->partial_token), s, end - s);
1627 : 496 : return JSON_INCOMPLETE;
1628 : : }
1629 : :
1630 : : /*
1631 : : * We've got a real alphanumeric token here. If it
1632 : : * happens to be true, false, or null, all is well. If
1633 : : * not, error out.
1634 : : */
1542 rhaas@postgresql.org 1635 :CBC 17826 : lex->prev_token_terminator = lex->token_terminator;
1636 : 17826 : lex->token_terminator = p;
1637 [ + + ]: 17826 : if (p - s == 4)
1638 : : {
1639 [ + + ]: 7903 : if (memcmp(s, "true", 4) == 0)
1640 : 3700 : lex->token_type = JSON_TOKEN_TRUE;
1641 [ + + ]: 4203 : else if (memcmp(s, "null", 4) == 0)
1642 : 4197 : lex->token_type = JSON_TOKEN_NULL;
1643 : : else
1539 1644 : 6 : return JSON_INVALID_TOKEN;
1645 : : }
1542 1646 [ + + + + ]: 9923 : else if (p - s == 5 && memcmp(s, "false", 5) == 0)
1647 : 9828 : lex->token_type = JSON_TOKEN_FALSE;
1648 : : else
1539 1649 : 95 : return JSON_INVALID_TOKEN;
1650 : : }
1651 : : } /* end of switch */
1652 : : }
1653 : :
35 andrew@dunslane.net 1654 [ + + + + :GNC 3575455 : if (lex->incremental && lex->token_type == JSON_TOKEN_END && !lex->inc_state->is_last_chunk)
+ + ]
1655 : 71835 : return JSON_INCOMPLETE;
1656 : : else
1657 : 3503620 : return JSON_SUCCESS;
1658 : : }
1659 : :
1660 : : /*
1661 : : * The next token in the input stream is known to be a string; lex it.
1662 : : *
1663 : : * If lex->strval isn't NULL, fill it with the decoded string.
1664 : : * Set lex->token_terminator to the end of the decoded input, and in
1665 : : * success cases, transfer its previous value to lex->prev_token_terminator.
1666 : : * Return JSON_SUCCESS or an error code.
1667 : : *
1668 : : * Note: be careful that all error exits advance lex->token_terminator
1669 : : * to the point after the character we detected the error on.
1670 : : */
1671 : : static inline JsonParseErrorType
1542 rhaas@postgresql.org 1672 :CBC 1028572 : json_lex_string(JsonLexContext *lex)
1673 : : {
1674 : : char *s;
646 john.naylor@postgres 1675 : 1028572 : char *const end = lex->input + lex->input_length;
1542 rhaas@postgresql.org 1676 : 1028572 : int hi_surrogate = -1;
1677 : :
1678 : : /* Convenience macros for error exits */
1679 : : #define FAIL_OR_INCOMPLETE_AT_CHAR_START(code) \
1680 : : do { \
1681 : : if (lex->incremental && !lex->inc_state->is_last_chunk) \
1682 : : { \
1683 : : appendBinaryStringInfo(&lex->inc_state->partial_token, \
1684 : : lex->token_start, end - lex->token_start); \
1685 : : return JSON_INCOMPLETE; \
1686 : : } \
1687 : : lex->token_terminator = s; \
1688 : : return code; \
1689 : : } while (0)
1690 : : #define FAIL_AT_CHAR_END(code) \
1691 : : do { \
1692 : : lex->token_terminator = \
1693 : : s + pg_encoding_mblen_bounded(lex->input_encoding, s); \
1694 : : return code; \
1695 : : } while (0)
1696 : :
1697 [ + + ]: 1028572 : if (lex->strval != NULL)
1698 : 980304 : resetStringInfo(lex->strval);
1699 : :
1700 [ - + ]: 1028572 : Assert(lex->input_length > 0);
1701 : 1028572 : s = lex->token_start;
1702 : : for (;;)
1703 : : {
1704 : 2057074 : s++;
1705 : : /* Premature end of the string. */
646 john.naylor@postgres 1706 [ + + ]: 2057074 : if (s >= end)
35 andrew@dunslane.net 1707 [ + + + + ]:GNC 8056 : FAIL_OR_INCOMPLETE_AT_CHAR_START(JSON_INVALID_TOKEN);
642 john.naylor@postgres 1708 [ + + ]:CBC 2049018 : else if (*s == '"')
1709 : 1020393 : break;
1542 rhaas@postgresql.org 1710 [ + + ]: 1028625 : else if (*s == '\\')
1711 : : {
1712 : : /* OK, we have an escape character. */
1713 : 1000 : s++;
646 john.naylor@postgres 1714 [ + + ]: 1000 : if (s >= end)
35 andrew@dunslane.net 1715 [ + - + - ]:GNC 22 : FAIL_OR_INCOMPLETE_AT_CHAR_START(JSON_INVALID_TOKEN);
1542 rhaas@postgresql.org 1716 [ + + ]:CBC 978 : else if (*s == 'u')
1717 : : {
1718 : : int i;
1719 : 505 : int ch = 0;
1720 : :
1721 [ + + ]: 2461 : for (i = 1; i <= 4; i++)
1722 : : {
1723 : 1982 : s++;
646 john.naylor@postgres 1724 [ + + ]: 1982 : if (s >= end)
35 andrew@dunslane.net 1725 [ + - + - ]:GNC 8 : FAIL_OR_INCOMPLETE_AT_CHAR_START(JSON_INVALID_TOKEN);
1542 rhaas@postgresql.org 1726 [ + + + + ]:CBC 1974 : else if (*s >= '0' && *s <= '9')
1727 : 1078 : ch = (ch * 16) + (*s - '0');
1728 [ + + + + ]: 896 : else if (*s >= 'a' && *s <= 'f')
1729 : 866 : ch = (ch * 16) + (*s - 'a') + 10;
1730 [ + + + + ]: 30 : else if (*s >= 'A' && *s <= 'F')
1731 : 12 : ch = (ch * 16) + (*s - 'A') + 10;
1732 : : else
398 tgl@sss.pgh.pa.us 1733 : 18 : FAIL_AT_CHAR_END(JSON_UNICODE_ESCAPE_FORMAT);
1734 : : }
1542 rhaas@postgresql.org 1735 [ + + ]: 479 : if (lex->strval != NULL)
1736 : : {
1737 : : /*
1738 : : * Combine surrogate pairs.
1739 : : */
1500 tgl@sss.pgh.pa.us 1740 [ + + ]: 107 : if (is_utf16_surrogate_first(ch))
1741 : : {
1542 rhaas@postgresql.org 1742 [ + + ]: 36 : if (hi_surrogate != -1)
398 tgl@sss.pgh.pa.us 1743 : 6 : FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_SURROGATE);
1500 1744 : 30 : hi_surrogate = ch;
1542 rhaas@postgresql.org 1745 : 30 : continue;
1746 : : }
1500 tgl@sss.pgh.pa.us 1747 [ + + ]: 71 : else if (is_utf16_surrogate_second(ch))
1748 : : {
1542 rhaas@postgresql.org 1749 [ + + ]: 30 : if (hi_surrogate == -1)
398 tgl@sss.pgh.pa.us 1750 : 12 : FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
1500 1751 : 18 : ch = surrogate_pair_to_codepoint(hi_surrogate, ch);
1542 rhaas@postgresql.org 1752 : 18 : hi_surrogate = -1;
1753 : : }
1754 : :
1755 [ - + ]: 59 : if (hi_surrogate != -1)
398 tgl@sss.pgh.pa.us 1756 :UBC 0 : FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
1757 : :
1758 : : /*
1759 : : * Reject invalid cases. We can't have a value above
1760 : : * 0xFFFF here (since we only accepted 4 hex digits
1761 : : * above), so no need to test for out-of-range chars.
1762 : : */
1542 rhaas@postgresql.org 1763 [ + + ]:CBC 59 : if (ch == 0)
1764 : : {
1765 : : /* We can't allow this, since our TEXT type doesn't */
398 tgl@sss.pgh.pa.us 1766 : 12 : FAIL_AT_CHAR_END(JSON_UNICODE_CODE_POINT_ZERO);
1767 : : }
1768 : :
1769 : : /*
1770 : : * Add the represented character to lex->strval. In the
1771 : : * backend, we can let pg_unicode_to_server_noerror()
1772 : : * handle any required character set conversion; in
1773 : : * frontend, we can only deal with trivial conversions.
1774 : : */
1775 : : #ifndef FRONTEND
1776 : : {
1777 : : char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
1778 : :
490 1779 [ - + ]: 42 : if (!pg_unicode_to_server_noerror(ch, (unsigned char *) cbuf))
398 tgl@sss.pgh.pa.us 1780 :UBC 0 : FAIL_AT_CHAR_END(JSON_UNICODE_UNTRANSLATABLE);
1500 tgl@sss.pgh.pa.us 1781 :CBC 42 : appendStringInfoString(lex->strval, cbuf);
1782 : : }
1783 : : #else
1500 tgl@sss.pgh.pa.us 1784 [ + - ]:GBC 5 : if (lex->input_encoding == PG_UTF8)
1785 : : {
1786 : : /* OK, we can map the code point to UTF8 easily */
1787 : : char utf8str[5];
1788 : : int utf8len;
1789 : :
1542 rhaas@postgresql.org 1790 : 5 : unicode_to_utf8(ch, (unsigned char *) utf8str);
1791 : 5 : utf8len = pg_utf_mblen((unsigned char *) utf8str);
1792 : 5 : appendBinaryStringInfo(lex->strval, utf8str, utf8len);
1793 : : }
1542 rhaas@postgresql.org 1794 [ # # ]:UBC 0 : else if (ch <= 0x007f)
1795 : : {
1796 : : /* The ASCII range is the same in all encodings */
1797 : 0 : appendStringInfoChar(lex->strval, (char) ch);
1798 : : }
1799 : : else
398 tgl@sss.pgh.pa.us 1800 : 0 : FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_ESCAPE);
1801 : : #endif /* FRONTEND */
1802 : : }
1803 : : }
1542 rhaas@postgresql.org 1804 [ + + ]:CBC 473 : else if (lex->strval != NULL)
1805 : : {
1806 [ - + ]: 192 : if (hi_surrogate != -1)
398 tgl@sss.pgh.pa.us 1807 :UBC 0 : FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
1808 : :
1542 rhaas@postgresql.org 1809 [ + + - + :CBC 192 : switch (*s)
- - + ]
1810 : : {
1811 : 144 : case '"':
1812 : : case '\\':
1813 : : case '/':
1814 : 144 : appendStringInfoChar(lex->strval, *s);
1815 : 144 : break;
1816 : 18 : case 'b':
1817 : 18 : appendStringInfoChar(lex->strval, '\b');
1818 : 18 : break;
1542 rhaas@postgresql.org 1819 :UBC 0 : case 'f':
1820 : 0 : appendStringInfoChar(lex->strval, '\f');
1821 : 0 : break;
1542 rhaas@postgresql.org 1822 :CBC 27 : case 'n':
1823 : 27 : appendStringInfoChar(lex->strval, '\n');
1824 : 27 : break;
1542 rhaas@postgresql.org 1825 :UBC 0 : case 'r':
1826 : 0 : appendStringInfoChar(lex->strval, '\r');
1827 : 0 : break;
1828 : 0 : case 't':
1829 : 0 : appendStringInfoChar(lex->strval, '\t');
1830 : 0 : break;
1542 rhaas@postgresql.org 1831 :CBC 3 : default:
1832 : :
1833 : : /*
1834 : : * Not a valid string escape, so signal error. We
1835 : : * adjust token_start so that just the escape sequence
1836 : : * is reported, not the whole string.
1837 : : */
1539 1838 : 3 : lex->token_start = s;
398 tgl@sss.pgh.pa.us 1839 : 3 : FAIL_AT_CHAR_END(JSON_ESCAPING_INVALID);
1840 : : }
1841 : : }
1542 rhaas@postgresql.org 1842 [ + + ]: 281 : else if (strchr("\"\\/bfnrt", *s) == NULL)
1843 : : {
1844 : : /*
1845 : : * Simpler processing if we're not bothered about de-escaping
1846 : : *
1847 : : * It's very tempting to remove the strchr() call here and
1848 : : * replace it with a switch statement, but testing so far has
1849 : : * shown it's not a performance win.
1850 : : */
1539 1851 : 17 : lex->token_start = s;
398 tgl@sss.pgh.pa.us 1852 : 17 : FAIL_AT_CHAR_END(JSON_ESCAPING_INVALID);
1853 : : }
1854 : : }
1855 : : else
1856 : : {
592 john.naylor@postgres 1857 : 1027625 : char *p = s;
1858 : :
1542 rhaas@postgresql.org 1859 [ + + ]: 1027625 : if (hi_surrogate != -1)
398 tgl@sss.pgh.pa.us 1860 : 6 : FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
1861 : :
1862 : : /*
1863 : : * Skip to the first byte that requires special handling, so we
1864 : : * can batch calls to appendBinaryStringInfo.
1865 : : */
592 john.naylor@postgres 1866 : 1027619 : while (p < end - sizeof(Vector8) &&
1867 [ + + ]: 1253672 : !pg_lfind8('\\', (uint8 *) p, sizeof(Vector8)) &&
1868 [ + + + + ]: 2541053 : !pg_lfind8('"', (uint8 *) p, sizeof(Vector8)) &&
1869 [ + - ]: 260347 : !pg_lfind8_le(31, (uint8 *) p, sizeof(Vector8)))
1870 : 260347 : p += sizeof(Vector8);
1871 : :
1872 [ + + ]: 8100378 : for (; p < end; p++)
1873 : : {
653 1874 [ + + + + ]: 8093620 : if (*p == '\\' || *p == '"')
1875 : : break;
592 1876 [ + + ]: 7072778 : else if ((unsigned char) *p <= 31)
1877 : : {
1878 : : /* Per RFC4627, these characters MUST be escaped. */
1879 : : /*
1880 : : * Since *p isn't printable, exclude it from the context
1881 : : * string
1882 : : */
653 1883 : 19 : lex->token_terminator = p;
1884 : 19 : return JSON_ESCAPING_REQUIRED;
1885 : : }
1886 : : }
1887 : :
1888 [ + + ]: 1027600 : if (lex->strval != NULL)
1889 : 980354 : appendBinaryStringInfo(lex->strval, s, p - s);
1890 : :
1891 : : /*
1892 : : * s will be incremented at the top of the loop, so set it to just
1893 : : * behind our lookahead position
1894 : : */
1895 : 1027600 : s = p - 1;
1896 : : }
1897 : : }
1898 : :
642 1899 [ - + ]: 1020393 : if (hi_surrogate != -1)
1900 : : {
398 tgl@sss.pgh.pa.us 1901 :UBC 0 : lex->token_terminator = s + 1;
642 john.naylor@postgres 1902 : 0 : return JSON_UNICODE_LOW_SURROGATE;
1903 : : }
1904 : :
1905 : : /* Hooray, we found the end of the string! */
642 john.naylor@postgres 1906 :CBC 1020393 : lex->prev_token_terminator = lex->token_terminator;
1907 : 1020393 : lex->token_terminator = s + 1;
1908 : 1020393 : return JSON_SUCCESS;
1909 : :
1910 : : #undef FAIL_OR_INCOMPLETE_AT_CHAR_START
1911 : : #undef FAIL_AT_CHAR_END
1912 : : }
1913 : :
1914 : : /*
1915 : : * The next token in the input stream is known to be a number; lex it.
1916 : : *
1917 : : * In JSON, a number consists of four parts:
1918 : : *
1919 : : * (1) An optional minus sign ('-').
1920 : : *
1921 : : * (2) Either a single '0', or a string of one or more digits that does not
1922 : : * begin with a '0'.
1923 : : *
1924 : : * (3) An optional decimal part, consisting of a period ('.') followed by
1925 : : * one or more digits. (Note: While this part can be omitted
1926 : : * completely, it's not OK to have only the decimal point without
1927 : : * any digits afterwards.)
1928 : : *
1929 : : * (4) An optional exponent part, consisting of 'e' or 'E', optionally
1930 : : * followed by '+' or '-', followed by one or more digits. (Note:
1931 : : * As with the decimal part, if 'e' or 'E' is present, it must be
1932 : : * followed by at least one digit.)
1933 : : *
1934 : : * The 's' argument to this function points to the ostensible beginning
1935 : : * of part 2 - i.e. the character after any optional minus sign, or the
1936 : : * first character of the string if there is none.
1937 : : *
1938 : : * If num_err is not NULL, we return an error flag to *num_err rather than
1939 : : * raising an error for a badly-formed number. Also, if total_len is not NULL
1940 : : * the distance from lex->input to the token end+1 is returned to *total_len.
1941 : : */
1942 : : static inline JsonParseErrorType
1542 rhaas@postgresql.org 1943 : 158101 : json_lex_number(JsonLexContext *lex, char *s,
1944 : : bool *num_err, int *total_len)
1945 : : {
1946 : 158101 : bool error = false;
1947 : 158101 : int len = s - lex->input;
1948 : :
1949 : : /* Part (1): leading sign indicator. */
1950 : : /* Caller already did this for us; so do nothing. */
1951 : :
1952 : : /* Part (2): parse main digit string. */
1953 [ + - + + ]: 158101 : if (len < lex->input_length && *s == '0')
1954 : : {
1955 : 24960 : s++;
1956 : 24960 : len++;
1957 : : }
1958 [ + - + - : 133141 : else if (len < lex->input_length && *s >= '1' && *s <= '9')
+ + ]
1959 : : {
1960 : : do
1961 : : {
1962 : 454326 : s++;
1963 : 454326 : len++;
1964 [ + + + + : 454326 : } while (len < lex->input_length && *s >= '0' && *s <= '9');
+ + ]
1965 : : }
1966 : : else
1967 : 1 : error = true;
1968 : :
1969 : : /* Part (3): parse optional decimal portion. */
1970 [ + + + + ]: 158101 : if (len < lex->input_length && *s == '.')
1971 : : {
1972 : 18707 : s++;
1973 : 18707 : len++;
1974 [ + - + - : 18707 : if (len == lex->input_length || *s < '0' || *s > '9')
+ + ]
1975 : 6 : error = true;
1976 : : else
1977 : : {
1978 : : do
1979 : : {
1980 : 45988 : s++;
1981 : 45988 : len++;
1982 [ + + + + : 45988 : } while (len < lex->input_length && *s >= '0' && *s <= '9');
+ + ]
1983 : : }
1984 : : }
1985 : :
1986 : : /* Part (4): parse optional exponent. */
1987 [ + + + + : 158101 : if (len < lex->input_length && (*s == 'e' || *s == 'E'))
+ + ]
1988 : : {
1989 : 47 : s++;
1990 : 47 : len++;
1991 [ + - + + : 47 : if (len < lex->input_length && (*s == '+' || *s == '-'))
+ + ]
1992 : : {
1993 : 5 : s++;
1994 : 5 : len++;
1995 : : }
1996 [ + - + - : 47 : if (len == lex->input_length || *s < '0' || *s > '9')
+ + ]
1997 : 6 : error = true;
1998 : : else
1999 : : {
2000 : : do
2001 : : {
2002 : 142 : s++;
2003 : 142 : len++;
2004 [ + + + - : 142 : } while (len < lex->input_length && *s >= '0' && *s <= '9');
+ + ]
2005 : : }
2006 : : }
2007 : :
2008 : : /*
2009 : : * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
2010 : : * here should be considered part of the token for error-reporting
2011 : : * purposes.
2012 : : */
2013 [ + + + + : 158203 : for (; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*s); s++, len++)
+ + + + -
+ + + + +
- + - + ]
2014 : 102 : error = true;
2015 : :
2016 [ + + ]: 158101 : if (total_len != NULL)
2017 : 23 : *total_len = len;
2018 : :
35 andrew@dunslane.net 2019 [ + + + + ]:GNC 158101 : if (lex->incremental && !lex->inc_state->is_last_chunk &&
2020 [ + + ]: 50472 : len >= lex->input_length)
2021 : : {
2022 : 120 : appendBinaryStringInfo(&lex->inc_state->partial_token,
2023 : 120 : lex->token_start, s - lex->token_start);
9 2024 [ - + ]: 120 : if (num_err != NULL)
9 andrew@dunslane.net 2025 :UNC 0 : *num_err = error;
2026 : :
35 andrew@dunslane.net 2027 :GNC 120 : return JSON_INCOMPLETE;
2028 : : }
2029 [ + + ]: 157981 : else if (num_err != NULL)
2030 : : {
2031 : : /* let the caller handle any error */
1542 rhaas@postgresql.org 2032 :CBC 23 : *num_err = error;
2033 : : }
2034 : : else
2035 : : {
2036 : : /* return token endpoint */
2037 : 157958 : lex->prev_token_terminator = lex->token_terminator;
2038 : 157958 : lex->token_terminator = s;
2039 : : /* handle error if any */
2040 [ + + ]: 157958 : if (error)
1539 2041 : 34 : return JSON_INVALID_TOKEN;
2042 : : }
2043 : :
2044 : 157947 : return JSON_SUCCESS;
2045 : : }
2046 : :
2047 : : /*
2048 : : * Report a parse error.
2049 : : *
2050 : : * lex->token_start and lex->token_terminator must identify the current token.
2051 : : */
2052 : : static JsonParseErrorType
1542 2053 : 272 : report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
2054 : : {
2055 : : /* Handle case where the input ended prematurely. */
2056 [ + + - + ]: 272 : if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END)
1539 2057 : 85 : return JSON_EXPECTED_MORE;
2058 : :
2059 : : /* Otherwise choose the error type based on the parsing context. */
2060 [ + + + + : 187 : switch (ctx)
+ + + + -
- ]
2061 : : {
2062 : 15 : case JSON_PARSE_END:
2063 : 15 : return JSON_EXPECTED_END;
2064 : 60 : case JSON_PARSE_VALUE:
2065 : 60 : return JSON_EXPECTED_JSON;
2066 : 25 : case JSON_PARSE_STRING:
2067 : 25 : return JSON_EXPECTED_STRING;
1539 rhaas@postgresql.org 2068 :GBC 7 : case JSON_PARSE_ARRAY_START:
2069 : 7 : return JSON_EXPECTED_ARRAY_FIRST;
2070 : 9 : case JSON_PARSE_ARRAY_NEXT:
2071 : 9 : return JSON_EXPECTED_ARRAY_NEXT;
1539 rhaas@postgresql.org 2072 :CBC 20 : case JSON_PARSE_OBJECT_START:
2073 : 20 : return JSON_EXPECTED_OBJECT_FIRST;
2074 : 25 : case JSON_PARSE_OBJECT_LABEL:
2075 : 25 : return JSON_EXPECTED_COLON;
2076 : 26 : case JSON_PARSE_OBJECT_NEXT:
2077 : 26 : return JSON_EXPECTED_OBJECT_NEXT;
1539 rhaas@postgresql.org 2078 :UBC 0 : case JSON_PARSE_OBJECT_COMMA:
2079 : 0 : return JSON_EXPECTED_STRING;
2080 : : }
2081 : :
2082 : : /*
2083 : : * We don't use a default: case, so that the compiler will warn about
2084 : : * unhandled enum values.
2085 : : */
1017 michael@paquier.xyz 2086 : 0 : Assert(false);
2087 : : return JSON_SUCCESS; /* silence stupider compilers */
2088 : : }
2089 : :
2090 : : /*
2091 : : * Construct an (already translated) detail message for a JSON error.
2092 : : *
2093 : : * The returned pointer should not be freed, the allocation is either static
2094 : : * or owned by the JsonLexContext.
2095 : : */
2096 : : char *
1539 rhaas@postgresql.org 2097 :CBC 461 : json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
2098 : : {
28 dgustafsson@postgres 2099 [ - + ]:GNC 461 : if (lex->errormsg)
28 dgustafsson@postgres 2100 :UNC 0 : resetStringInfo(lex->errormsg);
2101 : : else
28 dgustafsson@postgres 2102 :GNC 461 : lex->errormsg = makeStringInfo();
2103 : :
2104 : : /*
2105 : : * A helper for error messages that should print the current token. The
2106 : : * format must contain exactly one %.*s specifier.
2107 : : */
2108 : : #define token_error(lex, format) \
2109 : : appendStringInfo((lex)->errormsg, _(format), \
2110 : : (int) ((lex)->token_terminator - (lex)->token_start), \
2111 : : (lex)->token_start);
2112 : :
1539 rhaas@postgresql.org 2113 [ - - + + :CBC 461 : switch (error)
+ + + + +
+ + + + +
+ + + - -
+ + - - ]
2114 : : {
35 andrew@dunslane.net 2115 :UNC 0 : case JSON_INCOMPLETE:
1539 rhaas@postgresql.org 2116 :EUB : case JSON_SUCCESS:
2117 : : /* fall through to the error code after switch */
1539 rhaas@postgresql.org 2118 :UBC 0 : break;
35 andrew@dunslane.net 2119 :UNC 0 : case JSON_INVALID_LEXER_TYPE:
2120 [ # # ]: 0 : if (lex->incremental)
10 2121 : 0 : return _("Recursive descent parser cannot use incremental lexer");
2122 : : else
2123 : 0 : return _("Incremental parser requires incremental lexer");
35 andrew@dunslane.net 2124 :GNC 64 : case JSON_NESTING_TOO_DEEP:
2125 : 64 : return (_("JSON nested too deep, maximum permitted depth is 6400"));
1539 rhaas@postgresql.org 2126 :CBC 20 : case JSON_ESCAPING_INVALID:
28 dgustafsson@postgres 2127 :GNC 20 : token_error(lex, "Escape sequence \"\\%.*s\" is invalid.");
2128 : 20 : break;
1539 rhaas@postgresql.org 2129 :CBC 19 : case JSON_ESCAPING_REQUIRED:
28 dgustafsson@postgres 2130 :GNC 19 : appendStringInfo(lex->errormsg,
2131 : 19 : _("Character with value 0x%02x must be escaped."),
2132 : 19 : (unsigned char) *(lex->token_terminator));
2133 : 19 : break;
1539 rhaas@postgresql.org 2134 :CBC 15 : case JSON_EXPECTED_END:
28 dgustafsson@postgres 2135 :GNC 15 : token_error(lex, "Expected end of input, but found \"%.*s\".");
2136 : 15 : break;
1539 rhaas@postgresql.org 2137 :GBC 7 : case JSON_EXPECTED_ARRAY_FIRST:
28 dgustafsson@postgres 2138 :GNC 7 : token_error(lex, "Expected array element or \"]\", but found \"%.*s\".");
2139 : 7 : break;
1539 rhaas@postgresql.org 2140 :GBC 9 : case JSON_EXPECTED_ARRAY_NEXT:
28 dgustafsson@postgres 2141 :GNC 9 : token_error(lex, "Expected \",\" or \"]\", but found \"%.*s\".");
2142 : 9 : break;
1539 rhaas@postgresql.org 2143 :CBC 25 : case JSON_EXPECTED_COLON:
28 dgustafsson@postgres 2144 :GNC 25 : token_error(lex, "Expected \":\", but found \"%.*s\".");
2145 : 25 : break;
1539 rhaas@postgresql.org 2146 :CBC 33 : case JSON_EXPECTED_JSON:
28 dgustafsson@postgres 2147 :GNC 33 : token_error(lex, "Expected JSON value, but found \"%.*s\".");
2148 : 33 : break;
1539 rhaas@postgresql.org 2149 :CBC 47 : case JSON_EXPECTED_MORE:
2150 : 47 : return _("The input string ended unexpectedly.");
2151 : 20 : case JSON_EXPECTED_OBJECT_FIRST:
28 dgustafsson@postgres 2152 :GNC 20 : token_error(lex, "Expected string or \"}\", but found \"%.*s\".");
2153 : 20 : break;
1539 rhaas@postgresql.org 2154 :CBC 26 : case JSON_EXPECTED_OBJECT_NEXT:
28 dgustafsson@postgres 2155 :GNC 26 : token_error(lex, "Expected \",\" or \"}\", but found \"%.*s\".");
2156 : 26 : break;
1539 rhaas@postgresql.org 2157 :CBC 25 : case JSON_EXPECTED_STRING:
28 dgustafsson@postgres 2158 :GNC 25 : token_error(lex, "Expected string, but found \"%.*s\".");
2159 : 25 : break;
1539 rhaas@postgresql.org 2160 :CBC 97 : case JSON_INVALID_TOKEN:
28 dgustafsson@postgres 2161 :GNC 97 : token_error(lex, "Token \"%.*s\" is invalid.");
2162 : 97 : break;
1539 rhaas@postgresql.org 2163 :CBC 12 : case JSON_UNICODE_CODE_POINT_ZERO:
2164 : 12 : return _("\\u0000 cannot be converted to text.");
2165 : 18 : case JSON_UNICODE_ESCAPE_FORMAT:
2166 : 18 : return _("\"\\u\" must be followed by four hexadecimal digits.");
1539 rhaas@postgresql.org 2167 :UBC 0 : case JSON_UNICODE_HIGH_ESCAPE:
2168 : : /* note: this case is only reachable in frontend not backend */
1500 tgl@sss.pgh.pa.us 2169 : 0 : return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
490 2170 : 0 : case JSON_UNICODE_UNTRANSLATABLE:
2171 : :
2172 : : /*
2173 : : * Note: this case is only reachable in backend and not frontend.
2174 : : * #ifdef it away so the frontend doesn't try to link against
2175 : : * backend functionality.
2176 : : */
2177 : : #ifndef FRONTEND
2178 : 0 : return psprintf(_("Unicode escape value could not be translated to the server's encoding %s."),
2179 : : GetDatabaseEncodingName());
2180 : : #else
28 dgustafsson@postgres 2181 :UNC 0 : Assert(false);
2182 : : break;
2183 : : #endif
1539 rhaas@postgresql.org 2184 :CBC 6 : case JSON_UNICODE_HIGH_SURROGATE:
2185 : 6 : return _("Unicode high surrogate must not follow a high surrogate.");
2186 : 18 : case JSON_UNICODE_LOW_SURROGATE:
2187 : 18 : return _("Unicode low surrogate must follow a high surrogate.");
490 tgl@sss.pgh.pa.us 2188 :UBC 0 : case JSON_SEM_ACTION_FAILED:
2189 : : /* fall through to the error code after switch */
2190 : 0 : break;
2191 : : }
2192 : : #undef token_error
2193 : :
2194 : : /*
2195 : : * We don't use a default: case, so that the compiler will warn about
2196 : : * unhandled enum values. But this needs to be here anyway to cover the
2197 : : * possibility of an incorrect input.
2198 : : */
28 dgustafsson@postgres 2199 [ - + ]:GNC 296 : if (lex->errormsg->len == 0)
28 dgustafsson@postgres 2200 :UNC 0 : appendStringInfo(lex->errormsg,
2201 : 0 : _("unexpected json parse error type: %d"),
2202 : : (int) error);
2203 : :
28 dgustafsson@postgres 2204 :GNC 296 : return lex->errormsg->data;
2205 : : }
|