1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "zbxjson.h"
22 #include "json_parser.h"
23 #include "json.h"
24 #include "jsonpath.h"
25
26 /******************************************************************************
27 * *
28 * Function: zbx_json_strerror *
29 * *
30 * Purpose: return string describing json error *
31 * *
32 * Return value: pointer to the null terminated string *
33 * *
34 * Author: Eugene Grigorjev *
35 * *
36 ******************************************************************************/
37 #define ZBX_JSON_MAX_STRERROR 255
38
39 static ZBX_THREAD_LOCAL char zbx_json_strerror_message[ZBX_JSON_MAX_STRERROR];
40
zbx_json_strerror(void)41 const char *zbx_json_strerror(void)
42 {
43 return zbx_json_strerror_message;
44 }
45
zbx_set_json_strerror(const char * fmt,...)46 void zbx_set_json_strerror(const char *fmt, ...)
47 {
48 size_t sz;
49 va_list args;
50
51 va_start(args, fmt);
52
53 sz = zbx_vsnprintf(zbx_json_strerror_message, sizeof(zbx_json_strerror_message), fmt, args);
54
55 if (sizeof(zbx_json_strerror_message) - 1 == sz)
56 {
57 /* ensure that the string is not cut in the middle of UTF-8 sequence */
58 size_t idx = sz - 1;
59 while (0x80 == (0xc0 & zbx_json_strerror_message[idx]) && 0 < idx)
60 idx--;
61
62 if (zbx_utf8_char_len(zbx_json_strerror_message + idx) != sz - idx)
63 zbx_json_strerror_message[idx] = '\0';
64 }
65
66 va_end(args);
67 }
68
69 /******************************************************************************
70 * *
71 * Function: __zbx_json_realloc *
72 * *
73 * Author: Alexander Vladishev *
74 * *
75 ******************************************************************************/
__zbx_json_realloc(struct zbx_json * j,size_t need)76 static void __zbx_json_realloc(struct zbx_json *j, size_t need)
77 {
78 int realloc = 0;
79
80 if (NULL == j->buffer)
81 {
82 if (need > sizeof(j->buf_stat))
83 {
84 j->buffer_allocated = need;
85 j->buffer = (char *)zbx_malloc(j->buffer, j->buffer_allocated);
86 }
87 else
88 {
89 j->buffer_allocated = sizeof(j->buf_stat);
90 j->buffer = j->buf_stat;
91 }
92 return;
93 }
94
95 while (need > j->buffer_allocated)
96 {
97 if (0 == j->buffer_allocated)
98 j->buffer_allocated = 1024;
99 else
100 j->buffer_allocated *= 2;
101 realloc = 1;
102 }
103
104 if (1 == realloc)
105 {
106 if (j->buffer == j->buf_stat)
107 {
108 j->buffer = NULL;
109 j->buffer = (char *)zbx_malloc(j->buffer, j->buffer_allocated);
110 memcpy(j->buffer, j->buf_stat, sizeof(j->buf_stat));
111 }
112 else
113 j->buffer = (char *)zbx_realloc(j->buffer, j->buffer_allocated);
114 }
115 }
116
zbx_json_init(struct zbx_json * j,size_t allocate)117 void zbx_json_init(struct zbx_json *j, size_t allocate)
118 {
119 assert(j);
120
121 j->buffer = NULL;
122 j->buffer_allocated = 0;
123 j->buffer_offset = 0;
124 j->buffer_size = 0;
125 j->status = ZBX_JSON_EMPTY;
126 j->level = 0;
127 __zbx_json_realloc(j, allocate);
128 *j->buffer = '\0';
129
130 zbx_json_addobject(j, NULL);
131 }
132
zbx_json_initarray(struct zbx_json * j,size_t allocate)133 void zbx_json_initarray(struct zbx_json *j, size_t allocate)
134 {
135 assert(j);
136
137 j->buffer = NULL;
138 j->buffer_allocated = 0;
139 j->buffer_offset = 0;
140 j->buffer_size = 0;
141 j->status = ZBX_JSON_EMPTY;
142 j->level = 0;
143 __zbx_json_realloc(j, allocate);
144 *j->buffer = '\0';
145
146 zbx_json_addarray(j, NULL);
147 }
148
zbx_json_setempty(struct zbx_json * j)149 static void zbx_json_setempty(struct zbx_json *j)
150 {
151 j->buffer_offset = 0;
152 j->buffer_size = 0;
153 j->status = ZBX_JSON_EMPTY;
154 j->level = 0;
155 *j->buffer = '\0';
156 }
157
zbx_json_cleanarray(struct zbx_json * j)158 void zbx_json_cleanarray(struct zbx_json *j)
159 {
160 zbx_json_setempty(j);
161 zbx_json_addarray(j, NULL);
162 }
163
zbx_json_clean(struct zbx_json * j)164 void zbx_json_clean(struct zbx_json *j)
165 {
166 zbx_json_setempty(j);
167 zbx_json_addobject(j, NULL);
168 }
169
zbx_json_free(struct zbx_json * j)170 void zbx_json_free(struct zbx_json *j)
171 {
172 assert(j);
173
174 if (j->buffer != j->buf_stat)
175 zbx_free(j->buffer);
176 }
177
__zbx_json_stringsize(const char * string,zbx_json_type_t type)178 static size_t __zbx_json_stringsize(const char *string, zbx_json_type_t type)
179 {
180 size_t len = 0;
181 const char *sptr;
182 char buffer[] = {"null"};
183
184 for (sptr = (NULL != string ? string : buffer); '\0' != *sptr; sptr++)
185 {
186 switch (*sptr)
187 {
188 case '"': /* quotation mark */
189 case '\\': /* reverse solidus */
190 /* We do not escape '/' (solidus). https://www.rfc-editor.org/errata_search.php?rfc=4627 */
191 /* says: "/" and "\/" are both allowed and both produce the same result. */
192 case '\b': /* backspace */
193 case '\f': /* formfeed */
194 case '\n': /* newline */
195 case '\r': /* carriage return */
196 case '\t': /* horizontal tab */
197 len += 2;
198 break;
199 default:
200 /* RFC 8259 requires escaping control characters U+0000 - U+001F */
201 if (0x1f >= (unsigned char)*sptr)
202 len += 6;
203 else
204 len++;
205 }
206 }
207
208 if (NULL != string && ZBX_JSON_TYPE_STRING == type)
209 len += 2; /* "" */
210
211 return len;
212 }
213
214 /******************************************************************************
215 * *
216 * Function: zbx_num2hex *
217 * *
218 * Purpose: convert parameter c (0-15) to hexadecimal value ('0'-'f') *
219 * *
220 * Parameters: *
221 * c - number 0-15 *
222 * *
223 * Return value: *
224 * '0'-'f' *
225 * *
226 * Author: Alexander Vladishev *
227 * *
228 ******************************************************************************/
zbx_num2hex(unsigned char c)229 static char zbx_num2hex(unsigned char c)
230 {
231 if (c >= 10)
232 return (char)(c + 0x57); /* a-f */
233 else
234 return (char)(c + 0x30); /* 0-9 */
235 }
236
__zbx_json_insstring(char * p,const char * string,zbx_json_type_t type)237 static char *__zbx_json_insstring(char *p, const char *string, zbx_json_type_t type)
238 {
239 const char *sptr;
240 char buffer[] = {"null"};
241
242 if (NULL != string && ZBX_JSON_TYPE_STRING == type)
243 *p++ = '"';
244
245 for (sptr = (NULL != string ? string : buffer); '\0' != *sptr; sptr++)
246 {
247 switch (*sptr)
248 {
249 case '"': /* quotation mark */
250 *p++ = '\\';
251 *p++ = '"';
252 break;
253 case '\\': /* reverse solidus */
254 *p++ = '\\';
255 *p++ = '\\';
256 break;
257 /* We do not escape '/' (solidus). https://www.rfc-editor.org/errata_search.php?rfc=4627 */
258 /* says: "/" and "\/" are both allowed and both produce the same result. */
259 case '\b': /* backspace */
260 *p++ = '\\';
261 *p++ = 'b';
262 break;
263 case '\f': /* formfeed */
264 *p++ = '\\';
265 *p++ = 'f';
266 break;
267 case '\n': /* newline */
268 *p++ = '\\';
269 *p++ = 'n';
270 break;
271 case '\r': /* carriage return */
272 *p++ = '\\';
273 *p++ = 'r';
274 break;
275 case '\t': /* horizontal tab */
276 *p++ = '\\';
277 *p++ = 't';
278 break;
279 default:
280 /* RFC 8259 requires escaping control characters U+0000 - U+001F */
281 if (0x1f >= (unsigned char)*sptr)
282 {
283 *p++ = '\\';
284 *p++ = 'u';
285 *p++ = '0';
286 *p++ = '0';
287 *p++ = zbx_num2hex((((unsigned char)*sptr) >> 4) & 0xf);
288 *p++ = zbx_num2hex(((unsigned char)*sptr) & 0xf);
289 }
290 else
291 *p++ = *sptr;
292 }
293 }
294
295 if (NULL != string && ZBX_JSON_TYPE_STRING == type)
296 *p++ = '"';
297
298 return p;
299 }
300
zbx_json_escape(char ** string)301 void zbx_json_escape(char **string)
302 {
303 size_t size;
304 char *buffer;
305
306 if (0 == (size = __zbx_json_stringsize(*string, ZBX_JSON_TYPE_UNKNOWN)))
307 return;
308
309 buffer = zbx_malloc(NULL, size + 1);
310 buffer[size] = '\0';
311 __zbx_json_insstring(buffer, *string, ZBX_JSON_TYPE_UNKNOWN);
312 zbx_free(*string);
313 *string = buffer;
314 }
315
__zbx_json_addobject(struct zbx_json * j,const char * name,int object)316 static void __zbx_json_addobject(struct zbx_json *j, const char *name, int object)
317 {
318 size_t len = 2; /* brackets */
319 char *p, *psrc, *pdst;
320
321 assert(j);
322
323 if (ZBX_JSON_COMMA == j->status)
324 len++; /* , */
325
326 if (NULL != name)
327 {
328 len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
329 len += 1; /* : */
330 }
331
332 __zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
333
334 psrc = j->buffer + j->buffer_offset;
335 pdst = j->buffer + j->buffer_offset + len;
336
337 memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
338
339 p = psrc;
340
341 if (ZBX_JSON_COMMA == j->status)
342 *p++ = ',';
343
344 if (NULL != name)
345 {
346 p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
347 *p++ = ':';
348 }
349
350 *p++ = object ? '{' : '[';
351 *p = object ? '}' : ']';
352
353 j->buffer_offset = p - j->buffer;
354 j->buffer_size += len;
355 j->level++;
356 j->status = ZBX_JSON_EMPTY;
357 }
358
zbx_json_addobject(struct zbx_json * j,const char * name)359 void zbx_json_addobject(struct zbx_json *j, const char *name)
360 {
361 __zbx_json_addobject(j, name, 1);
362 }
363
zbx_json_addarray(struct zbx_json * j,const char * name)364 void zbx_json_addarray(struct zbx_json *j, const char *name)
365 {
366 __zbx_json_addobject(j, name, 0);
367 }
368
zbx_json_addstring(struct zbx_json * j,const char * name,const char * string,zbx_json_type_t type)369 void zbx_json_addstring(struct zbx_json *j, const char *name, const char *string, zbx_json_type_t type)
370 {
371 size_t len = 0;
372 char *p, *psrc, *pdst;
373
374 assert(j);
375
376 if (ZBX_JSON_COMMA == j->status)
377 len++; /* , */
378
379 if (NULL != name)
380 {
381 len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
382 len += 1; /* : */
383 }
384 len += __zbx_json_stringsize(string, type);
385
386 __zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
387
388 psrc = j->buffer + j->buffer_offset;
389 pdst = j->buffer + j->buffer_offset + len;
390
391 memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
392
393 p = psrc;
394
395 if (ZBX_JSON_COMMA == j->status)
396 *p++ = ',';
397
398 if (NULL != name)
399 {
400 p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
401 *p++ = ':';
402 }
403 p = __zbx_json_insstring(p, string, type);
404
405 j->buffer_offset = p - j->buffer;
406 j->buffer_size += len;
407 j->status = ZBX_JSON_COMMA;
408 }
409
zbx_json_addraw(struct zbx_json * j,const char * name,const char * data)410 void zbx_json_addraw(struct zbx_json *j, const char *name, const char *data)
411 {
412 size_t len = 0, len_data;
413 char *p, *psrc, *pdst;
414
415 assert(j);
416 len_data = strlen(data);
417
418 if (ZBX_JSON_COMMA == j->status)
419 len++; /* , */
420
421 if (NULL != name)
422 {
423 len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
424 len += 1; /* : */
425 }
426 len += len_data;
427
428 __zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
429
430 psrc = j->buffer + j->buffer_offset;
431 pdst = j->buffer + j->buffer_offset + len;
432
433 memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
434
435 p = psrc;
436
437 if (ZBX_JSON_COMMA == j->status)
438 *p++ = ',';
439
440 if (NULL != name)
441 {
442 p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
443 *p++ = ':';
444 }
445
446 memcpy(p, data, len_data);
447 p += len_data;
448
449 j->buffer_offset = p - j->buffer;
450 j->buffer_size += len;
451 j->status = ZBX_JSON_COMMA;
452 }
453
zbx_json_adduint64(struct zbx_json * j,const char * name,zbx_uint64_t value)454 void zbx_json_adduint64(struct zbx_json *j, const char *name, zbx_uint64_t value)
455 {
456 char buffer[MAX_ID_LEN];
457
458 zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_UI64, value);
459 zbx_json_addstring(j, name, buffer, ZBX_JSON_TYPE_INT);
460 }
461
zbx_json_addint64(struct zbx_json * j,const char * name,zbx_int64_t value)462 void zbx_json_addint64(struct zbx_json *j, const char *name, zbx_int64_t value)
463 {
464 char buffer[MAX_ID_LEN];
465
466 zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_I64, value);
467 zbx_json_addstring(j, name, buffer, ZBX_JSON_TYPE_INT);
468 }
469
zbx_json_addfloat(struct zbx_json * j,const char * name,double value)470 void zbx_json_addfloat(struct zbx_json *j, const char *name, double value)
471 {
472 char buffer[MAX_ID_LEN];
473
474 zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_DBL, value);
475 zbx_json_addstring(j, name, buffer, ZBX_JSON_TYPE_INT);
476 }
477
zbx_json_close(struct zbx_json * j)478 int zbx_json_close(struct zbx_json *j)
479 {
480 if (1 == j->level)
481 {
482 zbx_set_json_strerror("cannot close top level object");
483 return FAIL;
484 }
485
486 j->level--;
487 j->buffer_offset++;
488 j->status = ZBX_JSON_COMMA;
489
490 return SUCCEED;
491 }
492
493 /******************************************************************************
494 * *
495 * Function: __zbx_json_type *
496 * *
497 * Purpose: return type of pointed value *
498 * *
499 * Return value: type of pointed value *
500 * *
501 * Author: Alexander Vladishev *
502 * *
503 ******************************************************************************/
__zbx_json_type(const char * p)504 static zbx_json_type_t __zbx_json_type(const char *p)
505 {
506 if ('"' == *p)
507 return ZBX_JSON_TYPE_STRING;
508 if (('0' <= *p && *p <= '9') || '-' == *p)
509 return ZBX_JSON_TYPE_INT;
510 if ('[' == *p)
511 return ZBX_JSON_TYPE_ARRAY;
512 if ('{' == *p)
513 return ZBX_JSON_TYPE_OBJECT;
514 if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3])
515 return ZBX_JSON_TYPE_NULL;
516 if ('t' == p[0] && 'r' == p[1] && 'u' == p[2] && 'e' == p[3])
517 return ZBX_JSON_TYPE_TRUE;
518 if ('f' == p[0] && 'a' == p[1] && 'l' == p[2] && 's' == p[3] && 'e' == p[4])
519 return ZBX_JSON_TYPE_FALSE;
520
521 zbx_set_json_strerror("invalid type of JSON value \"%.64s\"", p);
522
523 return ZBX_JSON_TYPE_UNKNOWN;
524 }
525
526 /******************************************************************************
527 * *
528 * Function: __zbx_json_rbracket *
529 * *
530 * Purpose: return position of right bracket *
531 * *
532 * Return value: position of right bracket *
533 * NULL - an error occurred *
534 * *
535 * Author: Alexander Vladishev *
536 * *
537 ******************************************************************************/
__zbx_json_rbracket(const char * p)538 static const char *__zbx_json_rbracket(const char *p)
539 {
540 int level = 0;
541 int state = 0; /* 0 - outside string; 1 - inside string */
542 char lbracket, rbracket;
543
544 assert(p);
545
546 lbracket = *p;
547
548 if ('{' != lbracket && '[' != lbracket)
549 return NULL;
550
551 rbracket = ('{' == lbracket ? '}' : ']');
552
553 while ('\0' != *p)
554 {
555 switch (*p)
556 {
557 case '"':
558 state = (0 == state ? 1 : 0);
559 break;
560 case '\\':
561 if (1 == state)
562 if ('\0' == *++p)
563 return NULL;
564 break;
565 case '[':
566 case '{':
567 if (0 == state)
568 level++;
569 break;
570 case ']':
571 case '}':
572 if (0 == state)
573 {
574 level--;
575 if (0 == level)
576 return (rbracket == *p ? p : NULL);
577 }
578 break;
579 }
580 p++;
581 }
582
583 return NULL;
584 }
585
586 /******************************************************************************
587 * *
588 * Function: zbx_json_open *
589 * *
590 * Purpose: open json buffer and check for brackets *
591 * *
592 * Return value: SUCCESS - processed successfully *
593 * FAIL - an error occurred *
594 * *
595 ******************************************************************************/
zbx_json_open(const char * buffer,struct zbx_json_parse * jp)596 int zbx_json_open(const char *buffer, struct zbx_json_parse *jp)
597 {
598 char *error = NULL;
599 zbx_int64_t len;
600
601 SKIP_WHITESPACE(buffer);
602
603 /* return immediate failure without logging when opening empty string */
604 if ('\0' == *buffer)
605 return FAIL;
606
607 jp->start = buffer;
608 jp->end = NULL;
609
610 if (0 == (len = zbx_json_validate(jp->start, &error)))
611 {
612 if (NULL != error)
613 {
614 zbx_set_json_strerror("cannot parse as a valid JSON object: %s", error);
615 zbx_free(error);
616 }
617 else
618 {
619 zbx_set_json_strerror("cannot parse as a valid JSON object \"%.64s\"", buffer);
620 }
621
622 return FAIL;
623 }
624
625 jp->end = jp->start + len - 1;
626
627 return SUCCEED;
628 }
629
630 /******************************************************************************
631 * *
632 * Function: zbx_json_next *
633 * *
634 * Purpose: locate next pair or element *
635 * *
636 * Return value: NULL - no more values *
637 * NOT NULL - pointer to pair or element *
638 * {"name",... or "array":["name", ... ,1,null] *
639 * p = ^ ^ *
640 * *
641 * Author: Alexander Vladishev *
642 * *
643 ******************************************************************************/
zbx_json_next(const struct zbx_json_parse * jp,const char * p)644 const char *zbx_json_next(const struct zbx_json_parse *jp, const char *p)
645 {
646 int level = 0;
647 int state = 0; /* 0 - outside string; 1 - inside string */
648
649 if (1 == jp->end - jp->start) /* empty object or array */
650 return NULL;
651
652 if (NULL == p)
653 {
654 p = jp->start + 1;
655 SKIP_WHITESPACE(p);
656 return p;
657 }
658
659 while (p <= jp->end)
660 {
661 switch (*p)
662 {
663 case '"':
664 state = (0 == state) ? 1 : 0;
665 break;
666 case '\\':
667 if (1 == state)
668 p++;
669 break;
670 case '[':
671 case '{':
672 if (0 == state)
673 level++;
674 break;
675 case ']':
676 case '}':
677 if (0 == state)
678 {
679 if (0 == level)
680 return NULL;
681 level--;
682 }
683 break;
684 case ',':
685 if (0 == state && 0 == level)
686 {
687 p++;
688 SKIP_WHITESPACE(p);
689 return p;
690 }
691 break;
692 }
693 p++;
694 }
695
696 return NULL;
697 }
698
699 /******************************************************************************
700 * *
701 * Function: zbx_is_valid_json_hex *
702 * *
703 * Purpose: check if a 4 character sequence is a valid hex number 0000 - FFFF *
704 * *
705 * Parameters: *
706 * p - pointer to the 1st character *
707 * *
708 * Return value: SUCCEED or FAIL *
709 * *
710 ******************************************************************************/
zbx_is_valid_json_hex(const char * p)711 static int zbx_is_valid_json_hex(const char *p)
712 {
713 int i;
714
715 for (i = 0; i < 4; ++i, ++p)
716 {
717 if (0 == isxdigit(*p))
718 return FAIL;
719 }
720
721 return SUCCEED;
722 }
723
724 /******************************************************************************
725 * *
726 * Function: zbx_hex2num *
727 * *
728 * Purpose: convert hexit c ('0'-'9''a'-'f''A'-'F') to number (0-15) *
729 * *
730 * Parameters: *
731 * c - char ('0'-'9''a'-'f''A'-'F') *
732 * *
733 * Return value: *
734 * 0-15 *
735 * *
736 * Author: Alexander Vladishev *
737 * *
738 ******************************************************************************/
zbx_hex2num(char c)739 static unsigned int zbx_hex2num(char c)
740 {
741 int res;
742
743 if (c >= 'a')
744 res = c - 'a' + 10; /* a-f */
745 else if (c >= 'A')
746 res = c - 'A' + 10; /* A-F */
747 else
748 res = c - '0'; /* 0-9 */
749
750 return (unsigned int)res;
751 }
752
753 /******************************************************************************
754 * *
755 * Function: zbx_json_decode_character *
756 * *
757 * Purpose: decodes JSON escape character into UTF-8 *
758 * *
759 * Parameters: p - [IN/OUT] a pointer to the first character in string *
760 * bytes - [OUT] a 4-element array where 1 - 4 bytes of character *
761 * UTF-8 representation are written *
762 * *
763 * Return value: number of UTF-8 bytes written into 'bytes' array or *
764 * 0 on error (invalid escape sequence) *
765 * *
766 ******************************************************************************/
zbx_json_decode_character(const char ** p,unsigned char * bytes)767 static unsigned int zbx_json_decode_character(const char **p, unsigned char *bytes)
768 {
769 bytes[0] = '\0';
770
771 switch (**p)
772 {
773 case '"':
774 bytes[0] = '"';
775 break;
776 case '\\':
777 bytes[0] = '\\';
778 break;
779 case '/':
780 bytes[0] = '/';
781 break;
782 case 'b':
783 bytes[0] = '\b';
784 break;
785 case 'f':
786 bytes[0] = '\f';
787 break;
788 case 'n':
789 bytes[0] = '\n';
790 break;
791 case 'r':
792 bytes[0] = '\r';
793 break;
794 case 't':
795 bytes[0] = '\t';
796 break;
797 default:
798 break;
799 }
800
801 if ('\0' != bytes[0])
802 {
803 ++*p;
804 return 1;
805 }
806
807 if ('u' == **p) /* \u0000 - \uffff */
808 {
809 unsigned int num;
810
811 if (FAIL == zbx_is_valid_json_hex(++*p))
812 return 0;
813
814 num = zbx_hex2num(**p) << 12;
815 num += zbx_hex2num(*(++*p)) << 8;
816 num += zbx_hex2num(*(++*p)) << 4;
817 num += zbx_hex2num(*(++*p));
818 ++*p;
819
820 if (0x007f >= num) /* 0000 - 007f */
821 {
822 bytes[0] = (unsigned char)num;
823 return 1;
824 }
825 else if (0x07ff >= num) /* 0080 - 07ff */
826 {
827 bytes[0] = (unsigned char)(0xc0 | ((num >> 6) & 0x1f));
828 bytes[1] = (unsigned char)(0x80 | (num & 0x3f));
829 return 2;
830 }
831 else if (0xd7ff >= num || 0xe000 <= num) /* 0800 - d7ff or e000 - ffff */
832 {
833 bytes[0] = (unsigned char)(0xe0 | ((num >> 12) & 0x0f));
834 bytes[1] = (unsigned char)(0x80 | ((num >> 6) & 0x3f));
835 bytes[2] = (unsigned char)(0x80 | (num & 0x3f));
836 return 3;
837 }
838 else if (0xd800 <= num && num <= 0xdbff) /* high surrogate d800 - dbff */
839 {
840 unsigned int num_lo, uc;
841
842 /* collect the low surrogate */
843
844 if ('\\' != **p || 'u' != *(++*p) || FAIL == zbx_is_valid_json_hex(++*p))
845 return 0;
846
847 num_lo = zbx_hex2num(**p) << 12;
848 num_lo += zbx_hex2num(*(++*p)) << 8;
849 num_lo += zbx_hex2num(*(++*p)) << 4;
850 num_lo += zbx_hex2num(*(++*p));
851 ++*p;
852
853 if (num_lo < 0xdc00 || 0xdfff < num_lo) /* low surrogate range is dc00 - dfff */
854 return 0;
855
856 /* decode surrogate pair */
857
858 uc = 0x010000 + ((num & 0x03ff) << 10) + (num_lo & 0x03ff);
859
860 bytes[0] = (unsigned char)(0xf0 | ((uc >> 18) & 0x07));
861 bytes[1] = (unsigned char)(0x80 | ((uc >> 12) & 0x3f));
862 bytes[2] = (unsigned char)(0x80 | ((uc >> 6) & 0x3f));
863 bytes[3] = (unsigned char)(0x80 | (uc & 0x3f));
864 return 4;
865 }
866 /* error - low surrogate without high surrogate */
867 }
868
869 return 0;
870 }
871
872 /******************************************************************************
873 * *
874 * Function: zbx_json_copy_string *
875 * *
876 * Purpose: copies json name/string value by omitting leading/trailing " and *
877 * converting escape sequences *
878 * *
879 * Parameters: p - [IN] a pointer to the next character in string *
880 * out - [OUT] the output buffer *
881 * size - [IN] the output buffer size *
882 * *
883 * Return value: A pointer to the next character in input string or NULL if *
884 * string copying failed. *
885 * *
886 ******************************************************************************/
zbx_json_copy_string(const char * p,char * out,size_t size)887 static const char *zbx_json_copy_string(const char *p, char *out, size_t size)
888 {
889 char *start = out;
890
891 if (0 == size)
892 return NULL;
893
894 p++;
895
896 while ('\0' != *p)
897 {
898 switch (*p)
899 {
900 unsigned int nbytes, i;
901 unsigned char uc[4]; /* decoded Unicode character takes 1-4 bytes in UTF-8 */
902
903 case '\\':
904 ++p;
905 if (0 == (nbytes = zbx_json_decode_character(&p, uc)))
906 return NULL;
907
908 if ((size_t)(out - start) + nbytes >= size)
909 return NULL;
910
911 for (i = 0; i < nbytes; ++i)
912 *out++ = (char)uc[i];
913
914 break;
915 case '"':
916 *out = '\0';
917 return ++p;
918 default:
919 *out++ = *p++;
920 }
921
922 if ((size_t)(out - start) == size)
923 break;
924 }
925
926 return NULL;
927 }
928
929 /******************************************************************************
930 * *
931 * Function: zbx_json_copy_value *
932 * *
933 * Purpose: copies unquoted (numeric, boolean) json value *
934 * *
935 * Parameters: p - [IN] a pointer to the next character in string *
936 * len - [IN] the value length *
937 * out - [OUT] the output buffer *
938 * size - [IN] the output buffer size *
939 * *
940 * Return value: A pointer to the next character in input string or NULL if *
941 * string copying failed. *
942 * *
943 ******************************************************************************/
zbx_json_copy_unquoted_value(const char * p,size_t len,char * out,size_t size)944 static const char *zbx_json_copy_unquoted_value(const char *p, size_t len, char *out, size_t size)
945 {
946 if (size < len + 1)
947 return NULL;
948
949 memcpy(out, p, len);
950 out[len] = '\0';
951
952 return p + len;
953 }
954
zbx_json_decodevalue(const char * p,char * string,size_t size,zbx_json_type_t * type)955 const char *zbx_json_decodevalue(const char *p, char *string, size_t size, zbx_json_type_t *type)
956 {
957 size_t len;
958 zbx_json_type_t type_local;
959
960 switch (type_local = __zbx_json_type(p))
961 {
962 case ZBX_JSON_TYPE_ARRAY:
963 case ZBX_JSON_TYPE_OBJECT:
964 case ZBX_JSON_TYPE_UNKNOWN:
965 /* only primitive values are decoded */
966 return NULL;
967 default:
968 if (0 == (len = json_parse_value(p, NULL)))
969 return NULL;
970 }
971
972 if (NULL != type)
973 *type = type_local;
974
975 switch (type_local)
976 {
977 case ZBX_JSON_TYPE_STRING:
978 return zbx_json_copy_string(p, string, size);
979 case ZBX_JSON_TYPE_NULL:
980 if (0 == size)
981 return NULL;
982 *string = '\0';
983 return p + len;
984 default: /* ZBX_JSON_TYPE_INT, ZBX_JSON_TYPE_TRUE, ZBX_JSON_TYPE_FALSE */
985 return zbx_json_copy_unquoted_value(p, len, string, size);
986 }
987 }
988
zbx_json_decodevalue_dyn(const char * p,char ** string,size_t * string_alloc,zbx_json_type_t * type)989 const char *zbx_json_decodevalue_dyn(const char *p, char **string, size_t *string_alloc, zbx_json_type_t *type)
990 {
991 size_t len;
992 zbx_json_type_t type_local;
993
994 switch (type_local = __zbx_json_type(p))
995 {
996 case ZBX_JSON_TYPE_ARRAY:
997 case ZBX_JSON_TYPE_OBJECT:
998 case ZBX_JSON_TYPE_UNKNOWN:
999 /* only primitive values are decoded */
1000 return NULL;
1001 default:
1002 if (0 == (len = json_parse_value(p, NULL)))
1003 return NULL;
1004 }
1005
1006 if (*string_alloc <= len)
1007 {
1008 *string_alloc = len + 1;
1009 *string = (char *)zbx_realloc(*string, *string_alloc);
1010 }
1011
1012 if (NULL != type)
1013 *type = type_local;
1014
1015 switch (type_local)
1016 {
1017 case ZBX_JSON_TYPE_STRING:
1018 return zbx_json_copy_string(p, *string, *string_alloc);
1019 case ZBX_JSON_TYPE_NULL:
1020 **string = '\0';
1021 return p + len;
1022 default: /* ZBX_JSON_TYPE_INT, ZBX_JSON_TYPE_TRUE, ZBX_JSON_TYPE_FALSE */
1023 return zbx_json_copy_unquoted_value(p, len, *string, *string_alloc);
1024 }
1025 }
1026
zbx_json_pair_next(const struct zbx_json_parse * jp,const char * p,char * name,size_t len)1027 const char *zbx_json_pair_next(const struct zbx_json_parse *jp, const char *p, char *name, size_t len)
1028 {
1029 if (NULL == (p = zbx_json_next(jp, p)))
1030 return NULL;
1031
1032 if (ZBX_JSON_TYPE_STRING != __zbx_json_type(p))
1033 return NULL;
1034
1035 if (NULL == (p = zbx_json_copy_string(p, name, len)))
1036 return NULL;
1037
1038 SKIP_WHITESPACE(p);
1039
1040 if (':' != *p++)
1041 return NULL;
1042
1043 SKIP_WHITESPACE(p);
1044
1045 return p;
1046 }
1047
1048 /******************************************************************************
1049 * *
1050 * Function: zbx_json_pair_by_name *
1051 * *
1052 * Purpose: find pair by name and return pointer to value *
1053 * *
1054 * Return value: pointer to value *
1055 * {"name":["a","b",...]} *
1056 * ^ - returned pointer *
1057 * *
1058 * Author: Alexander Vladishev *
1059 * *
1060 ******************************************************************************/
zbx_json_pair_by_name(const struct zbx_json_parse * jp,const char * name)1061 const char *zbx_json_pair_by_name(const struct zbx_json_parse *jp, const char *name)
1062 {
1063 char buffer[MAX_STRING_LEN];
1064 const char *p = NULL;
1065
1066 while (NULL != (p = zbx_json_pair_next(jp, p, buffer, sizeof(buffer))))
1067 if (0 == strcmp(name, buffer))
1068 return p;
1069
1070 zbx_set_json_strerror("cannot find pair with name \"%s\"", name);
1071
1072 return NULL;
1073 }
1074
1075 /******************************************************************************
1076 * *
1077 * Function: zbx_json_next_value *
1078 * *
1079 * Author: Alexander Vladishev *
1080 * *
1081 ******************************************************************************/
zbx_json_next_value(const struct zbx_json_parse * jp,const char * p,char * string,size_t len,zbx_json_type_t * type)1082 const char *zbx_json_next_value(const struct zbx_json_parse *jp, const char *p, char *string, size_t len,
1083 zbx_json_type_t *type)
1084 {
1085 if (NULL == (p = zbx_json_next(jp, p)))
1086 return NULL;
1087
1088 return zbx_json_decodevalue(p, string, len, type);
1089 }
1090
1091 /******************************************************************************
1092 * *
1093 * Function: zbx_json_next_value_dyn *
1094 * *
1095 ******************************************************************************/
zbx_json_next_value_dyn(const struct zbx_json_parse * jp,const char * p,char ** string,size_t * string_alloc,zbx_json_type_t * type)1096 const char *zbx_json_next_value_dyn(const struct zbx_json_parse *jp, const char *p, char **string,
1097 size_t *string_alloc, zbx_json_type_t *type)
1098 {
1099 if (NULL == (p = zbx_json_next(jp, p)))
1100 return NULL;
1101
1102 return zbx_json_decodevalue_dyn(p, string, string_alloc, type);
1103 }
1104
1105 /******************************************************************************
1106 * *
1107 * Function: zbx_json_value_by_name *
1108 * *
1109 * Purpose: return value by pair name *
1110 * *
1111 * Return value: SUCCEED - if value successfully parsed, FAIL - otherwise *
1112 * *
1113 * Author: Alexander Vladishev *
1114 * *
1115 ******************************************************************************/
zbx_json_value_by_name(const struct zbx_json_parse * jp,const char * name,char * string,size_t len,zbx_json_type_t * type)1116 int zbx_json_value_by_name(const struct zbx_json_parse *jp, const char *name, char *string, size_t len,
1117 zbx_json_type_t *type)
1118 {
1119 const char *p;
1120
1121 if (NULL == (p = zbx_json_pair_by_name(jp, name)))
1122 return FAIL;
1123
1124 if (NULL == zbx_json_decodevalue(p, string, len, type))
1125 return FAIL;
1126
1127 return SUCCEED;
1128 }
1129
1130 /******************************************************************************
1131 * *
1132 * Function: zbx_json_value_by_name_dyn *
1133 * *
1134 * Purpose: return value by pair name *
1135 * *
1136 * Return value: SUCCEED - if value successfully parsed, FAIL - otherwise *
1137 * *
1138 * Author: Alexander Vladishev *
1139 * *
1140 ******************************************************************************/
zbx_json_value_by_name_dyn(const struct zbx_json_parse * jp,const char * name,char ** string,size_t * string_alloc,zbx_json_type_t * type)1141 int zbx_json_value_by_name_dyn(const struct zbx_json_parse *jp, const char *name, char **string,
1142 size_t *string_alloc, zbx_json_type_t *type)
1143 {
1144 const char *p;
1145
1146 if (NULL == (p = zbx_json_pair_by_name(jp, name)))
1147 return FAIL;
1148
1149 if (NULL == zbx_json_decodevalue_dyn(p, string, string_alloc, type))
1150 return FAIL;
1151
1152 return SUCCEED;
1153 }
1154
1155 /******************************************************************************
1156 * *
1157 * Function: zbx_json_brackets_open *
1158 * *
1159 * Return value: SUCCESS - processed successfully *
1160 * FAIL - an error occurred *
1161 * *
1162 * Author: Alexander Vladishev *
1163 * *
1164 ******************************************************************************/
zbx_json_brackets_open(const char * p,struct zbx_json_parse * jp)1165 int zbx_json_brackets_open(const char *p, struct zbx_json_parse *jp)
1166 {
1167 if (NULL == (jp->end = __zbx_json_rbracket(p)))
1168 {
1169 zbx_set_json_strerror("cannot open JSON object or array \"%.64s\"", p);
1170 return FAIL;
1171 }
1172
1173 SKIP_WHITESPACE(p);
1174
1175 jp->start = p;
1176
1177 return SUCCEED;
1178 }
1179
1180 /******************************************************************************
1181 * *
1182 * Function: zbx_json_brackets_by_name *
1183 * *
1184 * Return value: SUCCESS - processed successfully *
1185 * FAIL - an error occurred *
1186 * *
1187 * Author: Alexander Vladishev *
1188 * *
1189 ******************************************************************************/
zbx_json_brackets_by_name(const struct zbx_json_parse * jp,const char * name,struct zbx_json_parse * out)1190 int zbx_json_brackets_by_name(const struct zbx_json_parse *jp, const char *name, struct zbx_json_parse *out)
1191 {
1192 const char *p;
1193
1194 if (NULL == (p = zbx_json_pair_by_name(jp, name)))
1195 return FAIL;
1196
1197 if (FAIL == zbx_json_brackets_open(p, out))
1198 return FAIL;
1199
1200 return SUCCEED;
1201 }
1202
1203 /******************************************************************************
1204 * *
1205 * Function: zbx_json_object_is_empty *
1206 * *
1207 * Return value: SUCCESS - if object is empty *
1208 * FAIL - if object contains data *
1209 * *
1210 * Author: Alexander Vladishev *
1211 * *
1212 ******************************************************************************/
zbx_json_object_is_empty(const struct zbx_json_parse * jp)1213 int zbx_json_object_is_empty(const struct zbx_json_parse *jp)
1214 {
1215 return jp->end - jp->start > 1 ? FAIL : SUCCEED;
1216 }
1217
1218 /******************************************************************************
1219 * *
1220 * Function: zbx_json_count *
1221 * *
1222 * Return value: number of elements in zbx_json_parse object *
1223 * *
1224 * Author: Alexander Vladishev *
1225 * *
1226 ******************************************************************************/
zbx_json_count(const struct zbx_json_parse * jp)1227 int zbx_json_count(const struct zbx_json_parse *jp)
1228 {
1229 int num = 0;
1230 const char *p = NULL;
1231
1232 while (NULL != (p = zbx_json_next(jp, p)))
1233 num++;
1234
1235 return num;
1236 }
1237
1238 /******************************************************************************
1239 * *
1240 * Function: zbx_json_open_path *
1241 * *
1242 * Purpose: opens an object by definite json path *
1243 * *
1244 * Return value: SUCCESS - processed successfully *
1245 * FAIL - an error occurred *
1246 * *
1247 * Comments: Only direct path to single object in dot or bracket notation *
1248 * is supported. *
1249 * *
1250 ******************************************************************************/
zbx_json_open_path(const struct zbx_json_parse * jp,const char * path,struct zbx_json_parse * out)1251 int zbx_json_open_path(const struct zbx_json_parse *jp, const char *path, struct zbx_json_parse *out)
1252 {
1253 int i, ret = FAIL;
1254 struct zbx_json_parse object;
1255 zbx_jsonpath_t jsonpath;
1256
1257 object = *jp;
1258
1259 if (FAIL == zbx_jsonpath_compile(path, &jsonpath))
1260 return FAIL;
1261
1262 if (0 == jsonpath.definite)
1263 {
1264 zbx_set_json_strerror("cannot use indefinite path when opening sub element");
1265 goto out;
1266 }
1267
1268 for (i = 0; i < jsonpath.segments_num; i++)
1269 {
1270 const char *p;
1271 zbx_jsonpath_segment_t *segment = &jsonpath.segments[i];
1272
1273 if (ZBX_JSONPATH_SEGMENT_MATCH_LIST != segment->type)
1274 {
1275 zbx_set_json_strerror("jsonpath segment %d is not a name or index", i + 1);
1276 goto out;
1277 }
1278
1279 if (ZBX_JSONPATH_LIST_INDEX == segment->data.list.type)
1280 {
1281 int index;
1282
1283 if ('[' != *object.start)
1284 goto out;
1285
1286 memcpy(&index, segment->data.list.values->data, sizeof(int));
1287
1288 for (p = NULL; NULL != (p = zbx_json_next(&object, p)) && 0 != index; index--)
1289 ;
1290
1291 if (0 != index || NULL == p)
1292 {
1293 zbx_set_json_strerror("array index out of bounds in jsonpath segment %d", i + 1);
1294 goto out;
1295 }
1296 }
1297 else
1298 {
1299 if (NULL == (p = zbx_json_pair_by_name(&object, (char *)&segment->data.list.values->data)))
1300 {
1301 zbx_set_json_strerror("object not found in jsonpath segment %d", i + 1);
1302 goto out;
1303 }
1304 }
1305
1306 object.start = p;
1307
1308 if (NULL == (object.end = __zbx_json_rbracket(p)))
1309 object.end = p + json_parse_value(p, NULL) - 1;
1310 }
1311
1312 *out = object;
1313 ret = SUCCEED;
1314 out:
1315 zbx_jsonpath_clear(&jsonpath);
1316 return ret;
1317 }
1318