1 /**
2  * @file parser_lyb.c
3  * @author Michal Vasko <mvasko@cesnet.cz>
4  * @brief LYB data parser for libyang
5  *
6  * Copyright (c) 2018 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 #include <assert.h>
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <inttypes.h>
20 
21 #include "libyang.h"
22 #include "common.h"
23 #include "context.h"
24 #include "parser.h"
25 #include "tree_internal.h"
26 
27 #define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
28 #define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
29 
30 static int
lyb_read(const char * data,uint8_t * buf,size_t count,struct lyb_state * lybs)31 lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
32 {
33     int ret = 0, i, empty_chunk_i;
34     size_t to_read;
35     uint8_t meta_buf[LYB_META_BYTES];
36 
37     assert(data && lybs);
38 
39     while (1) {
40         /* check for fully-read (empty) data chunks */
41         to_read = count;
42         empty_chunk_i = -1;
43         for (i = 0; i < lybs->used; ++i) {
44             /* we want the innermost chunks resolved first, so replace previous empty chunks,
45              * also ignore chunks that are completely finished, there is nothing for us to do */
46             if ((lybs->written[i] <= to_read) && lybs->position[i]) {
47                 /* empty chunk, do not read more */
48                 to_read = lybs->written[i];
49                 empty_chunk_i = i;
50             }
51         }
52 
53         if ((empty_chunk_i == -1) && !count) {
54             break;
55         }
56 
57         /* we are actually reading some data, not just finishing another chunk */
58         if (to_read) {
59             if (buf) {
60                 memcpy(buf, data + ret, to_read);
61             }
62 
63             for (i = 0; i < lybs->used; ++i) {
64                 /* decrease all written counters */
65                 lybs->written[i] -= to_read;
66                 assert(lybs->written[i] <= LYB_SIZE_MAX);
67             }
68             /* decrease count/buf */
69             count -= to_read;
70             if (buf) {
71                 buf += to_read;
72             }
73 
74             ret += to_read;
75         }
76 
77         if (empty_chunk_i > -1) {
78             /* read the next chunk meta information */
79             memcpy(meta_buf, data + ret, LYB_META_BYTES);
80             lybs->written[empty_chunk_i] = meta_buf[0];
81             lybs->inner_chunks[empty_chunk_i] = meta_buf[1];
82 
83             /* remember whether there is a following chunk or not */
84             lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
85 
86             ret += LYB_META_BYTES;
87         }
88     }
89 
90     return ret;
91 }
92 
93 static int
lyb_read_number(void * num,size_t num_size,size_t bytes,const char * data,struct lyb_state * lybs)94 lyb_read_number(void *num, size_t num_size, size_t bytes, const char *data, struct lyb_state *lybs)
95 {
96     int r, ret = 0;
97     uint64_t buf = 0;
98 
99     ret += (r = lyb_read(data, (uint8_t *)&buf, bytes, lybs));
100     LYB_HAVE_READ_RETURN(r, data, -1);
101 
102     /* correct byte order */
103     buf = le64toh(buf);
104 
105     switch (num_size) {
106     case 1:
107         *((uint8_t *)num) = buf;
108         break;
109     case 2:
110         *((uint16_t *)num) = buf;
111         break;
112     case 4:
113         *((uint32_t *)num) = buf;
114         break;
115     case 8:
116         *((uint64_t *)num) = buf;
117         break;
118     default:
119         LOGINT(lybs->ctx);
120         return -1;
121     }
122 
123     return ret;
124 }
125 
126 static int
lyb_read_enum(uint64_t * enum_idx,uint32_t count,const char * data,struct lyb_state * lybs)127 lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
128 {
129     size_t bytes;
130 
131     if (count < (1 << 8)) {
132         bytes = 1;
133     } else if (count < (1 << 16)) {
134         bytes = 2;
135     } else if (count < (1 << 24)) {
136         bytes = 3;
137     } else {
138         bytes = 4;
139     }
140 
141     /* enum is always read into a uint64_t buffer */
142     *enum_idx = 0;
143     return lyb_read_number(enum_idx, sizeof *enum_idx, bytes, data, lybs);
144 }
145 
146 static int
lyb_read_string(const char * data,char ** str,int with_length,struct lyb_state * lybs)147 lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
148 {
149     int next_chunk = 0, r, ret = 0;
150     size_t len = 0, cur_len;
151 
152     if (with_length) {
153         ret += (r = lyb_read_number(&len, sizeof len, 2, data, lybs));
154         LYB_HAVE_READ_GOTO(r, data, error);
155     } else {
156         /* read until the end of this subtree */
157         len = lybs->written[lybs->used - 1];
158         if (lybs->position[lybs->used - 1]) {
159             next_chunk = 1;
160         }
161     }
162 
163     *str = malloc((len + 1) * sizeof **str);
164     LY_CHECK_ERR_RETURN(!*str, LOGMEM(lybs->ctx), -1);
165 
166     ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
167     LYB_HAVE_READ_GOTO(r, data, error);
168 
169     while (next_chunk) {
170         cur_len = lybs->written[lybs->used - 1];
171         if (lybs->position[lybs->used - 1]) {
172             next_chunk = 1;
173         } else {
174             next_chunk = 0;
175         }
176 
177         *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
178         LY_CHECK_ERR_RETURN(!*str, LOGMEM(lybs->ctx), -1);
179 
180         ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
181         LYB_HAVE_READ_GOTO(r, data, error);
182 
183         len += cur_len;
184     }
185 
186     ((char *)*str)[len] = '\0';
187     return ret;
188 
189 error:
190     free((char *)*str);
191     *str = NULL;
192     return -1;
193 }
194 
195 static void
lyb_read_stop_subtree(struct lyb_state * lybs)196 lyb_read_stop_subtree(struct lyb_state *lybs)
197 {
198     if (lybs->written[lybs->used - 1]) {
199         LOGINT(lybs->ctx);
200     }
201 
202     --lybs->used;
203 }
204 
205 static int
lyb_read_start_subtree(const char * data,struct lyb_state * lybs)206 lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
207 {
208     uint8_t meta_buf[LYB_META_BYTES];
209 
210     if (lybs->used == lybs->size) {
211         lybs->size += LYB_STATE_STEP;
212         lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
213         lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
214         lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
215         LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(lybs->ctx), -1);
216     }
217 
218     memcpy(meta_buf, data, LYB_META_BYTES);
219 
220     ++lybs->used;
221     lybs->written[lybs->used - 1] = meta_buf[0];
222     lybs->inner_chunks[lybs->used - 1] = meta_buf[LYB_SIZE_BYTES];
223     lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
224 
225     return LYB_META_BYTES;
226 }
227 
228 static int
lyb_parse_model(const char * data,const struct lys_module ** mod,int options,struct lyb_state * lybs)229 lyb_parse_model(const char *data, const struct lys_module **mod, int options, struct lyb_state *lybs)
230 {
231     int r, ret = 0;
232     char *mod_name = NULL, mod_rev[11];
233     uint16_t rev;
234 
235     /* model name */
236     ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
237     LYB_HAVE_READ_GOTO(r, data, error);
238 
239     /* revision */
240     ret += (r = lyb_read_number(&rev, sizeof rev, 2, data, lybs));
241     LYB_HAVE_READ_GOTO(r, data, error);
242 
243     if (rev) {
244         sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, rev & 0x001Fu);
245         *mod = ly_ctx_get_module(lybs->ctx, mod_name, mod_rev, 0);
246         if ((options & LYD_OPT_LYB_MOD_UPDATE) && !(*mod)) {
247             /* try to use an updated module */
248             *mod = ly_ctx_get_module(lybs->ctx, mod_name, NULL, 1);
249             if (*mod && (!(*mod)->implemented || !(*mod)->rev_size || (strcmp((*mod)->rev[0].date, mod_rev) < 0))) {
250                 /* not an implemented module in a newer revision */
251                 *mod = NULL;
252             }
253         }
254     } else {
255         *mod = ly_ctx_get_module(lybs->ctx, mod_name, NULL, 0);
256     }
257     if (lybs->ctx->data_clb) {
258         if (!*mod) {
259             *mod = lybs->ctx->data_clb(lybs->ctx, mod_name, NULL, 0, lybs->ctx->data_clb_data);
260         } else if (!(*mod)->implemented) {
261             *mod = lybs->ctx->data_clb(lybs->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybs->ctx->data_clb_data);
262         }
263     }
264 
265     if (!*mod) {
266         LOGERR(lybs->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
267                mod_name, rev ? "@" : "", rev ? mod_rev : "");
268         goto error;
269     } else if (!(*mod)->implemented) {
270         LOGERR(lybs->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
271                mod_name, rev ? "@" : "", rev ? mod_rev : "");
272         goto error;
273     }
274 
275     free(mod_name);
276     return ret;
277 
278 error:
279     free(mod_name);
280     return -1;
281 }
282 
283 static struct lyd_node *
lyb_new_node(const struct lys_node * schema,int options)284 lyb_new_node(const struct lys_node *schema, int options)
285 {
286     struct lyd_node *node;
287 
288     switch (schema->nodetype) {
289     case LYS_CONTAINER:
290     case LYS_LIST:
291     case LYS_NOTIF:
292     case LYS_RPC:
293     case LYS_ACTION:
294         node = calloc(sizeof(struct lyd_node), 1);
295         break;
296     case LYS_LEAF:
297     case LYS_LEAFLIST:
298         node = calloc(sizeof(struct lyd_node_leaf_list), 1);
299         break;
300     case LYS_ANYDATA:
301     case LYS_ANYXML:
302         node = calloc(sizeof(struct lyd_node_anydata), 1);
303         break;
304     default:
305         return NULL;
306     }
307     LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
308 
309     /* fill basic info */
310     node->schema = (struct lys_node *)schema;
311     if (resolve_applies_when(schema, 0, NULL)) {
312         node->when_status = LYD_WHEN;
313 
314         if (options & LYD_OPT_TRUSTED) {
315             /* this data are considered trusted so if this node exists, it means its when must have been true */
316             node->when_status |= LYD_WHEN_TRUE;
317         }
318     }
319     node->prev = node;
320 
321     return node;
322 }
323 
324 static int
lyb_parse_anydata(struct lyd_node * node,const char * data,struct lyb_state * lybs)325 lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
326 {
327     int r, ret = 0;
328     char *str = NULL;
329     struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
330 
331     /* read value type */
332     ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
333     LYB_HAVE_READ_RETURN(r, data, -1);
334 
335     /* read anydata content */
336     if (any->value_type == LYD_ANYDATA_DATATREE) {
337         /* invalid situation */
338         LOGINT(node->schema->module->ctx);
339         return -1;
340     } else if (any->value_type == LYD_ANYDATA_LYB) {
341         ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
342         LYB_HAVE_READ_RETURN(r, data, -1);
343     } else {
344         ret += (r = lyb_read_string(data, &str, 0, lybs));
345         LYB_HAVE_READ_RETURN(r, data, -1);
346 
347         /* add to dictionary */
348         any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
349     }
350 
351     return ret;
352 }
353 
354 /* generally, fill lyd_val value union */
355 static int
lyb_parse_val_1(struct lys_type * type,LY_DATA_TYPE value_type,uint8_t value_flags,const char * data,const char ** value_str,lyd_val * value,struct lyb_state * lybs)356 lyb_parse_val_1(struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
357         const char **value_str, lyd_val *value, struct lyb_state *lybs)
358 {
359     int r, ret;
360     size_t i;
361     char *str = NULL;
362     uint8_t byte;
363     uint64_t num;
364 
365     if (value_flags & LY_VALUE_USER) {
366         /* just read value_str */
367         ret = lyb_read_string(data, &str, 0, lybs);
368         if (ret > -1) {
369             *value_str = lydict_insert_zc(lybs->ctx, str);
370         }
371         return ret;
372     }
373 
374     /* find the correct structure, go through leafrefs and typedefs */
375     switch (value_type) {
376     case LY_TYPE_ENUM:
377         for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
378         for (; !type->info.enums.count; type = &type->der->type);
379         break;
380     case LY_TYPE_BITS:
381         for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
382         for (; !type->info.bits.count; type = &type->der->type);
383         break;
384     default:
385         break;
386     }
387 
388     switch (value_type) {
389     case LY_TYPE_INST:
390     case LY_TYPE_IDENT:
391     case LY_TYPE_UNION:
392         /* we do not actually fill value now, but value_str */
393         ret = lyb_read_string(data, &str, 0, lybs);
394         if (ret > -1) {
395             *value_str = lydict_insert_zc(lybs->ctx, str);
396         }
397         break;
398     case LY_TYPE_BINARY:
399     case LY_TYPE_STRING:
400     case LY_TYPE_UNKNOWN:
401         /* read string */
402         ret = lyb_read_string(data, &str, 0, lybs);
403         if (ret > -1) {
404             value->string = lydict_insert_zc(lybs->ctx, str);
405         }
406         break;
407     case LY_TYPE_BITS:
408         value->bit = calloc(type->info.bits.count, sizeof *value->bit);
409         LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(lybs->ctx), -1);
410 
411         /* read values */
412         ret = 0;
413         for (i = 0; i < type->info.bits.count; ++i) {
414             if (i % 8 == 0) {
415                 /* read another byte */
416                 ret += (r = lyb_read(data + ret, &byte, sizeof byte, lybs));
417                 if (r < 0) {
418                     return -1;
419                 }
420             }
421 
422             if (byte & (0x01 << (i % 8))) {
423                 /* bit is set */
424                 value->bit[i] = &type->info.bits.bit[i];
425             }
426         }
427         break;
428     case LY_TYPE_BOOL:
429         /* read byte */
430         ret = lyb_read(data, &byte, sizeof byte, lybs);
431         if ((ret > 0) && byte) {
432             value->bln = 1;
433         }
434         break;
435     case LY_TYPE_EMPTY:
436         /* nothing to read */
437         ret = 0;
438         break;
439     case LY_TYPE_ENUM:
440         num = 0;
441         ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
442         if (ret > 0) {
443             assert(num < type->info.enums.count);
444             value->enm = &type->info.enums.enm[num];
445         }
446         break;
447     case LY_TYPE_INT8:
448     case LY_TYPE_UINT8:
449         ret = lyb_read_number(&value->uint8, sizeof value->uint8, 1, data, lybs);
450         break;
451     case LY_TYPE_INT16:
452     case LY_TYPE_UINT16:
453         ret = lyb_read_number(&value->uint16, sizeof value->uint16, 2, data, lybs);
454         break;
455     case LY_TYPE_INT32:
456     case LY_TYPE_UINT32:
457         ret = lyb_read_number(&value->uint32, sizeof value->uint32, 4, data, lybs);
458         break;
459     case LY_TYPE_DEC64:
460     case LY_TYPE_INT64:
461     case LY_TYPE_UINT64:
462         ret = lyb_read_number(&value->uint64, sizeof value->uint64, 8, data, lybs);
463         break;
464     default:
465         return -1;
466     }
467 
468     return ret;
469 }
470 
471 /* generally, fill value_str */
472 static int
lyb_parse_val_2(struct lys_type * type,struct lyd_node_leaf_list * leaf,struct lyd_attr * attr,struct unres_data * unres)473 lyb_parse_val_2(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct unres_data *unres)
474 {
475     struct ly_ctx *ctx;
476     struct lys_module *mod;
477     struct lys_type *rtype = NULL;
478     char num_str[22], *str;
479     int64_t frac, num;
480     uint32_t i, str_len;
481     uint8_t *value_flags, dig;
482     const char **value_str;
483     LY_DATA_TYPE value_type;
484     lyd_val *value;
485 
486     if (leaf) {
487         ctx = leaf->schema->module->ctx;
488         mod = lys_node_module(leaf->schema);
489 
490         value = &leaf->value;
491         value_str = &leaf->value_str;
492         value_flags = &leaf->value_flags;
493         value_type = leaf->value_type;
494     } else {
495         ctx = attr->annotation->module->ctx;
496         mod = lys_main_module(attr->annotation->module);
497 
498         value = &attr->value;
499         value_str = &attr->value_str;
500         value_flags = &attr->value_flags;
501         value_type = attr->value_type;
502     }
503 
504     if (*value_flags & LY_VALUE_USER) {
505         /* unfortunately, we need to also fill the value properly, so just parse it again */
506         *value_flags &= ~LY_VALUE_USER;
507         if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0))) {
508             return -1;
509         }
510 
511         if (!(*value_flags & LY_VALUE_USER)) {
512             LOGWRN(ctx, "Value \"%s\" was stored as a user type, but it is not in the current context.", value_str);
513         }
514         return 0;
515     }
516 
517     /* we are parsing leafref/ptr union stored as the target type,
518      * so we first parse it into string and then resolve the leafref/ptr union */
519     if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
520             || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
521         if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
522             /* we already have a string */
523             goto parse_reference;
524         }
525     }
526 
527     /* find the correct structure, go through leafrefs and typedefs */
528     switch (value_type) {
529     case LY_TYPE_BITS:
530         for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &rtype->info.lref.target->type);
531         for (; !rtype->info.bits.count; rtype = &rtype->der->type);
532         break;
533     case LY_TYPE_DEC64:
534         for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &type->info.lref.target->type);
535         break;
536     default:
537         break;
538     }
539 
540     switch (value_type) {
541     case LY_TYPE_IDENT:
542         /* fill the identity pointer now */
543         value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
544         if (!value->ident) {
545             return -1;
546         }
547         break;
548     case LY_TYPE_INST:
549         /* unresolved instance-identifier, keep value NULL */
550         value->instance = NULL;
551         break;
552     case LY_TYPE_BINARY:
553     case LY_TYPE_STRING:
554     case LY_TYPE_UNKNOWN:
555         /* just re-assign it */
556         *value_str = value->string;
557         break;
558     case LY_TYPE_BITS:
559         /* print the set bits */
560         str = malloc(1);
561         LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
562         str[0] = '\0';
563         str_len = 0;
564         for (i = 0; i < rtype->info.bits.count; ++i) {
565             if (value->bit[i]) {
566                 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
567                 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
568 
569                 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
570             }
571         }
572 
573         *value_str = lydict_insert_zc(ctx, str);
574         break;
575     case LY_TYPE_BOOL:
576         *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
577         break;
578     case LY_TYPE_EMPTY:
579         *value_str = lydict_insert(ctx, "", 0);
580         break;
581     case LY_TYPE_UNION:
582         if (attr) {
583             /* we do not support union type attribute */
584             LOGINT(ctx);
585             return -1;
586         }
587 
588         if (resolve_union(leaf, type, 1, 2, NULL)) {
589             return -1;
590         }
591         break;
592     case LY_TYPE_ENUM:
593         /* print the value */
594         *value_str = lydict_insert(ctx, value->enm->name, 0);
595         break;
596     case LY_TYPE_INT8:
597         sprintf(num_str, "%d", value->int8);
598         *value_str = lydict_insert(ctx, num_str, 0);
599         break;
600     case LY_TYPE_UINT8:
601         sprintf(num_str, "%u", value->uint8);
602         *value_str = lydict_insert(ctx, num_str, 0);
603         break;
604     case LY_TYPE_INT16:
605         sprintf(num_str, "%d", value->int16);
606         *value_str = lydict_insert(ctx, num_str, 0);
607         break;
608     case LY_TYPE_UINT16:
609         sprintf(num_str, "%u", value->uint16);
610         *value_str = lydict_insert(ctx, num_str, 0);
611         break;
612     case LY_TYPE_INT32:
613         sprintf(num_str, "%d", value->int32);
614         *value_str = lydict_insert(ctx, num_str, 0);
615         break;
616     case LY_TYPE_UINT32:
617         sprintf(num_str, "%u", value->uint32);
618         *value_str = lydict_insert(ctx, num_str, 0);
619         break;
620     case LY_TYPE_INT64:
621         sprintf(num_str, "%"PRId64, value->int64);
622         *value_str = lydict_insert(ctx, num_str, 0);
623         break;
624     case LY_TYPE_UINT64:
625         sprintf(num_str, "%"PRIu64, value->uint64);
626         *value_str = lydict_insert(ctx, num_str, 0);
627         break;
628     case LY_TYPE_DEC64:
629         num = value->dec64 / (int64_t)rtype->info.dec64.div;
630         frac = value->dec64 % (int64_t)rtype->info.dec64.div;
631         dig = rtype->info.dec64.dig;
632 
633         /* frac should always be positive, remove trailing zeros */
634         if (frac < 0) {
635             frac *= -1;
636         }
637         while ((dig > 1) && !(frac % 10)) {
638             frac /= 10;
639             --dig;
640         }
641 
642         /* handle special case of int64_t not supporting printing -0 */
643         sprintf(num_str, "%s%"PRId64".%.*"PRId64, (num == 0) && (value->dec64 < 0) ? "-" : "", num, dig, frac);
644         *value_str = lydict_insert(ctx, num_str, 0);
645         break;
646     default:
647         return -1;
648     }
649 
650     if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
651             || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
652 parse_reference:
653         assert(*value_str);
654 
655         if (attr) {
656             /* we do not support reference types of attributes */
657             LOGINT(ctx);
658             return -1;
659         }
660 
661         if (type->base == LY_TYPE_INST) {
662             if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
663                 return -1;
664             }
665         } else if (type->base == LY_TYPE_LEAFREF) {
666             if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
667                 return -1;
668             }
669         } else {
670             if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
671                 return -1;
672             }
673         }
674     }
675 
676     return 0;
677 }
678 
679 static int
lyb_parse_value(struct lys_type * type,struct lyd_node_leaf_list * leaf,struct lyd_attr * attr,const char * data,struct unres_data * unres,struct lyb_state * lybs)680 lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
681                 struct unres_data *unres, struct lyb_state *lybs)
682 {
683     int r, ret = 0;
684     uint8_t start_byte;
685 
686     const char **value_str;
687     lyd_val *value;
688     LY_DATA_TYPE *value_type;
689     uint8_t *value_flags;
690 
691     assert((leaf || attr) && (!leaf || !attr));
692 
693     if (leaf) {
694         value_str = &leaf->value_str;
695         value = &leaf->value;
696         value_type = &leaf->value_type;
697         value_flags = &leaf->value_flags;
698     } else {
699         value_str = &attr->value_str;
700         value = &attr->value;
701         value_type = &attr->value_type;
702         value_flags = &attr->value_flags;
703     }
704 
705     /* read value type and flags on the first byte */
706     ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
707     LYB_HAVE_READ_RETURN(r, data, -1);
708 
709     /* fill value type, flags */
710     *value_type = start_byte & 0x1F;
711     if (start_byte & 0x80) {
712         assert(leaf);
713         leaf->dflt = 1;
714     }
715     if (start_byte & 0x40) {
716         *value_flags |= LY_VALUE_USER;
717     }
718     if (start_byte & 0x20) {
719         *value_flags |= LY_VALUE_UNRES;
720     }
721 
722     ret += (r = lyb_parse_val_1(type, *value_type, *value_flags, data, value_str, value, lybs));
723     LYB_HAVE_READ_RETURN(r, data, -1);
724 
725     /* union is handled specially */
726     if ((type->base == LY_TYPE_UNION) && !(*value_flags & LY_VALUE_USER)) {
727         assert(*value_type == LY_TYPE_STRING);
728 
729         *value_str = value->string;
730         value->string = NULL;
731         *value_type = LY_TYPE_UNION;
732     }
733 
734     ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
735     LYB_HAVE_READ_RETURN(r, data, -1);
736 
737     return ret;
738 }
739 
740 static int
lyb_parse_attr_name(const struct lys_module * mod,const char * data,struct lys_ext_instance_complex ** ext,int options,struct lyb_state * lybs)741 lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
742                     struct lyb_state *lybs)
743 {
744     int r, ret = 0, pos, i, j, k;
745     const struct lys_submodule *submod = NULL;
746     char *attr_name = NULL;
747 
748     /* attr name */
749     ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
750     LYB_HAVE_READ_RETURN(r, data, -1);
751 
752     /* search module */
753     pos = -1;
754     for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
755         j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
756         if (j == -1) {
757             break;
758         }
759         if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
760             pos = i + j;
761             break;
762         }
763     }
764 
765     /* try submodules */
766     if (pos == -1) {
767         for (k = 0; k < mod->inc_size; ++k) {
768             submod = mod->inc[k].submodule;
769             for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
770                 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
771                 if (j == -1) {
772                     break;
773                 }
774                 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
775                     pos = i + j;
776                     break;
777                 }
778             }
779         }
780     }
781 
782     if (pos == -1) {
783         *ext = NULL;
784     } else {
785         *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
786     }
787 
788     if (!*ext && (options & LYD_OPT_STRICT)) {
789         LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
790         free(attr_name);
791         return -1;
792     }
793 
794     free(attr_name);
795     return ret;
796 }
797 
798 static int
lyb_parse_attributes(struct lyd_node * node,const char * data,int options,struct unres_data * unres,struct lyb_state * lybs)799 lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
800 {
801     int r, ret = 0;
802     uint8_t i, count = 0;
803     const struct lys_module *mod;
804     struct lys_type **type;
805     struct lyd_attr *attr = NULL;
806     struct lys_ext_instance_complex *ext;
807 
808     /* read number of attributes stored */
809     ret += (r = lyb_read(data, &count, 1, lybs));
810     LYB_HAVE_READ_GOTO(r, data, error);
811 
812     /* read attributes */
813     for (i = 0; i < count; ++i) {
814         ret += (r = lyb_read_start_subtree(data, lybs));
815         LYB_HAVE_READ_GOTO(r, data, error);
816 
817         /* find model */
818         ret += (r = lyb_parse_model(data, &mod, options, lybs));
819         LYB_HAVE_READ_GOTO(r, data, error);
820 
821         if (mod) {
822             /* annotation name */
823             ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
824             LYB_HAVE_READ_GOTO(r, data, error);
825         }
826 
827         if (!mod || !ext) {
828             /* unknown attribute, skip it */
829             do {
830                 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
831                 LYB_HAVE_READ_GOTO(r, data, error);
832             } while (lybs->written[lybs->used - 1]);
833             goto stop_subtree;
834         }
835 
836         /* allocate new attribute */
837         if (!attr) {
838             assert(!node->attr);
839 
840             attr = calloc(1, sizeof *attr);
841             LY_CHECK_ERR_GOTO(!attr, LOGMEM(lybs->ctx), error);
842 
843             node->attr = attr;
844         } else {
845             attr->next = calloc(1, sizeof *attr);
846             LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(lybs->ctx), error);
847 
848             attr = attr->next;
849         }
850 
851         /* attribute annotation */
852         attr->annotation = ext;
853 
854         /* attribute name */
855         attr->name = lydict_insert(lybs->ctx, attr->annotation->arg_value, 0);
856 
857         /* get the type */
858         type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
859         if (!type || !(*type)) {
860             goto error;
861         }
862 
863         /* attribute value */
864         ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
865         LYB_HAVE_READ_GOTO(r, data, error);
866 
867 stop_subtree:
868         lyb_read_stop_subtree(lybs);
869     }
870 
871     return ret;
872 
873 error:
874     lyd_free_attr(lybs->ctx, node, node->attr, 1);
875     return -1;
876 }
877 
878 static int
lyb_is_schema_hash_match(struct lys_node * sibling,LYB_HASH * hash,uint8_t hash_count)879 lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
880 {
881     LYB_HASH sibling_hash;
882     uint8_t i;
883 
884     /* compare all the hashes starting from collision ID 0 */
885     for (i = 0; i < hash_count; ++i) {
886         sibling_hash = lyb_hash(sibling, i);
887         if (sibling_hash != hash[i]) {
888             return 0;
889         }
890     }
891 
892     return 1;
893 }
894 
895 static int
lyb_parse_schema_hash(const struct lys_node * sparent,const struct lys_module * mod,const char * data,const char * yang_data_name,int options,struct lys_node ** snode,struct lyb_state * lybs)896 lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
897                       int options, struct lys_node **snode, struct lyb_state *lybs)
898 {
899     int r, ret = 0;
900     uint8_t i, j;
901     struct lys_node *sibling;
902     LYB_HASH hash[LYB_HASH_BITS - 1];
903 
904     assert((sparent || mod) && (!sparent || !mod));
905 
906     /* read the first hash */
907     ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
908     LYB_HAVE_READ_RETURN(r, data, -1);
909 
910     /* based on the first hash read all the other ones, if any */
911     for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
912         if (i > LYB_HASH_BITS) {
913             return -1;
914         }
915     }
916 
917     /* move the first hash on its accurate position */
918     hash[i] = hash[0];
919 
920     /* read the rest of hashes */
921     for (j = i; j; --j) {
922         ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
923         LYB_HAVE_READ_RETURN(r, data, -1);
924 
925         /* correct collision ID */
926         assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
927         /* preceded with zeros */
928         assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
929     }
930 
931     /* handle yang data templates */
932     if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
933         sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
934         if (!sparent) {
935             sibling = NULL;
936             goto finish;
937         }
938     }
939 
940     /* handle RPC/action input/output */
941     if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
942         sibling = NULL;
943         while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
944             if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
945                 break;
946             }
947             if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
948                 break;
949             }
950         }
951         if (!sibling) {
952             /* fail */
953             goto finish;
954         }
955 
956         /* use only input/output children nodes */
957         sparent = sibling;
958     }
959 
960     /* find our node with matching hashes */
961     sibling = NULL;
962     while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
963         /* skip schema nodes from models not present during printing */
964         if (lyb_has_schema_model(sibling, lybs->models, lybs->mod_count) && lyb_is_schema_hash_match(sibling, hash, i + 1)) {
965             /* match found */
966             break;
967         }
968     }
969 
970 finish:
971     *snode = sibling;
972     if (!sibling && (options & LYD_OPT_STRICT)) {
973         if (mod) {
974             LOGVAL(lybs->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".",
975                     mod->name);
976         } else {
977             LOGVAL(lybs->ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".",
978                     sparent->name);
979         }
980         return -1;
981     }
982 
983     return ret;
984 }
985 
986 static int
lyb_skip_subtree(const char * data,struct lyb_state * lybs)987 lyb_skip_subtree(const char *data, struct lyb_state *lybs)
988 {
989     int r, ret = 0;
990 
991     do {
992         /* first skip any meta information inside */
993         r = lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES;
994         data += r;
995         ret += r;
996 
997         /* then read data */
998         ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
999         LYB_HAVE_READ_RETURN(r, data, -1);
1000     } while (lybs->written[lybs->used - 1]);
1001 
1002     return ret;
1003 }
1004 
1005 static int
lyb_parse_subtree(const char * data,struct lyd_node * parent,struct lyd_node ** first_sibling,const char * yang_data_name,int options,struct unres_data * unres,struct lyb_state * lybs)1006 lyb_parse_subtree(const char *data, struct lyd_node *parent, struct lyd_node **first_sibling, const char *yang_data_name,
1007         int options, struct unres_data *unres, struct lyb_state *lybs)
1008 {
1009     int r, ret = 0;
1010     struct lyd_node *node = NULL, *iter;
1011     const struct lys_module *mod;
1012     struct lys_node *snode;
1013 
1014     assert((parent && !first_sibling) || (!parent && first_sibling));
1015 
1016     /* register a new subtree */
1017     ret += (r = lyb_read_start_subtree(data, lybs));
1018     LYB_HAVE_READ_GOTO(r, data, error);
1019 
1020     if (!parent) {
1021         /* top-level, read module name */
1022         ret += (r = lyb_parse_model(data, &mod, options, lybs));
1023         LYB_HAVE_READ_GOTO(r, data, error);
1024 
1025         if (mod) {
1026             /* read hash, find the schema node starting from mod, possibly yang_data_name */
1027             r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
1028         }
1029     } else {
1030         mod = lyd_node_module(parent);
1031 
1032         /* read hash, find the schema node starting from parent schema */
1033         r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
1034     }
1035     ret += r;
1036     LYB_HAVE_READ_GOTO(r, data, error);
1037 
1038     if (!mod || !snode) {
1039         /* unknown data subtree, skip it whole */
1040         ret += (r = lyb_skip_subtree(data, lybs));
1041         LYB_HAVE_READ_GOTO(r, data, error);
1042         goto stop_subtree;
1043     }
1044 
1045     /*
1046      * read the node
1047      */
1048     node = lyb_new_node(snode, options);
1049     if (!node) {
1050         goto error;
1051     }
1052 
1053     ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
1054     LYB_HAVE_READ_GOTO(r, data, error);
1055 
1056     /* read node content */
1057     switch (snode->nodetype) {
1058     case LYS_CONTAINER:
1059     case LYS_LIST:
1060     case LYS_NOTIF:
1061     case LYS_RPC:
1062     case LYS_ACTION:
1063         /* nothing to read */
1064         break;
1065     case LYS_LEAF:
1066     case LYS_LEAFLIST:
1067         ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1068                                     NULL, data, unres, lybs));
1069         LYB_HAVE_READ_GOTO(r, data, error);
1070         break;
1071     case LYS_ANYXML:
1072     case LYS_ANYDATA:
1073         ret += (r = lyb_parse_anydata(node, data, lybs));
1074         LYB_HAVE_READ_GOTO(r, data, error);
1075         break;
1076     default:
1077         goto error;
1078     }
1079 
1080     /* insert into data tree, manually */
1081     if (parent) {
1082         if (!parent->child) {
1083             /* only child */
1084             parent->child = node;
1085         } else {
1086             /* last child */
1087             parent->child->prev->next = node;
1088             node->prev = parent->child->prev;
1089             parent->child->prev = node;
1090         }
1091         node->parent = parent;
1092     } else if (*first_sibling) {
1093         /* last sibling */
1094         (*first_sibling)->prev->next = node;
1095         node->prev = (*first_sibling)->prev;
1096         (*first_sibling)->prev = node;
1097     } else {
1098         /* only sibling */
1099         *first_sibling = node;
1100     }
1101 
1102     /* read all descendants */
1103     while (lybs->written[lybs->used - 1]) {
1104         ret += (r = lyb_parse_subtree(data, node, NULL, NULL, options, unres, lybs));
1105         LYB_HAVE_READ_GOTO(r, data, error);
1106     }
1107 
1108     /* make containers default if should be */
1109     if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
1110         LY_TREE_FOR(node->child, iter) {
1111             if (!iter->dflt) {
1112                 break;
1113             }
1114         }
1115 
1116         if (!iter) {
1117             node->dflt = 1;
1118         }
1119     }
1120 
1121 #ifdef LY_ENABLED_CACHE
1122     /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1123     if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
1124         lyd_hash(node);
1125         lyd_insert_hash(node);
1126     }
1127 #endif
1128 
1129 stop_subtree:
1130     /* end the subtree */
1131     lyb_read_stop_subtree(lybs);
1132 
1133     return ret;
1134 
1135 error:
1136     lyd_free(node);
1137     if (first_sibling && (*first_sibling == node)) {
1138         *first_sibling = NULL;
1139     }
1140     return -1;
1141 }
1142 
1143 static int
lyb_parse_data_models(const char * data,int options,struct lyb_state * lybs)1144 lyb_parse_data_models(const char *data, int options, struct lyb_state *lybs)
1145 {
1146     int i, r, ret = 0;
1147 
1148     /* read model count */
1149     ret += (r = lyb_read_number(&lybs->mod_count, sizeof lybs->mod_count, 2, data, lybs));
1150     LYB_HAVE_READ_RETURN(r, data, -1);
1151 
1152     if (lybs->mod_count) {
1153         lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1154         LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(lybs->ctx), -1);
1155 
1156         /* read modules */
1157         for (i = 0; i < lybs->mod_count; ++i) {
1158             ret += (r = lyb_parse_model(data, &lybs->models[i], options, lybs));
1159             LYB_HAVE_READ_RETURN(r, data, -1);
1160         }
1161     }
1162 
1163     return ret;
1164 }
1165 
1166 static int
lyb_parse_magic_number(const char * data,struct lyb_state * lybs)1167 lyb_parse_magic_number(const char *data, struct lyb_state *lybs)
1168 {
1169     int r, ret = 0;
1170     char magic_byte = 0;
1171 
1172     ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1173     LYB_HAVE_READ_RETURN(r, data, -1);
1174     if (magic_byte != 'l') {
1175         LOGERR(lybs->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1176         return -1;
1177     }
1178 
1179     ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1180     LYB_HAVE_READ_RETURN(r, data, -1);
1181     if (magic_byte != 'y') {
1182         LOGERR(lybs->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1183         return -1;
1184     }
1185 
1186     ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1187     LYB_HAVE_READ_RETURN(r, data, -1);
1188     if (magic_byte != 'b') {
1189         LOGERR(lybs->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1190         return -1;
1191     }
1192 
1193     return ret;
1194 }
1195 
1196 static int
lyb_parse_header(const char * data,struct lyb_state * lybs)1197 lyb_parse_header(const char *data, struct lyb_state *lybs)
1198 {
1199     int ret = 0;
1200     uint8_t byte = 0;
1201 
1202     /* TODO version, any flags? */
1203     ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1204 
1205     return ret;
1206 }
1207 
1208 struct lyd_node *
lyd_parse_lyb(struct ly_ctx * ctx,const char * data,int options,const struct lyd_node * data_tree,const char * yang_data_name,int * parsed)1209 lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1210               const char *yang_data_name, int *parsed)
1211 {
1212     int r = 0, ret = 0;
1213     struct lyd_node *node = NULL, *next, *act_notif = NULL;
1214     struct unres_data *unres = NULL;
1215     struct lyb_state lybs;
1216 
1217     if (!ctx || !data) {
1218         LOGARG;
1219         return NULL;
1220     }
1221 
1222     lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1223     lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
1224     lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1225     LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
1226     lybs.used = 0;
1227     lybs.size = LYB_STATE_STEP;
1228     lybs.models = NULL;
1229     lybs.mod_count = 0;
1230     lybs.ctx = ctx;
1231 
1232     unres = calloc(1, sizeof *unres);
1233     LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
1234 
1235     /* read magic number */
1236     ret += (r = lyb_parse_magic_number(data, &lybs));
1237     LYB_HAVE_READ_GOTO(r, data, finish);
1238 
1239     /* read header */
1240     ret += (r = lyb_parse_header(data, &lybs));
1241     LYB_HAVE_READ_GOTO(r, data, finish);
1242 
1243     /* read used models */
1244     ret += (r = lyb_parse_data_models(data, options, &lybs));
1245     LYB_HAVE_READ_GOTO(r, data, finish);
1246 
1247     /* read subtree(s) */
1248     while (data[0]) {
1249         ret += (r = lyb_parse_subtree(data, NULL, &node, yang_data_name, options, unres, &lybs));
1250         if (r < 0) {
1251             lyd_free_withsiblings(node);
1252             node = NULL;
1253             goto finish;
1254         }
1255         data += r;
1256     }
1257 
1258     /* read the last zero, parsing finished */
1259     ++ret;
1260     r = ret;
1261 
1262     if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1263         if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1264             LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1265             lyd_free_withsiblings(node);
1266             node = NULL;
1267             goto finish;
1268         }
1269     }
1270 
1271     /* resolve any unresolved instance-identifiers */
1272     if (unres->count) {
1273         if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1274             LY_TREE_DFS_BEGIN(node, next, act_notif) {
1275                 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1276                     break;
1277                 }
1278                 LY_TREE_DFS_END(node, next, act_notif);
1279             }
1280         }
1281         if (lyd_defaults_add_unres(&node, options, ctx, NULL, 0, data_tree, act_notif, unres, 0)) {
1282             lyd_free_withsiblings(node);
1283             node = NULL;
1284             goto finish;
1285         }
1286     }
1287 
1288 finish:
1289     free(lybs.written);
1290     free(lybs.position);
1291     free(lybs.inner_chunks);
1292     free(lybs.models);
1293     if (unres) {
1294         free(unres->node);
1295         free(unres->type);
1296         free(unres);
1297     }
1298 
1299     if (parsed) {
1300         *parsed = r;
1301     }
1302     return node;
1303 }
1304 
1305 API int
lyd_lyb_data_length(const char * data)1306 lyd_lyb_data_length(const char *data)
1307 {
1308     FUN_IN;
1309 
1310     struct lyb_state lybs;
1311     int r = 0, ret = 0, i;
1312     size_t len;
1313     uint8_t buf[LYB_SIZE_MAX];
1314 
1315     if (!data) {
1316         return -1;
1317     }
1318 
1319     lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1320     lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
1321     lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1322     LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(NULL), finish);
1323     lybs.used = 0;
1324     lybs.size = LYB_STATE_STEP;
1325     lybs.models = NULL;
1326     lybs.mod_count = 0;
1327     lybs.ctx = NULL;
1328 
1329     /* read magic number */
1330     ret += (r = lyb_parse_magic_number(data, &lybs));
1331     LYB_HAVE_READ_GOTO(r, data, finish);
1332 
1333     /* read header */
1334     ret += (r = lyb_parse_header(data, &lybs));
1335     LYB_HAVE_READ_GOTO(r, data, finish);
1336 
1337     /* read model count */
1338     ret += (r = lyb_read_number(&lybs.mod_count, sizeof lybs.mod_count, 2, data, &lybs));
1339     LYB_HAVE_READ_GOTO(r, data, finish);
1340 
1341     /* read all models */
1342     for (i = 0; i < lybs.mod_count; ++i) {
1343         /* module name length */
1344         len = 0;
1345         ret += (r = lyb_read_number(&len, sizeof len, 2, data, &lybs));
1346         LYB_HAVE_READ_GOTO(r, data, finish);
1347 
1348         /* model name */
1349         ret += (r = lyb_read(data, buf, len, &lybs));
1350         LYB_HAVE_READ_GOTO(r, data, finish);
1351 
1352         /* revision */
1353         ret += (r = lyb_read(data, buf, 2, &lybs));
1354         LYB_HAVE_READ_GOTO(r, data, finish);
1355     }
1356 
1357     while (data[0]) {
1358         /* register a new subtree */
1359         ret += (r = lyb_read_start_subtree(data, &lybs));
1360         LYB_HAVE_READ_GOTO(r, data, finish);
1361 
1362         /* skip it */
1363         ret += (r = lyb_skip_subtree(data, &lybs));
1364         LYB_HAVE_READ_GOTO(r, data, finish);
1365 
1366         /* subtree finished */
1367         lyb_read_stop_subtree(&lybs);
1368     }
1369 
1370     /* read the last zero, parsing finished */
1371     ++ret;
1372 
1373 finish:
1374     free(lybs.written);
1375     free(lybs.position);
1376     free(lybs.inner_chunks);
1377     free(lybs.models);
1378     return ret;
1379 }
1380