1 /**
2  * @file parser_json.c
3  * @author Radek Krejci <rkrejci@cesnet.cz>
4  * @brief JSON data parser for libyang
5  *
6  * Copyright (c) 2015 CESNET, z.s.p.o.
7  *
8  * This source code is licensed under BSD 3-Clause License (the "License").
9  * You may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     https://opensource.org/licenses/BSD-3-Clause
13  */
14 
15 #define _GNU_SOURCE
16 #include <assert.h>
17 #include <ctype.h>
18 #include <limits.h>
19 #include <errno.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "libyang.h"
24 #include "common.h"
25 #include "context.h"
26 #include "parser.h"
27 #include "printer.h"
28 #include "tree_internal.h"
29 #include "validation.h"
30 #include "xml_internal.h"
31 
32 static int
lyjson_isspace(int c)33 lyjson_isspace(int c)
34 {
35     switch(c) {
36     case 0x20: /* space */
37     case 0x09: /* horizontal tab */
38     case 0x0a: /* line feed or new line */
39     case 0x0d: /* carriage return */
40         return 1;
41     default:
42         return 0;
43     }
44 }
45 
46 static unsigned int
skip_ws(const char * data)47 skip_ws(const char *data)
48 {
49     unsigned int len = 0;
50 
51     /* skip leading whitespaces */
52     while (data[len] && lyjson_isspace(data[len])) {
53         len++;
54     }
55 
56     return len;
57 }
58 
59 static char *
lyjson_parse_text(struct ly_ctx * ctx,const char * data,unsigned int * len)60 lyjson_parse_text(struct ly_ctx *ctx, const char *data, unsigned int *len)
61 {
62 #define BUFSIZE 1024
63 
64     char buf[BUFSIZE];
65     char *result = NULL, *aux;
66     int o, size = 0;
67     unsigned int r, i;
68     int32_t value;
69 
70     for (*len = o = 0; data[*len] && data[*len] != '"'; o++) {
71         if (o > BUFSIZE - 4) {
72             /* add buffer into the result */
73             if (result) {
74                 size = size + o;
75                 aux = ly_realloc(result, size + 1);
76                 LY_CHECK_ERR_RETURN(!aux, LOGMEM(ctx), NULL);
77                 result = aux;
78             } else {
79                 size = o;
80                 result = malloc((size + 1) * sizeof *result);
81                 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), NULL);
82             }
83             memcpy(&result[size - o], buf, o);
84 
85             /* write again into the beginning of the buffer */
86             o = 0;
87         }
88 
89         if (data[*len] == '\\') {
90             /* parse escape sequence */
91             (*len)++;
92             i = 1;
93             switch (data[(*len)]) {
94             case '"':
95                 /* quotation mark */
96                 value = 0x22;
97                 break;
98             case '\\':
99                 /* reverse solidus */
100                 value = 0x5c;
101                 break;
102             case '/':
103                 /* solidus */
104                 value = 0x2f;
105                 break;
106             case 'b':
107                 /* backspace */
108                 value = 0x08;
109                 break;
110             case 'f':
111                 /* form feed */
112                 value = 0x0c;
113                 break;
114             case 'n':
115                 /* line feed */
116                 value = 0x0a;
117                 break;
118             case 'r':
119                 /* carriage return */
120                 value = 0x0d;
121                 break;
122             case 't':
123                 /* tab */
124                 value = 0x09;
125                 break;
126             case 'u':
127                 /* Basic Multilingual Plane character \uXXXX */
128                 (*len)++;
129                 for (value = i = 0; i < 4; i++) {
130                     if (isdigit(data[(*len) + i])) {
131                         r = (data[(*len) + i] - '0');
132                     } else if (data[(*len) + i] > 'F') {
133                         r = 10 + (data[(*len) + i] - 'a');
134                     } else {
135                         r = 10 + (data[(*len) + i] - 'A');
136                     }
137                     value = (16 * value) + r;
138                 }
139                 break;
140             default:
141                 /* invalid escape sequence */
142                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "character escape sequence");
143                 goto error;
144 
145             }
146             r = pututf8(ctx, &buf[o], value);
147             if (!r) {
148                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "character UTF8 character");
149                 goto error;
150             }
151             o += r - 1; /* o is ++ in for loop */
152             (*len) += i; /* number of read characters */
153         } else if ((unsigned char)(data[*len]) < 0x20) {
154             /* In C, char != unsigned char != signed char, so let's work with ASCII explicitly */
155             /* control characters must be escaped */
156             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "control character (unescaped)");
157             goto error;
158         } else {
159             /* unescaped character */
160             r = copyutf8(ctx, &buf[o], &data[*len]);
161             if (!r) {
162                 goto error;
163             }
164 
165             o += r - 1;     /* o is ++ in for loop */
166             (*len) += r;
167         }
168     }
169 
170 #undef BUFSIZE
171 
172     if (o) {
173         if (result) {
174             size = size + o;
175             aux = ly_realloc(result, size + 1);
176             LY_CHECK_ERR_RETURN(!aux, LOGMEM(ctx), NULL);
177             result = aux;
178         } else {
179             size = o;
180             result = malloc((size + 1) * sizeof *result);
181             LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), NULL);
182         }
183         memcpy(&result[size - o], buf, o);
184     }
185     if (result) {
186         result[size] = '\0';
187     } else {
188         size = 0;
189         result = strdup("");
190         LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), NULL);
191     }
192 
193     return result;
194 
195 error:
196     free(result);
197     return NULL;
198 }
199 
200 static unsigned int
lyjson_parse_number(struct ly_ctx * ctx,const char * data)201 lyjson_parse_number(struct ly_ctx *ctx, const char *data)
202 {
203     unsigned int len = 0;
204 
205     if (data[len] == '-') {
206         ++len;
207     }
208 
209     if (data[len] == '0') {
210         ++len;
211     } else if (isdigit(data[len])) {
212         ++len;
213         while (isdigit(data[len])) {
214             ++len;
215         }
216     } else {
217         LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
218         return 0;
219     }
220 
221     if (data[len] == '.') {
222         ++len;
223         if (!isdigit(data[len])) {
224             if (data[len]) {
225                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
226             } else {
227                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value (EOF).");
228             }
229             return 0;
230         }
231         while (isdigit(data[len])) {
232             ++len;
233         }
234     }
235 
236     if ((data[len] == 'e') || (data[len] == 'E')) {
237         ++len;
238         if ((data[len] == '+') || (data[len] == '-')) {
239             ++len;
240         }
241         while (isdigit(data[len])) {
242             ++len;
243         }
244     }
245 
246     if (data[len] && (data[len] != ',') && (data[len] != ']') && (data[len] != '}') && !lyjson_isspace(data[len])) {
247         LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
248         return 0;
249     }
250 
251     return len;
252 }
253 
254 static char *
lyjson_convert_enumber(struct ly_ctx * ctx,const char * number,unsigned int num_len,char * e_ptr)255 lyjson_convert_enumber(struct ly_ctx *ctx, const char *number, unsigned int num_len, char *e_ptr)
256 {
257     char *ptr, *num;
258     const char *number_ptr;
259     long int e_val;
260     int dot_pos, chars_to_dot, minus;
261     unsigned int num_len_no_e;
262 
263     if (*number == '-') {
264         minus = 1;
265         ++number;
266         --num_len;
267     } else {
268         minus = 0;
269     }
270 
271     num_len_no_e = e_ptr - number;
272 
273     errno = 0;
274     ++e_ptr;
275     e_val = strtol(e_ptr, &ptr, 10);
276     if (errno) {
277         LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Exponent out-of-bounds in a JSON Number value (%.*s).",
278                num_len - (e_ptr - number), e_ptr);
279         return NULL;
280     } else if (ptr != number + num_len) {
281         /* we checked this already */
282         LOGINT(ctx);
283         return NULL;
284     }
285 
286     if ((ptr = strnchr(number, '.', num_len_no_e))) {
287         dot_pos = ptr - number;
288     } else {
289         dot_pos = num_len_no_e;
290     }
291 
292     dot_pos += e_val;
293 
294     /* allocate enough memory */
295     if (dot_pos < 1) {
296         /* (.XXX)XXX[.]XXXX */
297         num = malloc((minus ? 1 : 0) + -dot_pos + 2 + (num_len_no_e - (ptr ? 1 : 0)) + 1);
298     } else if (dot_pos < (signed)num_len_no_e) {
299         /* XXXX(.)XX.XXX */
300         num = malloc((minus ? 1 : 0) + num_len_no_e + (ptr ? 0 : 1) + 1);
301     } else {
302         /* XXX[.]XXXX(XXX.) */
303         num = malloc((minus ? 1 : 0) + (dot_pos - (ptr ? 2 : 1)) + 1);
304     }
305     LY_CHECK_ERR_RETURN(!num, LOGMEM(ctx), NULL);
306     if (minus) {
307         strcpy(num, "-");
308     } else {
309         num[0] = '\0';
310     }
311 
312     if (dot_pos < 1) {
313         strcat(num, "0.");
314     }
315     if (dot_pos < 0) {
316         sprintf(num + strlen(num), "%0*d", -dot_pos, 0);
317     }
318 
319     chars_to_dot = dot_pos;
320     for (ptr = num + strlen(num), number_ptr = number; (unsigned)(number_ptr - number) < num_len_no_e; ) {
321         if (!chars_to_dot) {
322             *ptr = '.';
323             ++ptr;
324             chars_to_dot = -1;
325         } else if (isdigit(*number_ptr)) {
326             *ptr = *number_ptr;
327             ++ptr;
328             ++number_ptr;
329             if (chars_to_dot > 0) {
330                 --chars_to_dot;
331             }
332         } else if (*number_ptr == '.') {
333             ++number_ptr;
334         } else {
335             LOGINT(ctx);
336             free(num);
337             return NULL;
338         }
339     }
340     *ptr = '\0';
341 
342     if (dot_pos > (signed)num_len_no_e) {
343         sprintf(num + strlen(num), "%0*d", dot_pos - num_len_no_e, 0);
344     }
345 
346     return num;
347 }
348 
349 static unsigned int
lyjson_parse_boolean(struct ly_ctx * ctx,const char * data)350 lyjson_parse_boolean(struct ly_ctx *ctx, const char *data)
351 {
352     unsigned int len = 0;
353 
354     if (!strncmp(data, "false", 5)) {
355         len = 5;
356     } else if (!strncmp(data, "true", 4)) {
357         len = 4;
358     }
359 
360     if (data[len] && data[len] != ',' && data[len] != ']' && data[len] != '}' && !lyjson_isspace(data[len])) {
361         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON literal value (expected true or false)");
362         return 0;
363     }
364 
365     return len;
366 }
367 
368 static unsigned int
json_get_anydata(struct lyd_node_anydata * any,const char * data)369 json_get_anydata(struct lyd_node_anydata *any, const char *data)
370 {
371     struct ly_ctx *ctx = any->schema->module->ctx;
372     unsigned int len = 0, c = 0, skip = 0;
373     char *str;
374 
375     if (data[len] == '"') {
376         len = 1;
377         str = lyjson_parse_text(ctx, &data[len], &c);
378         if (!str) {
379             return 0;
380         }
381         if (data[len + c] != '"') {
382             free(str);
383             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, any,
384                    "JSON data (missing quotation-mark at the end of string)");
385             return 0;
386         }
387 
388         any->value.str = lydict_insert_zc(ctx, str);
389         any->value_type = LYD_ANYDATA_CONSTSTRING;
390         return len + c + 1;
391     } else if (data[len] != '{') {
392         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, any, "anydata/anyxml content (not an object nor string)");
393         return 0;
394     }
395 
396     /* count opening '{' and closing '}' brackets to get the end of the object without its parsing */
397     c = len = 0;
398     do {
399         switch (data[len]) {
400         case '{':
401             if (!skip) {
402                 c++;
403             }
404             break;
405         case '}':
406             if (!skip) {
407                 c--;
408             }
409             break;
410         case '\\':
411             /* when parsing a string, ignore escaped quotes to not end it prematurely */
412             if (skip && data[len + 1]) {
413                 len++;
414             }
415             break;
416         case '\"':
417             skip = !skip;
418             break;
419         default:
420             break;
421         }
422         len++;
423     } while (data[len] && c);
424     if (c) {
425         LOGVAL(ctx, LYE_EOF, LY_VLOG_LYD, any);
426         return 0;
427     }
428 
429     any->value_type = LYD_ANYDATA_JSON;
430     any->value.str = lydict_insert(ctx, data, len);
431 
432     return len;
433 }
434 
435 static unsigned int
json_get_value(struct lyd_node_leaf_list * leaf,struct lyd_node ** first_sibling,const char * data,int options,struct unres_data * unres)436 json_get_value(struct lyd_node_leaf_list *leaf, struct lyd_node **first_sibling, const char *data, int options,
437                struct unres_data *unres)
438 {
439     struct lyd_node_leaf_list *new;
440     struct lys_type *stype;
441     struct ly_ctx *ctx;
442     unsigned int len = 0, r;
443     char *str;
444 
445     assert(leaf && data);
446     ctx = leaf->schema->module->ctx;
447 
448     stype = &((struct lys_node_leaf *)leaf->schema)->type;
449 
450     if (leaf->schema->nodetype == LYS_LEAFLIST) {
451         /* expecting begin-array */
452         if (data[len++] != '[') {
453             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected begin-array)");
454             return 0;
455         }
456 
457 repeat:
458         len += skip_ws(&data[len]);
459     }
460 
461     /* will be changed in case of union */
462     leaf->value_type = stype->base;
463 
464     if (data[len] == '"') {
465         if ((leaf->value_type == LY_TYPE_INT8) || (leaf->value_type == LY_TYPE_INT16) ||
466                 (leaf->value_type == LY_TYPE_INT32) || (leaf->value_type == LY_TYPE_UINT8) ||
467                 (leaf->value_type == LY_TYPE_UINT16) || (leaf->value_type == LY_TYPE_UINT32)) {
468             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected number, but found string)");
469             return 0;
470         }
471         if (leaf->value_type == LY_TYPE_BOOL) {
472             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected boolean, but found string)");
473             return 0;
474         }
475 
476         /* string representations */
477         ++len;
478         str = lyjson_parse_text(ctx, &data[len], &r);
479         if (!str) {
480             LOGPATH(ctx, LY_VLOG_LYD, leaf);
481             return 0;
482         }
483         leaf->value_str = lydict_insert_zc(ctx, str);
484         if (data[len + r] != '"') {
485             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf,
486                    "JSON data (missing quotation-mark at the end of string)");
487             return 0;
488         }
489         len += r + 1;
490     } else if (data[len] == '-' || isdigit(data[len])) {
491         if ((leaf->value_type == LY_TYPE_INT64) || (leaf->value_type == LY_TYPE_UINT64) ||
492                 (leaf->value_type == LY_TYPE_STRING)) {
493             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected string, but found number)");
494             return 0;
495         }
496 
497         /* numeric type */
498         r = lyjson_parse_number(ctx, &data[len]);
499         if (!r) {
500             LOGPATH(ctx, LY_VLOG_LYD, leaf);
501             return 0;
502         }
503         /* if it's a number with 'e' or 'E', get rid of it first */
504         if ((str = strnchr(&data[len], 'e', r)) || (str = strnchr(&data[len], 'E', r))) {
505             str = lyjson_convert_enumber(ctx, &data[len], r, str);
506             if (!str) {
507                 return 0;
508             }
509             leaf->value_str = lydict_insert_zc(ctx, str);
510         } else {
511             leaf->value_str = lydict_insert(ctx, &data[len], r);
512         }
513         len += r;
514     } else if (data[len] == 'f' || data[len] == 't') {
515         if (leaf->value_type == LY_TYPE_STRING) {
516             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected string, but found boolean)");
517             return 0;
518         }
519 
520         /* boolean */
521         r = lyjson_parse_boolean(ctx, &data[len]);
522         if (!r) {
523             LOGPATH(ctx, LY_VLOG_LYD, leaf);
524             return 0;
525         }
526         leaf->value_str = lydict_insert(ctx, &data[len], r);
527         len += r;
528     } else if (data[len] == '[') {
529         /* empty '[' WSP 'null' WSP ']' */
530         for (r = len + 1; isspace(data[r]); ++r);
531         if (strncmp(&data[r], "null", 4)) {
532             goto inval;
533         }
534         for (r += 4; isspace(data[r]); ++r);
535         if (data[r] != ']') {
536             goto inval;
537         }
538         leaf->value_str = lydict_insert(ctx, "", 0);
539         len = r + 1;
540     } else {
541 inval:
542         /* error */
543         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (unexpected value)");
544         return 0;
545     }
546 
547     /* the value is here converted to a JSON format if needed in case of LY_TYPE_IDENT and LY_TYPE_INST or to a
548      * canonical form of the value */
549     if (!lyp_parse_value(&((struct lys_node_leaf *)leaf->schema)->type, &leaf->value_str, NULL, leaf, NULL, NULL, 1, 0)) {
550         return 0;
551     }
552 
553 #ifdef LY_ENABLED_CACHE
554     /* calculate the hash and insert it into parent */
555     lyd_hash((struct lyd_node *)leaf);
556     lyd_insert_hash((struct lyd_node *)leaf);
557 #endif
558 
559     if (leaf->schema->nodetype == LYS_LEAFLIST) {
560         /* repeat until end-array */
561         len += skip_ws(&data[len]);
562         if (data[len] == ',') {
563             /* various validation checks */
564             if (lyv_data_context((struct lyd_node*)leaf, options, 0, unres) ||
565                     lyv_data_content((struct lyd_node*)leaf, options, unres) ||
566                     lyv_multicases((struct lyd_node*)leaf, NULL, first_sibling, 0, NULL)) {
567                 return 0;
568             }
569 
570             /* another instance of the leaf-list */
571             new = calloc(1, sizeof(struct lyd_node_leaf_list));
572             LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), 0);
573 
574             new->parent = leaf->parent;
575             new->prev = (struct lyd_node *)leaf;
576             leaf->next = (struct lyd_node *)new;
577 
578             /* copy the validity and when flags */
579             new->validity = leaf->validity;
580             new->when_status = leaf->when_status;
581 
582             /* fix the "last" pointer */
583             (*first_sibling)->prev = (struct lyd_node *)new;
584 
585             new->schema = leaf->schema;
586 
587             /* repeat value parsing */
588             leaf = new;
589             len++;
590             goto repeat;
591         } else if (data[len] == ']') {
592             len++;
593             len += skip_ws(&data[len]);
594         } else {
595             /* something unexpected */
596             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expecting value-separator or end-array)");
597             return 0;
598         }
599     }
600 
601     len += skip_ws(&data[len]);
602     return len;
603 }
604 
605 static unsigned int
json_parse_attr(struct lys_module * parent_module,struct lyd_attr ** attr,const char * data,int options)606 json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data, int options)
607 {
608     struct ly_ctx *ctx = parent_module->ctx;
609     unsigned int len = 0, r;
610     char *str = NULL, *name, *prefix = NULL, *value;
611     struct lys_module *module = parent_module;
612     struct lyd_attr *attr_new, *attr_last = NULL;
613     int ret;
614 
615     *attr = NULL;
616 
617     if (data[len] != '{') {
618         if (!strncmp(&data[len], "null", 4)) {
619             len += 4;
620             len += skip_ws(&data[len]);
621             return len;
622         }
623         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing begin-object)");
624         goto error;
625     }
626 
627 repeat:
628     prefix = NULL;
629     len++;
630     len += skip_ws(&data[len]);
631 
632     if (data[len] != '"') {
633         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the beginning of string)");
634         return 0;
635     }
636     len++;
637     str = lyjson_parse_text(ctx, &data[len], &r);
638     if (!r) {
639         goto error;
640     } else if (data[len + r] != '"') {
641         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the end of string)");
642         goto error;
643     }
644     if ((name = strchr(str, ':'))) {
645         *name = '\0';
646         name++;
647         prefix = str;
648         module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL, 0);
649         if (!module) {
650             LOGVAL(ctx, LYE_INELEM, LY_VLOG_NONE, NULL, name);
651             goto error;
652         }
653     } else {
654         name = str;
655     }
656 
657     /* prepare data for parsing node content */
658     len += r + 1;
659     len += skip_ws(&data[len]);
660     if (data[len] != ':') {
661         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing name-separator)");
662         goto error;
663     }
664     len++;
665     len += skip_ws(&data[len]);
666 
667     if (data[len] != '"') {
668         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the beginning of string)");
669         goto error;
670     }
671     len++;
672     value = lyjson_parse_text(ctx, &data[len], &r);
673     if (!r) {
674         goto error;
675     } else if (data[len + r] != '"') {
676         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the end of string)");
677         free(value);
678         goto error;
679     }
680     len += r + 1;
681     len += skip_ws(&data[len]);
682 
683     ret = lyp_fill_attr(parent_module->ctx, NULL, NULL, prefix, name, value, NULL, &attr_new);
684     if (ret == -1) {
685         free(value);
686         goto error;
687     } else if (ret == 1) {
688         if (options & LYD_OPT_STRICT) {
689             LOGVAL(ctx, LYE_INMETA, LY_VLOG_NONE, NULL, prefix, name, value);
690             free(value);
691             goto error;
692         }
693 
694         LOGWRN(ctx, "Unknown \"%s:%s\" metadata with value \"%s\", ignoring.",
695                (prefix ? prefix : "<none>"), name, value);
696         free(value);
697         goto next;
698     }
699     free(value);
700 
701     if (!attr_last) {
702         *attr = attr_last = attr_new;
703     } else {
704         attr_last->next = attr_new;
705         attr_last = attr_new;
706     }
707 
708 next:
709     free(str);
710     str = NULL;
711 
712     if (data[len] == ',') {
713         goto repeat;
714     } else if (data[len] != '}') {
715         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing end-object)");
716         goto error;
717     }
718     len++;
719     len += skip_ws(&data[len]);
720 
721     return len;
722 
723 error:
724     free(str);
725     if (*attr) {
726         lyd_free_attr(module->ctx, NULL, *attr, 1);
727         *attr = NULL;
728     }
729     return 0;
730 }
731 
732 struct attr_cont {
733     struct attr_cont *next;
734     struct lyd_attr *attr;
735     struct lys_node *schema;
736     unsigned int index;    /** non-zero only in case of leaf-list */
737 };
738 
739 static int
store_attrs(struct ly_ctx * ctx,struct attr_cont * attrs,struct lyd_node * first,int options)740 store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first, int options)
741 {
742     struct lyd_node *diter;
743     struct attr_cont *iter;
744     struct lyd_attr *aiter;
745     unsigned int flag_leaflist = 0;
746 
747     while (attrs) {
748         iter = attrs;
749         attrs = attrs->next;
750 
751         if (iter->index) {
752             flag_leaflist = 1;
753         } else {
754             flag_leaflist = 0;
755         }
756 
757         LY_TREE_FOR(first, diter) {
758             if (iter->schema != diter->schema) {
759                 continue;
760             }
761 
762             if (flag_leaflist && flag_leaflist != iter->index) {
763                 flag_leaflist++;
764                 continue;
765             }
766 
767             /* we have match */
768             if (diter->attr) {
769                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, diter,
770                        "attribute (multiple attribute definitions belong to a single element)");
771                 free(iter);
772                 goto error;
773             }
774 
775             diter->attr = iter->attr;
776             for (aiter = iter->attr; aiter; aiter = aiter->next) {
777                 aiter->parent = diter;
778             }
779 
780             break;
781         }
782 
783         if (!diter) {
784             LOGVAL(ctx, LYE_XML_MISS, LY_VLOG_NONE, NULL, "element for the specified attribute", iter->attr->name);
785             lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
786             free(iter);
787             goto error;
788         }
789         free(iter);
790 
791         /* check edit-config attribute correctness */
792         if ((options & LYD_OPT_EDIT) && lyp_check_edit_attr(ctx, diter->attr, diter, NULL)) {
793             goto error;
794         }
795     }
796 
797     return 0;
798 
799 error:
800 
801     while (attrs) {
802         iter = attrs;
803         attrs = attrs->next;
804 
805         lyd_free_attr(ctx, NULL, iter->attr, 1);
806         free(iter);
807     }
808 
809     return -1;
810 }
811 
812 /**
813  * @brief Skip subtree (find its end in the input data) of the current JSON item.
814  * @param[in] ctx libyang context for logging
815  * @param[in] parent parent node for logging
816  * @param[in] data input data (pointing to the beginning, @p len is used to go to the current position).
817  * @param[in, out] len Current position in the @p data, will be updated to the end of the element's subtree in the @p data
818  * @retun 0 on success
819  * @return -1 on error.
820  */
821 static int
json_skip_unknown(struct ly_ctx * ctx,struct lyd_node * parent,const char * data,unsigned int * len)822 json_skip_unknown(struct ly_ctx *ctx, struct lyd_node *parent, const char *data, unsigned int *len)
823 {
824     int qstr = 0;
825     int objects = 0;
826     int arrays = 0;
827 
828     while (data[*len]) {
829         switch (data[*len]) {
830         case '\"':
831             if (qstr) {
832                 if (data[(*len) - 1] != '\\')  {
833                     qstr = 0;
834                 }
835             } else if (data[(*len) - 1] != '\\') {
836                 qstr = 1;
837             } else {
838                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, parent, "JSON data (missing quotation mark for a string data) ");
839                 return -1;
840             }
841             break;
842         case '[':
843             if (!qstr) {
844                 arrays++;
845             }
846             break;
847         case '{':
848             if (!qstr) {
849                 objects++;
850             }
851             break;
852         case ']':
853             if (!qstr) {
854                 arrays--;
855             }
856             break;
857         case '}':
858             if (!qstr) {
859                 objects--;
860             }
861             break;
862         case ',':
863             if (!qstr && !objects && !arrays) {
864                 /* do not eat the comma character */
865                 return 0;
866             }
867         }
868 
869         if (objects < 0) {
870             if (arrays) {
871                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, parent, "JSON data (missing end-array)");
872                 return -1;
873             }
874             return 0;
875         }
876         if (arrays < 0) {
877             if (objects) {
878                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, parent, "JSON data (missing end-object)");
879                 return -1;
880             }
881             return 0;
882         }
883         (*len)++;
884     }
885 
886     return 0;
887 }
888 
889 static unsigned int
json_parse_data(struct ly_ctx * ctx,const char * data,const struct lys_node * schema_parent,struct lyd_node ** parent,struct lyd_node * first_sibling,struct lyd_node * prev,struct attr_cont ** attrs,int options,struct unres_data * unres,struct lyd_node ** act_notif,const char * yang_data_name)890 json_parse_data(struct ly_ctx *ctx, const char *data, const struct lys_node *schema_parent, struct lyd_node **parent,
891                 struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
892                 struct unres_data *unres, struct lyd_node **act_notif, const char *yang_data_name)
893 {
894     unsigned int len = 0;
895     unsigned int r;
896     unsigned int flag_leaflist = 0;
897     int i;
898     uint8_t pos;
899     char *name, *prefix = NULL, *str = NULL;
900     const struct lys_module *module = NULL;
901     struct lys_node *schema = NULL;
902     const struct lys_node *sparent = NULL;
903     struct lyd_node *result = NULL, *new, *list, *diter = NULL;
904     struct lyd_attr *attr;
905     struct attr_cont *attrs_aux;
906 
907     /* each YANG data node representation starts with string (node identifier) */
908     if (data[len] != '"') {
909         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
910                "JSON data (missing quotation-mark at the beginning of string)");
911         return 0;
912     }
913     len++;
914 
915     str = lyjson_parse_text(ctx, &data[len], &r);
916     if (!str) {
917         goto error;
918     }
919 
920     if (!r) {
921         goto error;
922     } else if (data[len + r] != '"') {
923         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
924                "JSON data (missing quotation-mark at the end of string)");
925         goto error;
926     }
927     if ((name = strchr(str, ':'))) {
928         *name = '\0';
929         name++;
930         prefix = str;
931         if (prefix[0] == '@') {
932             prefix++;
933         }
934     } else {
935         name = str;
936         if (name[0] == '@') {
937             name++;
938         }
939     }
940 
941     /* prepare data for parsing node content */
942     len += r + 1;
943     len += skip_ws(&data[len]);
944     if (data[len] != ':') {
945         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing name-separator)");
946         goto error;
947     }
948     len++;
949     len += skip_ws(&data[len]);
950 
951     if (str[0] == '@' && !str[1]) {
952         /* process attribute of the parent object (container or list) */
953         if (!(*parent)) {
954             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "attribute with no corresponding element to belongs to");
955             goto error;
956         }
957 
958         r = json_parse_attr((*parent)->schema->module, &attr, &data[len], options);
959         if (!r) {
960             LOGPATH(ctx, LY_VLOG_LYD, *parent);
961             goto error;
962         }
963         len += r;
964 
965         if ((*parent)->attr) {
966             lyd_free_attr(ctx, NULL, attr, 1);
967         } else {
968             (*parent)->attr = attr;
969             for (; attr; attr = attr->next) {
970                 attr->parent = *parent;
971             }
972         }
973 
974         /* check edit-config attribute correctness */
975         if ((options & LYD_OPT_EDIT) && lyp_check_edit_attr(ctx, (*parent)->attr, *parent, NULL)) {
976             goto error;
977         }
978 
979         free(str);
980         return len;
981     }
982 
983     /* find schema node */
984     if (!(*parent)) {
985         /* starting in root */
986         /* get the proper schema */
987         module = ly_ctx_get_module(ctx, prefix, NULL, 0);
988         if (ctx->data_clb) {
989             if (!module) {
990                 module = ctx->data_clb(ctx, prefix, NULL, 0, ctx->data_clb_data);
991             } else if (!module->implemented) {
992                 module = ctx->data_clb(ctx, module->name, module->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
993             }
994         }
995         if (module && module->implemented) {
996             if (yang_data_name) {
997                 sparent = lyp_get_yang_data_template(module, yang_data_name, strlen(yang_data_name));
998                 schema = NULL;
999                 if (sparent) {
1000                     /* get the proper schema node */
1001                     while ((schema = (struct lys_node *) lys_getnext(schema, sparent, module, 0))) {
1002                         if (!strcmp(schema->name, name)) {
1003                             break;
1004                         }
1005                     }
1006                 }
1007             } else {
1008                 /* get the proper schema node */
1009                 while ((schema = (struct lys_node *) lys_getnext(schema, NULL, module, 0))) {
1010                     if (!strcmp(schema->name, name)) {
1011                         break;
1012                     }
1013                 }
1014             }
1015         }
1016     } else {
1017         if (prefix) {
1018             /* get the proper module to give the chance to load/implement it */
1019             module = ly_ctx_get_module(ctx, prefix, NULL, 1);
1020             if (ctx->data_clb) {
1021                 if (!module) {
1022                     ctx->data_clb(ctx, prefix, NULL, 0, ctx->data_clb_data);
1023                 } else if (!module->implemented) {
1024                     ctx->data_clb(ctx, module->name, module->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
1025                 }
1026             }
1027         }
1028 
1029         /* go through RPC's input/output following the options' data type */
1030         if ((*parent)->schema->nodetype == LYS_RPC || (*parent)->schema->nodetype == LYS_ACTION) {
1031             while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, NULL, LYS_GETNEXT_WITHINOUT))) {
1032                 if ((options & LYD_OPT_RPC) && (schema->nodetype == LYS_INPUT)) {
1033                     break;
1034                 } else if ((options & LYD_OPT_RPCREPLY) && (schema->nodetype == LYS_OUTPUT)) {
1035                     break;
1036                 }
1037             }
1038             schema_parent = schema;
1039             schema = NULL;
1040         }
1041 
1042         if (schema_parent) {
1043             while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, NULL, 0))) {
1044                 if (!strcmp(schema->name, name)
1045                         && ((prefix && !strcmp(lys_node_module(schema)->name, prefix))
1046                         || (!prefix && (lys_node_module(schema) == lys_node_module(schema_parent))))) {
1047                     break;
1048                 }
1049             }
1050         } else {
1051             while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, NULL, 0))) {
1052                 if (!strcmp(schema->name, name)
1053                         && ((prefix && !strcmp(lys_node_module(schema)->name, prefix))
1054                         || (!prefix && (lys_node_module(schema) == lyd_node_module(*parent))))) {
1055                     break;
1056                 }
1057             }
1058         }
1059     }
1060 
1061     module = lys_node_module(schema);
1062     if (!module || !module->implemented || module->disabled) {
1063         if (options & LYD_OPT_STRICT) {
1064             LOGVAL(ctx, LYE_INELEM, (*parent ? LY_VLOG_LYD : LY_VLOG_NONE), (*parent), name);
1065             goto error;
1066         } else {
1067             if (json_skip_unknown(ctx, *parent, data, &len)) {
1068                 goto error;
1069             }
1070             free(str);
1071             return len;
1072         }
1073     }
1074 
1075     if (str[0] == '@') {
1076         /* attribute for some sibling node */
1077         if (data[len] == '[') {
1078             flag_leaflist = 1;
1079             len++;
1080             len += skip_ws(&data[len]);
1081         }
1082 
1083 attr_repeat:
1084         r = json_parse_attr((struct lys_module *)module, &attr, &data[len], options);
1085         if (!r) {
1086             LOGPATH(ctx, LY_VLOG_LYD, (*parent));
1087             goto error;
1088         }
1089         len += r;
1090 
1091         if (attr) {
1092             attrs_aux = malloc(sizeof *attrs_aux);
1093             LY_CHECK_ERR_GOTO(!attrs_aux, LOGMEM(ctx), error);
1094             attrs_aux->attr = attr;
1095             attrs_aux->index = flag_leaflist;
1096             attrs_aux->schema = schema;
1097             attrs_aux->next = *attrs;
1098             *attrs = attrs_aux;
1099         }
1100 
1101         if (flag_leaflist) {
1102             if (data[len] == ',') {
1103                 len++;
1104                 len += skip_ws(&data[len]);
1105                 flag_leaflist++;
1106                 goto attr_repeat;
1107             } else if (data[len] != ']') {
1108                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing end-array)");
1109                 goto error;
1110             }
1111             len++;
1112             len += skip_ws(&data[len]);
1113         }
1114 
1115         free(str);
1116         return len;
1117     }
1118 
1119     switch (schema->nodetype) {
1120     case LYS_CONTAINER:
1121     case LYS_LIST:
1122     case LYS_NOTIF:
1123     case LYS_RPC:
1124     case LYS_ACTION:
1125         result = calloc(1, sizeof *result);
1126         break;
1127     case LYS_LEAF:
1128     case LYS_LEAFLIST:
1129         result = calloc(1, sizeof(struct lyd_node_leaf_list));
1130         break;
1131     case LYS_ANYXML:
1132     case LYS_ANYDATA:
1133         result = calloc(1, sizeof(struct lyd_node_anydata));
1134         break;
1135     default:
1136         LOGINT(ctx);
1137         goto error;
1138     }
1139     LY_CHECK_ERR_GOTO(!result, LOGMEM(ctx), error);
1140 
1141     result->prev = result;
1142     result->schema = schema;
1143     result->parent = *parent;
1144     diter = NULL;
1145     if (lys_is_key((struct lys_node_leaf *)schema, &pos)) {
1146         /* it is key and we need to insert it into a correct place (we must have parent then, a key cannot be top-level) */
1147         assert(*parent);
1148         for (i = 0, diter = (*parent)->child;
1149                 diter && i < pos && diter->schema->nodetype == LYS_LEAF && lys_is_key((struct lys_node_leaf *)diter->schema, NULL);
1150                 i++, diter = diter->next);
1151         if (diter) {
1152             /* out of order insertion - insert list's key to the correct position, before the diter */
1153             if ((*parent)->child == diter) {
1154                 (*parent)->child = result;
1155                 /* update first_sibling */
1156                 first_sibling = result;
1157             }
1158             if (diter->prev->next) {
1159                 diter->prev->next = result;
1160             }
1161             result->prev = diter->prev;
1162             diter->prev = result;
1163             result->next = diter;
1164         }
1165     }
1166     if (!diter) {
1167         /* simplified (faster) insert as the last node */
1168         if (*parent && !(*parent)->child) {
1169             (*parent)->child = result;
1170         }
1171         if (prev) {
1172             result->prev = prev;
1173             prev->next = result;
1174 
1175             /* fix the "last" pointer */
1176             first_sibling->prev = result;
1177         } else {
1178             result->prev = result;
1179             first_sibling = result;
1180         }
1181     }
1182     result->validity = ly_new_node_validity(result->schema);
1183     if (resolve_applies_when(schema, 0, NULL)) {
1184         result->when_status = LYD_WHEN;
1185     }
1186 
1187     /* type specific processing */
1188     switch (schema->nodetype) {
1189     case LYS_LEAF:
1190     case LYS_LEAFLIST:
1191         /* type detection and assigning the value */
1192         r = json_get_value((struct lyd_node_leaf_list *)result, &first_sibling, &data[len], options, unres);
1193         if (!r) {
1194             goto error;
1195         }
1196         /* only for leaf-list */
1197         while (result->next && (result->next->schema == result->schema)) {
1198             result = result->next;
1199         }
1200 
1201         len += r;
1202         len += skip_ws(&data[len]);
1203         break;
1204     case LYS_ANYDATA:
1205     case LYS_ANYXML:
1206         r = json_get_anydata((struct lyd_node_anydata *)result, &data[len]);
1207         if (!r) {
1208             goto error;
1209         }
1210 
1211 #ifdef LY_ENABLED_CACHE
1212         /* calculate the hash and insert it into parent */
1213         lyd_hash(result);
1214         lyd_insert_hash(result);
1215 #endif
1216 
1217         len += r;
1218         len += skip_ws(&data[len]);
1219         break;
1220     case LYS_CONTAINER:
1221     case LYS_RPC:
1222     case LYS_ACTION:
1223     case LYS_NOTIF:
1224         if (schema->nodetype & (LYS_RPC | LYS_ACTION)) {
1225             if (!(options & LYD_OPT_RPC) || *act_notif) {
1226                 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, result, schema->name);
1227                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected %s node \"%s\".",
1228                        (schema->nodetype == LYS_RPC ? "rpc" : "action"), schema->name);
1229                 goto error;
1230             }
1231             *act_notif = result;
1232         } else if (schema->nodetype == LYS_NOTIF) {
1233             if (!(options & LYD_OPT_NOTIF) || *act_notif) {
1234                 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, result, schema->name);
1235                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected notification node \"%s\".", schema->name);
1236                 goto error;
1237             }
1238             *act_notif = result;
1239         }
1240 
1241 #ifdef LY_ENABLED_CACHE
1242         /* calculate the hash and insert it into parent */
1243         lyd_hash(result);
1244         lyd_insert_hash(result);
1245 #endif
1246 
1247         if (data[len] != '{') {
1248             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-object)");
1249             goto error;
1250         }
1251         len++;
1252         len += skip_ws(&data[len]);
1253 
1254         if (data[len] != '}') {
1255             /* non-empty container */
1256             len--;
1257             diter = NULL;
1258             attrs_aux = NULL;
1259             do {
1260                 len++;
1261                 len += skip_ws(&data[len]);
1262 
1263                 r = json_parse_data(ctx, &data[len], NULL, &result, result->child, diter, &attrs_aux, options, unres, act_notif, yang_data_name);
1264                 if (!r) {
1265                     goto error;
1266                 }
1267                 len += r;
1268 
1269                 if (result->child) {
1270                     diter = result->child->prev;
1271                 }
1272             } while(data[len] == ',');
1273 
1274             /* store attributes */
1275             if (store_attrs(ctx, attrs_aux, result->child, options)) {
1276                 goto error;
1277             }
1278         }
1279 
1280         if (data[len] != '}') {
1281             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-object)");
1282             goto error;
1283         }
1284         len++;
1285         len += skip_ws(&data[len]);
1286 
1287         /* if we have empty non-presence container, mark it as default */
1288         if (schema->nodetype == LYS_CONTAINER && !result->child &&
1289                 !result->attr && !((struct lys_node_container *)schema)->presence) {
1290             result->dflt = 1;
1291         }
1292         break;
1293     case LYS_LIST:
1294         if (data[len] != '[') {
1295             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-array)");
1296             goto error;
1297         }
1298 
1299         list = result;
1300         do {
1301             len++;
1302             len += skip_ws(&data[len]);
1303 
1304             if (data[len] != '{') {
1305                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result,
1306                        "JSON data (missing list instance's begin-object)");
1307                 goto error;
1308             }
1309             diter = NULL;
1310             attrs_aux = NULL;
1311             do {
1312                 len++;
1313                 len += skip_ws(&data[len]);
1314 
1315                 r = json_parse_data(ctx, &data[len], NULL, &list, list->child, diter, &attrs_aux, options, unres, act_notif, yang_data_name);
1316                 if (!r) {
1317                     goto error;
1318                 }
1319                 len += r;
1320 
1321                 if (list->child) {
1322                     diter = list->child->prev;
1323                 }
1324             } while (data[len] == ',');
1325 
1326 #ifdef LY_ENABLED_CACHE
1327             /* calculate the hash and insert it into parent */
1328             if (!((struct lys_node_list *)list->schema)->keys_size) {
1329                 lyd_hash(list);
1330                 lyd_insert_hash(list);
1331             }
1332 #endif
1333 
1334             /* store attributes */
1335             if (store_attrs(ctx, attrs_aux, list->child, options)) {
1336                 goto error;
1337             }
1338 
1339             if (data[len] != '}') {
1340                 /* expecting end-object */
1341                 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result,
1342                        "JSON data (missing list instance's end-object)");
1343                 goto error;
1344             }
1345             len++;
1346             len += skip_ws(&data[len]);
1347 
1348             if (data[len] == ',') {
1349                 /* various validation checks */
1350                 if (lyv_data_context(list, options, 0, unres) ||
1351                         lyv_data_content(list, options, unres) ||
1352                         lyv_multicases(list, NULL, prev ? &first_sibling : NULL, 0, NULL)) {
1353                     goto error;
1354                 }
1355 
1356                 /* another instance of the list */
1357                 new = calloc(1, sizeof *new);
1358                 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx), error);
1359                 new->parent = list->parent;
1360                 new->prev = list;
1361                 list->next = new;
1362 
1363                 /* copy the validity and when flags */
1364                 new->validity = list->validity;
1365                 new->when_status = list->when_status;
1366 
1367                 /* fix the "last" pointer */
1368                 first_sibling->prev = new;
1369 
1370                 new->schema = list->schema;
1371                 list = new;
1372             }
1373         } while (data[len] == ',');
1374         result = list;
1375 
1376         if (data[len] != ']') {
1377             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-array)");
1378             goto error;
1379         }
1380         len++;
1381         len += skip_ws(&data[len]);
1382         break;
1383     default:
1384         LOGINT(ctx);
1385         goto error;
1386     }
1387 
1388     /* various validation checks */
1389     if (lyv_data_context(result, options, 0, unres) ||
1390             lyv_data_content(result, options, unres) ||
1391             lyv_multicases(result, NULL, prev ? &first_sibling : NULL, 0, NULL)) {
1392         goto error;
1393     }
1394 
1395     /* validation successful */
1396     if (result->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
1397         /* postpone checking of unique when there will be all list/leaflist instances */
1398         result->validity |= LYD_VAL_DUP;
1399     }
1400 
1401     if (!(*parent)) {
1402         *parent = result;
1403     }
1404 
1405     free(str);
1406     return len;
1407 
1408 error:
1409     /* cleanup */
1410     for (i = unres->count - 1; i >= 0; i--) {
1411         /* remove unres items connected with the node being removed */
1412         if (unres->node[i] == result) {
1413             unres_data_del(unres, i);
1414         }
1415     }
1416     while (*attrs) {
1417         attrs_aux = *attrs;
1418         *attrs = (*attrs)->next;
1419 
1420         lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1421         free(attrs_aux);
1422     }
1423 
1424     lyd_free(result);
1425     free(str);
1426 
1427     return 0;
1428 }
1429 
1430 struct lyd_node *
lyd_parse_json(struct ly_ctx * ctx,const char * data,int options,const struct lyd_node * rpc_act,const struct lyd_node * data_tree,const char * yang_data_name)1431 lyd_parse_json(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *rpc_act,
1432                const struct lyd_node *data_tree, const char *yang_data_name)
1433 {
1434     struct lyd_node *result = NULL, *next, *iter, *reply_parent = NULL, *reply_top = NULL, *act_notif = NULL;
1435     struct unres_data *unres = NULL;
1436     unsigned int len = 0, r;
1437     int act_cont = 0;
1438     struct attr_cont *attrs = NULL;
1439 
1440     if (!ctx || !data) {
1441         LOGARG;
1442         return NULL;
1443     }
1444 
1445     /* skip leading whitespaces */
1446     len += skip_ws(&data[len]);
1447 
1448     /* expect top-level { */
1449     if (data[len] != '{') {
1450         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level begin-object)");
1451         return NULL;
1452     }
1453 
1454     /* check for empty object */
1455     r = len + 1;
1456     r += skip_ws(&data[r]);
1457     if (data[r] == '}') {
1458         if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1459             result = ly_ctx_info(ctx);
1460         }
1461         lyd_validate(&result, options, ctx);
1462         return result;
1463     }
1464 
1465     unres = calloc(1, sizeof *unres);
1466     LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
1467 
1468     /* create RPC/action reply part that is not in the parsed data */
1469     if (rpc_act) {
1470         assert(options & LYD_OPT_RPCREPLY);
1471         if (rpc_act->schema->nodetype == LYS_RPC) {
1472             /* RPC request */
1473             reply_top = reply_parent = _lyd_new(NULL, rpc_act->schema, 0);
1474         } else {
1475             /* action request */
1476             reply_top = lyd_dup(rpc_act, 1);
1477             LY_TREE_DFS_BEGIN(reply_top, iter, reply_parent) {
1478                 if (reply_parent->schema->nodetype == LYS_ACTION) {
1479                     break;
1480                 }
1481                 LY_TREE_DFS_END(reply_top, iter, reply_parent);
1482             }
1483             if (!reply_parent) {
1484                 LOGERR(ctx, LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *rpc_act).", __func__);
1485                 goto error;
1486             }
1487             lyd_free_withsiblings(reply_parent->child);
1488         }
1489     }
1490 
1491     iter = NULL;
1492     next = reply_parent;
1493     do {
1494         len++;
1495         len += skip_ws(&data[len]);
1496 
1497         if (!act_cont) {
1498             if (!strncmp(&data[len], "\"yang:action\"", 13)) {
1499                 len += 13;
1500                 len += skip_ws(&data[len]);
1501                 if (data[len] != ':') {
1502                     LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level begin-object)");
1503                     goto error;
1504                 }
1505                 ++len;
1506                 len += skip_ws(&data[len]);
1507                 if (data[len] != '{') {
1508                     LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level yang:action object)");
1509                     goto error;
1510                 }
1511                 ++len;
1512                 len += skip_ws(&data[len]);
1513 
1514                 act_cont = 1;
1515             } else {
1516                 act_cont = -1;
1517             }
1518         }
1519 
1520         r = json_parse_data(ctx, &data[len], NULL, &next, result, iter, &attrs, options, unres, &act_notif, yang_data_name);
1521         if (!r) {
1522             goto error;
1523         }
1524         len += r;
1525 
1526         if (!result) {
1527             if (reply_parent) {
1528                 result = next->child;
1529                 iter = next->child ? next->child->prev : NULL;
1530             } else {
1531                 for (iter = next; iter && iter->prev->next; iter = iter->prev);
1532                 result = iter;
1533                 if (iter && (options & LYD_OPT_DATA_ADD_YANGLIB) && iter->schema->module == ctx->models.list[ctx->internal_module_count - 1]) {
1534                     /* ietf-yang-library data present, so ignore the option to add them */
1535                     options &= ~LYD_OPT_DATA_ADD_YANGLIB;
1536                 }
1537                 iter = next;
1538             }
1539         } else {
1540             iter = result->prev;
1541         }
1542         if (!reply_parent) {
1543             next = NULL;
1544         }
1545     } while (data[len] == ',');
1546 
1547     if (data[len] != '}') {
1548         /* expecting end-object */
1549         LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
1550         goto error;
1551     }
1552     len++;
1553     len += skip_ws(&data[len]);
1554 
1555     if (act_cont == 1) {
1556         if (data[len] != '}') {
1557             LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
1558             goto error;
1559         }
1560         len++;
1561         len += skip_ws(&data[len]);
1562     }
1563 
1564     /* store attributes */
1565     if (store_attrs(ctx, attrs, result, options)) {
1566         goto error;
1567     }
1568 
1569     if (reply_top) {
1570         result = reply_top;
1571     }
1572 
1573     if (!result && (options & LYD_OPT_STRICT)) {
1574         LOGERR(ctx, LY_EVALID, "Model for the data to be linked with not found.");
1575         goto error;
1576     }
1577 
1578     /* order the elements by hand as it is not required of the JSON input */
1579     if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY))) {
1580         if (lyd_schema_sort(result, 1)) {
1581             goto error;
1582         }
1583     }
1584 
1585     if ((options & LYD_OPT_RPCREPLY) && (rpc_act->schema->nodetype != LYS_RPC)) {
1586         /* action reply */
1587         act_notif = reply_parent;
1588     } else if ((options & (LYD_OPT_RPC | LYD_OPT_NOTIF)) && !act_notif) {
1589         if (result) {
1590             LOGVAL(ctx, LYE_MISSELEM, LY_VLOG_LYD, result, (options & LYD_OPT_RPC ? "action" : "notification"),
1591                    result->schema->name);
1592         } else {
1593             LOGVAL(ctx, LYE_MISSELEM, LY_VLOG_NONE, NULL, (options & LYD_OPT_RPC ? "action" : "notification"), "data");
1594         }
1595         goto error;
1596     }
1597 
1598     /* add missing ietf-yang-library if requested */
1599     if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1600         if (lyd_merge(result, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1601             LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1602             goto error;
1603         }
1604     }
1605 
1606     /* check for uniquness of top-level lists/leaflists because
1607      * only the inner instances were tested in lyv_data_content() */
1608     LY_TREE_FOR(result, iter) {
1609         if (!(iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(iter->validity & LYD_VAL_DUP)) {
1610             continue;
1611         }
1612 
1613         if (lyv_data_dup(iter, result)) {
1614             goto error;
1615         }
1616     }
1617 
1618     /* add/validate default values, unres */
1619     if (lyd_defaults_add_unres(&result, options, ctx, NULL, 0, data_tree, act_notif, unres, 1)) {
1620         goto error;
1621     }
1622 
1623     /* check for missing top level mandatory nodes */
1624     if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))
1625             && lyd_check_mandatory_tree((act_notif ? act_notif : result), ctx, NULL, 0, options)) {
1626         goto error;
1627     }
1628 
1629     free(unres->node);
1630     free(unres->type);
1631     free(unres);
1632 
1633     return result;
1634 
1635 error:
1636     lyd_free_withsiblings(result);
1637     if (reply_top && result != reply_top) {
1638         lyd_free_withsiblings(reply_top);
1639     }
1640     free(unres->node);
1641     free(unres->type);
1642     free(unres);
1643 
1644     return NULL;
1645 }
1646