• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include <libwebsockets.h>
26 #include "private-lib-core.h"
27 #include <string.h>
28 #include <stdio.h>
29 
30 static const char * const parser_errs[] = {
31 	"",
32 	"",
33 	"No opening '{'",
34 	"Expected closing '}'",
35 	"Expected '\"'",
36 	"String underrun",
37 	"Illegal unescaped control char",
38 	"Illegal escape format",
39 	"Illegal hex number",
40 	"Expected ':'",
41 	"Illegal value start",
42 	"Digit required after decimal point",
43 	"Bad number format",
44 	"Bad exponent format",
45 	"Unknown token",
46 	"Too many ']'",
47 	"Mismatched ']'",
48 	"Expected ']'",
49 	"JSON nesting limit exceeded",
50 	"Nesting tracking used up",
51 	"Number too long",
52 	"Comma or block end expected",
53 	"Unknown",
54 	"Parser callback errored (see earlier error)",
55 };
56 
57 /**
58  * lejp_construct - prepare a struct lejp_ctx for use
59  *
60  * \param ctx:	pointer to your struct lejp_ctx
61  * \param callback:	your user callback which will received parsed tokens
62  * \param user:	optional user data pointer untouched by lejp
63  * \param paths:	your array of name elements you are interested in
64  * \param count_paths:	LWS_ARRAY_SIZE() of @paths
65  *
66  * Prepares your context struct for use with lejp
67  */
68 
69 void
lejp_construct(struct lejp_ctx * ctx,signed char (* callback)(struct lejp_ctx * ctx,char reason),void * user,const char * const * paths,unsigned char count_paths)70 lejp_construct(struct lejp_ctx *ctx,
71 	signed char (*callback)(struct lejp_ctx *ctx, char reason), void *user,
72 			const char * const *paths, unsigned char count_paths)
73 {
74 	ctx->st[0].s = 0;
75 	ctx->st[0].p = 0;
76 	ctx->st[0].i = 0;
77 	ctx->st[0].b = 0;
78 	ctx->sp = 0;
79 	ctx->ipos = 0;
80 	ctx->path_match = 0;
81 	ctx->path_stride = 0;
82 	ctx->path[0] = '\0';
83 	ctx->user = user;
84 	ctx->line = 1;
85 
86 	ctx->pst_sp = 0;
87 	ctx->pst[0].callback = callback;
88 	ctx->pst[0].paths = paths;
89 	ctx->pst[0].count_paths = count_paths;
90 	ctx->pst[0].user = NULL;
91 	ctx->pst[0].ppos = 0;
92 
93 	ctx->pst[0].callback(ctx, LEJPCB_CONSTRUCTED);
94 }
95 
96 /**
97  * lejp_destruct - retire a previously constructed struct lejp_ctx
98  *
99  * \param ctx:	pointer to your struct lejp_ctx
100  *
101  * lejp does not perform any allocations, but since your user code might, this
102  * provides a one-time LEJPCB_DESTRUCTED callback at destruction time where
103  * you can clean up in your callback.
104  */
105 
106 void
lejp_destruct(struct lejp_ctx * ctx)107 lejp_destruct(struct lejp_ctx *ctx)
108 {
109 	/* no allocations... just let callback know what it happening */
110 	ctx->pst[0].callback(ctx, LEJPCB_DESTRUCTED);
111 }
112 
113 /**
114  * lejp_change_callback - switch to a different callback from now on
115  *
116  * \param ctx:	pointer to your struct lejp_ctx
117  * \param callback:	your user callback which will received parsed tokens
118  *
119  * This tells the old callback it was destroyed, in case you want to take any
120  * action because that callback "lost focus", then changes to the new
121  * callback and tells it first that it was constructed, and then started.
122  *
123  * Changing callback is a cheap and powerful trick to split out handlers
124  * according to information earlier in the parse.  For example you may have
125  * a JSON pair "schema" whose value defines what can be expected for the rest
126  * of the JSON.  Rather than having one huge callback for all cases, you can
127  * have an initial one looking for "schema" which then calls
128  * lejp_change_callback() to a handler specific for the schema.
129  *
130  * Notice that afterwards, you need to construct the context again anyway to
131  * parse another JSON object, and the callback is reset then to the main,
132  * schema-interpreting one.  The construction action is very lightweight.
133  */
134 
135 void
lejp_change_callback(struct lejp_ctx * ctx,signed char (* callback)(struct lejp_ctx * ctx,char reason))136 lejp_change_callback(struct lejp_ctx *ctx,
137 		     signed char (*callback)(struct lejp_ctx *ctx, char reason))
138 {
139 	ctx->pst[0].callback(ctx, LEJPCB_DESTRUCTED);
140 	ctx->pst[0].callback = callback;
141 	ctx->pst[0].callback(ctx, LEJPCB_CONSTRUCTED);
142 	ctx->pst[0].callback(ctx, LEJPCB_START);
143 }
144 
145 void
lejp_check_path_match(struct lejp_ctx * ctx)146 lejp_check_path_match(struct lejp_ctx *ctx)
147 {
148 	const char *p, *q;
149 	int n;
150 	size_t s = sizeof(char *);
151 
152 	if (ctx->path_stride)
153 		s = ctx->path_stride;
154 
155 	/* we only need to check if a match is not active */
156 	for (n = 0; !ctx->path_match &&
157 	     n < ctx->pst[ctx->pst_sp].count_paths; n++) {
158 		ctx->wildcount = 0;
159 		p = ctx->path;
160 
161 		q = *((char **)(((char *)ctx->pst[ctx->pst_sp].paths) + (n * s)));
162 
163 		while (*p && *q) {
164 			if (*q != '*') {
165 				if (*p != *q)
166 					break;
167 				p++;
168 				q++;
169 				continue;
170 			}
171 			ctx->wild[ctx->wildcount++] = lws_ptr_diff(p, ctx->path);
172 			q++;
173 			/*
174 			 * if * has something after it, match to .
175 			 * if ends with *, eat everything.
176 			 * This implies match sequences must be ordered like
177 			 *  x.*.*
178 			 *  x.*
179 			 * if both options are possible
180 			 */
181 			while (*p && (*p != '.' || !*q))
182 				p++;
183 		}
184 		if (*p || *q)
185 			continue;
186 
187 		ctx->path_match = n + 1;
188 		ctx->path_match_len = ctx->pst[ctx->pst_sp].ppos;
189 		return;
190 	}
191 
192 	if (!ctx->path_match)
193 		ctx->wildcount = 0;
194 }
195 
196 int
lejp_get_wildcard(struct lejp_ctx * ctx,int wildcard,char * dest,int len)197 lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len)
198 {
199 	int n;
200 
201 	if (wildcard >= ctx->wildcount || !len)
202 		return 0;
203 
204 	n = ctx->wild[wildcard];
205 
206 	while (--len && n < ctx->pst[ctx->pst_sp].ppos &&
207 	       (n == ctx->wild[wildcard] || ctx->path[n] != '.'))
208 		*dest++ = ctx->path[n++];
209 
210 	*dest = '\0';
211 	n++;
212 
213 	return n - ctx->wild[wildcard];
214 }
215 
216 /**
217  * lejp_parse - interpret some more incoming data incrementally
218  *
219  * \param ctx:	previously constructed parsing context
220  * \param json:	char buffer with the new data to interpret
221  * \param len:	amount of data in the buffer
222  *
223  * Because lejp is a stream parser, it incrementally parses as new data
224  * becomes available, maintaining all state in the context struct.  So an
225  * incomplete JSON is a normal situation, getting you a LEJP_CONTINUE
226  * return, signalling there's no error but to call again with more data when
227  * it comes to complete the parsing.  Successful parsing completes with a
228  * 0 or positive integer indicating how much of the last input buffer was
229  * unused.
230  */
231 
232 int
lejp_parse(struct lejp_ctx * ctx,const unsigned char * json,int len)233 lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
234 {
235 	unsigned char c, n, s, ret = LEJP_REJECT_UNKNOWN;
236 	static const char esc_char[] = "\"\\/bfnrt";
237 	static const char esc_tran[] = "\"\\/\b\f\n\r\t";
238 	static const char tokens[] = "rue alse ull ";
239 
240 	if (!ctx->sp && !ctx->pst[ctx->pst_sp].ppos)
241 		ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_START);
242 
243 	while (len--) {
244 		c = *json++;
245 		s = ctx->st[ctx->sp].s;
246 
247 		/* skip whitespace unless we should care */
248 		if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '#') {
249 			if (c == '\n') {
250 				ctx->line++;
251 				ctx->st[ctx->sp].s &= ~LEJP_FLAG_WS_COMMENTLINE;
252 			}
253 			if (!(s & LEJP_FLAG_WS_KEEP)) {
254 				if (c == '#')
255 					ctx->st[ctx->sp].s |=
256 						LEJP_FLAG_WS_COMMENTLINE;
257 				continue;
258 			}
259 		}
260 
261 		if (ctx->st[ctx->sp].s & LEJP_FLAG_WS_COMMENTLINE)
262 			continue;
263 
264 		switch (s) {
265 		case LEJP_IDLE:
266 			if (c != '{') {
267 				ret = LEJP_REJECT_IDLE_NO_BRACE;
268 				goto reject;
269 			}
270 			if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_START)) {
271 				ret = LEJP_REJECT_CALLBACK;
272 				goto reject;
273 			}
274 			ctx->st[ctx->sp].s = LEJP_MEMBERS;
275 			break;
276 		case LEJP_MEMBERS:
277 			if (c == '}') {
278 				ctx->st[ctx->sp].s = LEJP_IDLE;
279 				ret = LEJP_REJECT_MEMBERS_NO_CLOSE;
280 				goto reject;
281 			}
282 			ctx->st[ctx->sp].s = LEJP_M_P;
283 			goto redo_character;
284 		case LEJP_M_P:
285 			if (c != '\"') {
286 				ret = LEJP_REJECT_MP_NO_OPEN_QUOTE;
287 				goto reject;
288 			}
289 			/* push */
290 			ctx->st[ctx->sp].s = LEJP_MP_DELIM;
291 			c = LEJP_MP_STRING;
292 			goto add_stack_level;
293 
294 		case LEJP_MP_STRING:
295 			if (c == '\"') {
296 				if (!ctx->sp) { /* JSON can't end on quote */
297 					ret = LEJP_REJECT_MP_STRING_UNDERRUN;
298 					goto reject;
299 				}
300 				if (ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
301 					ctx->buf[ctx->npos] = '\0';
302 					if (ctx->pst[ctx->pst_sp].callback(ctx,
303 						      LEJPCB_VAL_STR_END) < 0) {
304 						ret = LEJP_REJECT_CALLBACK;
305 						goto reject;
306 					}
307 				}
308 				/* pop */
309 				ctx->sp--;
310 				break;
311 			}
312 			if (c == '\\') {
313 				ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC;
314 				break;
315 			}
316 			if (c < ' ') {/* "control characters" not allowed */
317 				ret = LEJP_REJECT_MP_ILLEGAL_CTRL;
318 				goto reject;
319 			}
320 			goto emit_string_char;
321 
322 		case LEJP_MP_STRING_ESC:
323 			if (c == 'u') {
324 				ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC_U1;
325 				ctx->uni = 0;
326 				break;
327 			}
328 			for (n = 0; n < sizeof(esc_char); n++) {
329 				if (c != esc_char[n])
330 					continue;
331 				/* found it */
332 				c = esc_tran[n];
333 				ctx->st[ctx->sp].s = LEJP_MP_STRING;
334 				goto emit_string_char;
335 			}
336 			ret = LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC;
337 			/* illegal escape char */
338 			goto reject;
339 
340 		case LEJP_MP_STRING_ESC_U1:
341 		case LEJP_MP_STRING_ESC_U2:
342 		case LEJP_MP_STRING_ESC_U3:
343 		case LEJP_MP_STRING_ESC_U4:
344 			ctx->uni <<= 4;
345 			if (c >= '0' && c <= '9')
346 				ctx->uni |= c - '0';
347 			else
348 				if (c >= 'a' && c <= 'f')
349 					ctx->uni = c - 'a' + 10;
350 				else
351 					if (c >= 'A' && c <= 'F')
352 						ctx->uni = c - 'A' + 10;
353 					else {
354 						ret = LEJP_REJECT_ILLEGAL_HEX;
355 						goto reject;
356 					}
357 			ctx->st[ctx->sp].s++;
358 			switch (s) {
359 			case LEJP_MP_STRING_ESC_U2:
360 				if (ctx->uni < 0x08)
361 					break;
362 				/*
363 				 * 0x08-0xff (0x0800 - 0xffff)
364 				 * emit 3-byte UTF-8
365 				 */
366 				c = 0xe0 | ((ctx->uni >> 4) & 0xf);
367 				goto emit_string_char;
368 
369 			case LEJP_MP_STRING_ESC_U3:
370 				if (ctx->uni >= 0x080) {
371 					/*
372 					 * 0x080 - 0xfff (0x0800 - 0xffff)
373 					 * middle 3-byte seq
374 					 * send ....XXXXXX..
375 					 */
376 					c = 0x80 | ((ctx->uni >> 2) & 0x3f);
377 					goto emit_string_char;
378 				}
379 				if (ctx->uni < 0x008)
380 					break;
381 				/*
382 				 * 0x008 - 0x7f (0x0080 - 0x07ff)
383 				 * start 2-byte seq
384 				 */
385 				c = 0xc0 | (ctx->uni >> 2);
386 				goto emit_string_char;
387 
388 			case LEJP_MP_STRING_ESC_U4:
389 				if (ctx->uni >= 0x0080)
390 					/* end of 2 or 3-byte seq */
391 					c = 0x80 | (ctx->uni & 0x3f);
392 				else
393 					/* literal */
394 					c = (unsigned char)ctx->uni;
395 
396 				ctx->st[ctx->sp].s = LEJP_MP_STRING;
397 				goto emit_string_char;
398 			default:
399 				break;
400 			}
401 			break;
402 
403 		case LEJP_MP_DELIM:
404 			if (c != ':') {
405 				ret = LEJP_REJECT_MP_DELIM_MISSING_COLON;
406 				goto reject;
407 			}
408 			ctx->st[ctx->sp].s = LEJP_MP_VALUE;
409 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
410 
411 			lejp_check_path_match(ctx);
412 			if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_PAIR_NAME)) {
413 				ret = LEJP_REJECT_CALLBACK;
414 				goto reject;
415 			}
416 			break;
417 
418 		case LEJP_MP_VALUE:
419 			if (c >= '0' && c <= '9') {
420 				ctx->npos = 0;
421 				ctx->dcount = 0;
422 				ctx->f = 0;
423 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
424 				goto redo_character;
425 			}
426 			switch (c) {
427 			case'\"':
428 				/* push */
429 				ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
430 				c = LEJP_MP_STRING;
431 				ctx->npos = 0;
432 				ctx->buf[0] = '\0';
433 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_STR_START)) {
434 					ret = LEJP_REJECT_CALLBACK;
435 					goto reject;
436 				}
437 				goto add_stack_level;
438 
439 			case '{':
440 				/* push */
441 				ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
442 				c = LEJP_MEMBERS;
443 				lejp_check_path_match(ctx);
444 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_START)) {
445 					ret = LEJP_REJECT_CALLBACK;
446 					goto reject;
447 				}
448 				ctx->path_match = 0;
449 				goto add_stack_level;
450 
451 			case '[':
452 				/* push */
453 				ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END;
454 				c = LEJP_MP_VALUE;
455 				ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '[';
456 				ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']';
457 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
458 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) {
459 					ret = LEJP_REJECT_CALLBACK;
460 					goto reject;
461 				}
462 				ctx->i[ctx->ipos++] = 0;
463 				if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
464 					ret = LEJP_REJECT_MP_DELIM_ISTACK;
465 					goto reject;
466 				}
467 				goto add_stack_level;
468 
469 			case ']':
470 				/* pop */
471 				if (!ctx->sp) { /* JSON can't end on ] */
472 					ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
473 					goto reject;
474 				}
475 				ctx->sp--;
476 				if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
477 					ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
478 					goto reject;
479 				}
480 				/* drop the path [n] bit */
481 				if (ctx->sp) {
482 					ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p;
483 					ctx->ipos = ctx->st[ctx->sp - 1].i;
484 				}
485 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
486 				if (ctx->path_match &&
487 				    ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
488 					/*
489 					 * we shrank the path to be
490 					 * smaller than the matching point
491 					 */
492 					ctx->path_match = 0;
493 				goto array_end;
494 
495 			case 't': /* true */
496 				ctx->uni = 0;
497 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
498 				break;
499 
500 			case 'f':
501 				ctx->uni = 4;
502 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
503 				break;
504 
505 			case 'n':
506 				ctx->uni = 4 + 5;
507 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
508 				break;
509 			default:
510 				ret = LEJP_REJECT_MP_DELIM_BAD_VALUE_START;
511 				goto reject;
512 			}
513 			break;
514 
515 		case LEJP_MP_VALUE_NUM_INT:
516 			if (!ctx->npos && c == '-') {
517 				ctx->f |= LEJP_SEEN_MINUS;
518 				goto append_npos;
519 			}
520 
521 			if (ctx->dcount < 20 && c >= '0' && c <= '9') {
522 				if (ctx->f & LEJP_SEEN_POINT)
523 					ctx->f |= LEJP_SEEN_POST_POINT;
524 				ctx->dcount++;
525 				goto append_npos;
526 			}
527 			if (c == '.') {
528 				if (!ctx->dcount || (ctx->f & LEJP_SEEN_POINT)) {
529 					ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
530 					goto reject;
531 				}
532 				ctx->f |= LEJP_SEEN_POINT;
533 				goto append_npos;
534 			}
535 			/*
536 			 * before exponent, if we had . we must have had at
537 			 * least one more digit
538 			 */
539 			if ((ctx->f &
540 				(LEJP_SEEN_POINT | LEJP_SEEN_POST_POINT)) ==
541 							      LEJP_SEEN_POINT) {
542 				ret = LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC;
543 				goto reject;
544 			}
545 			if (c == 'e' || c == 'E') {
546 				if (ctx->f & LEJP_SEEN_EXP) {
547 					ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
548 					goto reject;
549 				}
550 				ctx->f |= LEJP_SEEN_EXP;
551 				ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_EXP;
552 				goto append_npos;
553 			}
554 			/* if none of the above, did we even have a number? */
555 			if (!ctx->dcount) {
556 				ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
557 				goto reject;
558 			}
559 
560 			ctx->buf[ctx->npos] = '\0';
561 			if (ctx->f & LEJP_SEEN_POINT) {
562 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_FLOAT)) {
563 					ret = LEJP_REJECT_CALLBACK;
564 					goto reject;
565 				}
566 			} else {
567 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_INT)) {
568 					ret = LEJP_REJECT_CALLBACK;
569 					goto reject;
570 				}
571 			}
572 
573 			/* then this is the post-number character, loop */
574 			ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
575 			goto redo_character;
576 
577 		case LEJP_MP_VALUE_NUM_EXP:
578 			ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
579 			if (c >= '0' && c <= '9')
580 				goto redo_character;
581 			if (c == '+' || c == '-')
582 				goto append_npos;
583 			ret = LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP;
584 			goto reject;
585 
586 		case LEJP_MP_VALUE_TOK: /* true, false, null */
587 			if (c != tokens[ctx->uni]) {
588 				ret = LEJP_REJECT_MP_VAL_TOK_UNKNOWN;
589 				goto reject;
590 			}
591 			ctx->uni++;
592 			if (tokens[ctx->uni] != ' ')
593 				break;
594 			switch (ctx->uni) {
595 			case 3:
596 				ctx->buf[0] = '1';
597 				ctx->buf[1] = '\0';
598 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_TRUE)) {
599 					ret = LEJP_REJECT_CALLBACK;
600 					goto reject;
601 				}
602 				break;
603 			case 8:
604 				ctx->buf[0] = '0';
605 				ctx->buf[1] = '\0';
606 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_FALSE)) {
607 					ret = LEJP_REJECT_CALLBACK;
608 					goto reject;
609 				}
610 				break;
611 			case 12:
612 				ctx->buf[0] = '\0';
613 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NULL)) {
614 					ret = LEJP_REJECT_CALLBACK;
615 					goto reject;
616 				}
617 				break;
618 			}
619 			ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
620 			break;
621 
622 		case LEJP_MP_COMMA_OR_END:
623 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
624 			if (c == ',') {
625 				/* increment this stack level's index */
626 				ctx->st[ctx->sp].s = LEJP_M_P;
627 				if (!ctx->sp) {
628 					ctx->pst[ctx->pst_sp].ppos = 0;
629 					/*
630 					 * since we came back to root level,
631 					 * no path can still match
632 					 */
633 					ctx->path_match = 0;
634 					break;
635 				}
636 				ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p;
637 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
638 				if (ctx->path_match &&
639 						ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
640 					/*
641 					 * we shrank the path to be
642 					 * smaller than the matching point
643 					 */
644 					ctx->path_match = 0;
645 
646 				if (ctx->st[ctx->sp - 1].s != LEJP_MP_ARRAY_END)
647 					break;
648 				/* top level is definitely an array... */
649 				if (ctx->ipos)
650 					ctx->i[ctx->ipos - 1]++;
651 				ctx->st[ctx->sp].s = LEJP_MP_VALUE;
652 				break;
653 			}
654 			if (c == ']') {
655 				if (!ctx->sp) {  /* JSON can't end on ] */
656 					ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
657 					goto reject;
658 				}
659 				/* pop */
660 				ctx->sp--;
661 				if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
662 					ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
663 					goto reject;
664 				}
665 				/* drop the path [n] bit */
666 				if (ctx->sp) {
667 					ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p;
668 					ctx->ipos = ctx->st[ctx->sp - 1].i;
669 				}
670 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
671 				if (ctx->path_match &&
672 						ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len)
673 					/*
674 					 * we shrank the path to be
675 					 * smaller than the matching point
676 					 */
677 					ctx->path_match = 0;
678 
679 				/* do LEJP_MP_ARRAY_END processing */
680 				goto redo_character;
681 			}
682 			if (c == '}') {
683 				if (!ctx->sp) {
684 					lejp_check_path_match(ctx);
685 					if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_END)) {
686 						ret = LEJP_REJECT_CALLBACK;
687 						goto reject;
688 					}
689 					if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_COMPLETE))
690 						goto reject;
691 					else
692 						/* done, return unused amount */
693 						return len;
694 				}
695 
696 				/* pop */
697 
698 				ctx->sp--;
699 				if (ctx->sp) {
700 					ctx->pst[ctx->pst_sp].ppos =
701 							ctx->st[ctx->sp].p;
702 					ctx->ipos = ctx->st[ctx->sp].i;
703 				}
704 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
705 				if (ctx->path_match &&
706 				    ctx->pst[ctx->pst_sp].ppos <=
707 						    ctx->path_match_len)
708 					/*
709 					 * we shrank the path to be
710 					 * smaller than the matching point
711 					 */
712 					ctx->path_match = 0;
713 
714 				lejp_check_path_match(ctx);
715 				if (ctx->pst[ctx->pst_sp].callback(ctx,
716 							LEJPCB_OBJECT_END)) {
717 					ret = LEJP_REJECT_CALLBACK;
718 					goto reject;
719 				}
720 				break;
721 			}
722 
723 			ret = LEJP_REJECT_MP_C_OR_E_NEITHER;
724 			goto reject;
725 
726 		case LEJP_MP_ARRAY_END:
727 array_end:
728 			ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
729 			if (c == ',') {
730 				/* increment this stack level's index */
731 				if (ctx->ipos)
732 					ctx->i[ctx->ipos - 1]++;
733 				ctx->st[ctx->sp].s = LEJP_MP_VALUE;
734 				if (ctx->sp)
735 					ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p;
736 				ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
737 				break;
738 			}
739 			if (c != ']') {
740 				ret = LEJP_REJECT_MP_ARRAY_END_MISSING;
741 				goto reject;
742 			}
743 
744 			ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
745 			ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_END);
746 			break;
747 		}
748 
749 		continue;
750 
751 emit_string_char:
752 		if (!ctx->sp || ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
753 			/* assemble the string value into chunks */
754 			ctx->buf[ctx->npos++] = c;
755 			if (ctx->npos == sizeof(ctx->buf) - 1) {
756 				if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_STR_CHUNK)) {
757 					ret = LEJP_REJECT_CALLBACK;
758 					goto reject;
759 				}
760 				ctx->npos = 0;
761 			}
762 			continue;
763 		}
764 		/* name part of name:value pair */
765 		ctx->path[ctx->pst[ctx->pst_sp].ppos++] = c;
766 		continue;
767 
768 add_stack_level:
769 		/* push on to the object stack */
770 		if (ctx->pst[ctx->pst_sp].ppos &&
771 		    ctx->st[ctx->sp].s != LEJP_MP_COMMA_OR_END &&
772 		    ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END)
773 			ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '.';
774 
775 		ctx->st[ctx->sp].p = ctx->pst[ctx->pst_sp].ppos;
776 		ctx->st[ctx->sp].i = ctx->ipos;
777 		if (++ctx->sp == LWS_ARRAY_SIZE(ctx->st)) {
778 			ret = LEJP_REJECT_STACK_OVERFLOW;
779 			goto reject;
780 		}
781 		ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0';
782 		ctx->st[ctx->sp].s = c;
783 		ctx->st[ctx->sp].b = 0;
784 		continue;
785 
786 append_npos:
787 		if (ctx->npos >= sizeof(ctx->buf)) {
788 			ret = LEJP_REJECT_NUM_TOO_LONG;
789 			goto reject;
790 		}
791 		ctx->buf[ctx->npos++] = c;
792 		continue;
793 
794 redo_character:
795 		json--;
796 		len++;
797 	}
798 
799 	return LEJP_CONTINUE;
800 
801 reject:
802 	ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_FAILED);
803 	return ret;
804 }
805 
806 int
807 lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths,
808 		 unsigned char paths_count, lejp_callback lejp_cb)
809 {
810 	struct _lejp_parsing_stack *p;
811 
812 	if (ctx->pst_sp + 1 == LEJP_MAX_PARSING_STACK_DEPTH)
813 		return -1;
814 
815 	lejp_check_path_match(ctx);
816 
817 	ctx->pst[ctx->pst_sp].path_match = ctx->path_match;
818 	ctx->pst_sp++;
819 
820 	p = &ctx->pst[ctx->pst_sp];
821 	p->user = user;
822 	p->callback = lejp_cb;
823 	p->paths = paths;
824 	p->count_paths = paths_count;
825 	p->ppos = 0;
826 
827 	ctx->path_match = 0;
828 	lejp_check_path_match(ctx);
829 
830 	lwsl_debug("%s: pushed parser stack to %d (path %s)\n", __func__,
831 		   ctx->pst_sp, ctx->path);
832 
833 	return 0;
834 }
835 
836 int
837 lejp_parser_pop(struct lejp_ctx *ctx)
838 {
839 	if (!ctx->pst_sp)
840 		return -1;
841 
842 	ctx->pst_sp--;
843 	lwsl_debug("%s: popped parser stack to %d\n", __func__, ctx->pst_sp);
844 
845 	ctx->path_match = 0; /* force it to check */
846 	lejp_check_path_match(ctx);
847 
848 	return 0;
849 }
850 
851 const char *
852 lejp_error_to_string(int e)
853 {
854 	if (e > 0)
855 		e = 0;
856 	else
857 		e = -e;
858 
859 	if (e >= (int)LWS_ARRAY_SIZE(parser_errs))
860 		return "Unknown error";
861 
862 	return parser_errs[e];
863 }
864