1 /**
2  * @file parser.c
3  * @author Radek Krejci <rkrejci@cesnet.cz>
4  * @brief common libyang parsers routines implementations
5  *
6  * Copyright (c) 2015-2017 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 <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/mman.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <pcre.h>
29 #include <time.h>
30 
31 #include "common.h"
32 #include "context.h"
33 #include "libyang.h"
34 #include "parser.h"
35 #include "resolve.h"
36 #include "tree_internal.h"
37 #include "parser_yang.h"
38 #include "xpath.h"
39 
40 #define LYP_URANGE_LEN 19
41 
42 static char *lyp_ublock2urange[][2] = {
43     {"BasicLatin", "[\\x{0000}-\\x{007F}]"},
44     {"Latin-1Supplement", "[\\x{0080}-\\x{00FF}]"},
45     {"LatinExtended-A", "[\\x{0100}-\\x{017F}]"},
46     {"LatinExtended-B", "[\\x{0180}-\\x{024F}]"},
47     {"IPAExtensions", "[\\x{0250}-\\x{02AF}]"},
48     {"SpacingModifierLetters", "[\\x{02B0}-\\x{02FF}]"},
49     {"CombiningDiacriticalMarks", "[\\x{0300}-\\x{036F}]"},
50     {"Greek", "[\\x{0370}-\\x{03FF}]"},
51     {"Cyrillic", "[\\x{0400}-\\x{04FF}]"},
52     {"Armenian", "[\\x{0530}-\\x{058F}]"},
53     {"Hebrew", "[\\x{0590}-\\x{05FF}]"},
54     {"Arabic", "[\\x{0600}-\\x{06FF}]"},
55     {"Syriac", "[\\x{0700}-\\x{074F}]"},
56     {"Thaana", "[\\x{0780}-\\x{07BF}]"},
57     {"Devanagari", "[\\x{0900}-\\x{097F}]"},
58     {"Bengali", "[\\x{0980}-\\x{09FF}]"},
59     {"Gurmukhi", "[\\x{0A00}-\\x{0A7F}]"},
60     {"Gujarati", "[\\x{0A80}-\\x{0AFF}]"},
61     {"Oriya", "[\\x{0B00}-\\x{0B7F}]"},
62     {"Tamil", "[\\x{0B80}-\\x{0BFF}]"},
63     {"Telugu", "[\\x{0C00}-\\x{0C7F}]"},
64     {"Kannada", "[\\x{0C80}-\\x{0CFF}]"},
65     {"Malayalam", "[\\x{0D00}-\\x{0D7F}]"},
66     {"Sinhala", "[\\x{0D80}-\\x{0DFF}]"},
67     {"Thai", "[\\x{0E00}-\\x{0E7F}]"},
68     {"Lao", "[\\x{0E80}-\\x{0EFF}]"},
69     {"Tibetan", "[\\x{0F00}-\\x{0FFF}]"},
70     {"Myanmar", "[\\x{1000}-\\x{109F}]"},
71     {"Georgian", "[\\x{10A0}-\\x{10FF}]"},
72     {"HangulJamo", "[\\x{1100}-\\x{11FF}]"},
73     {"Ethiopic", "[\\x{1200}-\\x{137F}]"},
74     {"Cherokee", "[\\x{13A0}-\\x{13FF}]"},
75     {"UnifiedCanadianAboriginalSyllabics", "[\\x{1400}-\\x{167F}]"},
76     {"Ogham", "[\\x{1680}-\\x{169F}]"},
77     {"Runic", "[\\x{16A0}-\\x{16FF}]"},
78     {"Khmer", "[\\x{1780}-\\x{17FF}]"},
79     {"Mongolian", "[\\x{1800}-\\x{18AF}]"},
80     {"LatinExtendedAdditional", "[\\x{1E00}-\\x{1EFF}]"},
81     {"GreekExtended", "[\\x{1F00}-\\x{1FFF}]"},
82     {"GeneralPunctuation", "[\\x{2000}-\\x{206F}]"},
83     {"SuperscriptsandSubscripts", "[\\x{2070}-\\x{209F}]"},
84     {"CurrencySymbols", "[\\x{20A0}-\\x{20CF}]"},
85     {"CombiningMarksforSymbols", "[\\x{20D0}-\\x{20FF}]"},
86     {"LetterlikeSymbols", "[\\x{2100}-\\x{214F}]"},
87     {"NumberForms", "[\\x{2150}-\\x{218F}]"},
88     {"Arrows", "[\\x{2190}-\\x{21FF}]"},
89     {"MathematicalOperators", "[\\x{2200}-\\x{22FF}]"},
90     {"MiscellaneousTechnical", "[\\x{2300}-\\x{23FF}]"},
91     {"ControlPictures", "[\\x{2400}-\\x{243F}]"},
92     {"OpticalCharacterRecognition", "[\\x{2440}-\\x{245F}]"},
93     {"EnclosedAlphanumerics", "[\\x{2460}-\\x{24FF}]"},
94     {"BoxDrawing", "[\\x{2500}-\\x{257F}]"},
95     {"BlockElements", "[\\x{2580}-\\x{259F}]"},
96     {"GeometricShapes", "[\\x{25A0}-\\x{25FF}]"},
97     {"MiscellaneousSymbols", "[\\x{2600}-\\x{26FF}]"},
98     {"Dingbats", "[\\x{2700}-\\x{27BF}]"},
99     {"BraillePatterns", "[\\x{2800}-\\x{28FF}]"},
100     {"CJKRadicalsSupplement", "[\\x{2E80}-\\x{2EFF}]"},
101     {"KangxiRadicals", "[\\x{2F00}-\\x{2FDF}]"},
102     {"IdeographicDescriptionCharacters", "[\\x{2FF0}-\\x{2FFF}]"},
103     {"CJKSymbolsandPunctuation", "[\\x{3000}-\\x{303F}]"},
104     {"Hiragana", "[\\x{3040}-\\x{309F}]"},
105     {"Katakana", "[\\x{30A0}-\\x{30FF}]"},
106     {"Bopomofo", "[\\x{3100}-\\x{312F}]"},
107     {"HangulCompatibilityJamo", "[\\x{3130}-\\x{318F}]"},
108     {"Kanbun", "[\\x{3190}-\\x{319F}]"},
109     {"BopomofoExtended", "[\\x{31A0}-\\x{31BF}]"},
110     {"EnclosedCJKLettersandMonths", "[\\x{3200}-\\x{32FF}]"},
111     {"CJKCompatibility", "[\\x{3300}-\\x{33FF}]"},
112     {"CJKUnifiedIdeographsExtensionA", "[\\x{3400}-\\x{4DB5}]"},
113     {"CJKUnifiedIdeographs", "[\\x{4E00}-\\x{9FFF}]"},
114     {"YiSyllables", "[\\x{A000}-\\x{A48F}]"},
115     {"YiRadicals", "[\\x{A490}-\\x{A4CF}]"},
116     {"HangulSyllables", "[\\x{AC00}-\\x{D7A3}]"},
117     {"PrivateUse", "[\\x{E000}-\\x{F8FF}]"},
118     {"CJKCompatibilityIdeographs", "[\\x{F900}-\\x{FAFF}]"},
119     {"AlphabeticPresentationForms", "[\\x{FB00}-\\x{FB4F}]"},
120     {"ArabicPresentationForms-A", "[\\x{FB50}-\\x{FDFF}]"},
121     {"CombiningHalfMarks", "[\\x{FE20}-\\x{FE2F}]"},
122     {"CJKCompatibilityForms", "[\\x{FE30}-\\x{FE4F}]"},
123     {"SmallFormVariants", "[\\x{FE50}-\\x{FE6F}]"},
124     {"ArabicPresentationForms-B", "[\\x{FE70}-\\x{FEFE}]"},
125     {"HalfwidthandFullwidthForms", "[\\x{FF00}-\\x{FFEF}]"},
126     {"Specials", "[\\x{FEFF}|\\x{FFF0}-\\x{FFFD}]"},
127     {NULL, NULL}
128 };
129 
130 const char *ly_stmt_str[] = {
131     [LY_STMT_UNKNOWN] = "",
132     [LY_STMT_ARGUMENT] = "argument",
133     [LY_STMT_BASE] = "base",
134     [LY_STMT_BELONGSTO] = "belongs-to",
135     [LY_STMT_CONTACT] = "contact",
136     [LY_STMT_DEFAULT] = "default",
137     [LY_STMT_DESCRIPTION] = "description",
138     [LY_STMT_ERRTAG] = "error-app-tag",
139     [LY_STMT_ERRMSG] = "error-message",
140     [LY_STMT_KEY] = "key",
141     [LY_STMT_NAMESPACE] = "namespace",
142     [LY_STMT_ORGANIZATION] = "organization",
143     [LY_STMT_PATH] = "path",
144     [LY_STMT_PREFIX] = "prefix",
145     [LY_STMT_PRESENCE] = "presence",
146     [LY_STMT_REFERENCE] = "reference",
147     [LY_STMT_REVISIONDATE] = "revision-date",
148     [LY_STMT_UNITS] = "units",
149     [LY_STMT_VALUE] = "value",
150     [LY_STMT_VERSION] = "yang-version",
151     [LY_STMT_MODIFIER] = "modifier",
152     [LY_STMT_REQINSTANCE] = "require-instance",
153     [LY_STMT_YINELEM] = "yin-element",
154     [LY_STMT_CONFIG] = "config",
155     [LY_STMT_MANDATORY] = "mandatory",
156     [LY_STMT_ORDEREDBY] = "ordered-by",
157     [LY_STMT_STATUS] = "status",
158     [LY_STMT_DIGITS] = "fraction-digits",
159     [LY_STMT_MAX] = "max-elements",
160     [LY_STMT_MIN] = "min-elements",
161     [LY_STMT_POSITION] = "position",
162     [LY_STMT_UNIQUE] = "unique",
163     [LY_STMT_MODULE] = "module",
164     [LY_STMT_SUBMODULE] = "submodule",
165     [LY_STMT_ACTION] = "action",
166     [LY_STMT_ANYDATA] = "anydata",
167     [LY_STMT_ANYXML] = "anyxml",
168     [LY_STMT_CASE] = "case",
169     [LY_STMT_CHOICE] = "choice",
170     [LY_STMT_CONTAINER] = "container",
171     [LY_STMT_GROUPING] = "grouping",
172     [LY_STMT_INPUT] = "input",
173     [LY_STMT_LEAF] = "leaf",
174     [LY_STMT_LEAFLIST] = "leaf-list",
175     [LY_STMT_LIST] = "list",
176     [LY_STMT_NOTIFICATION] = "notification",
177     [LY_STMT_OUTPUT] = "output",
178     [LY_STMT_RPC] = "rpc",
179     [LY_STMT_USES] = "uses",
180     [LY_STMT_TYPEDEF] = "typedef",
181     [LY_STMT_TYPE] = "type",
182     [LY_STMT_BIT] = "bit",
183     [LY_STMT_ENUM] = "enum",
184     [LY_STMT_REFINE] = "refine",
185     [LY_STMT_AUGMENT] = "augment",
186     [LY_STMT_DEVIATE] = "deviate",
187     [LY_STMT_DEVIATION] = "deviation",
188     [LY_STMT_EXTENSION] = "extension",
189     [LY_STMT_FEATURE] = "feature",
190     [LY_STMT_IDENTITY] = "identity",
191     [LY_STMT_IFFEATURE] = "if-feature",
192     [LY_STMT_IMPORT] = "import",
193     [LY_STMT_INCLUDE] = "include",
194     [LY_STMT_LENGTH] = "length",
195     [LY_STMT_MUST] = "must",
196     [LY_STMT_PATTERN] = "pattern",
197     [LY_STMT_RANGE] = "range",
198     [LY_STMT_WHEN] = "when",
199     [LY_STMT_REVISION] = "revision"
200 };
201 
202 int
lyp_is_rpc_action(struct lys_node * node)203 lyp_is_rpc_action(struct lys_node *node)
204 {
205     assert(node);
206 
207     while (lys_parent(node)) {
208         node = lys_parent(node);
209         if (node->nodetype == LYS_ACTION) {
210             break;
211         }
212     }
213 
214     if (node->nodetype & (LYS_RPC | LYS_ACTION)) {
215         return 1;
216     } else {
217         return 0;
218     }
219 }
220 
221 int
lyp_data_check_options(struct ly_ctx * ctx,int options,const char * func)222 lyp_data_check_options(struct ly_ctx *ctx, int options, const char *func)
223 {
224     int x = options & LYD_OPT_TYPEMASK;
225 
226     /* LYD_OPT_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG */
227     if (options & LYD_OPT_WHENAUTODEL) {
228         if ((x == LYD_OPT_EDIT) || (x == LYD_OPT_NOTIF_FILTER)) {
229             LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG)",
230                    func, options);
231             return 1;
232         }
233     }
234 
235     if (options & (LYD_OPT_DATA_ADD_YANGLIB | LYD_OPT_DATA_NO_YANGLIB)) {
236         if (x != LYD_OPT_DATA) {
237             LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_*_YANGLIB can be used only with LYD_OPT_DATA)",
238                    func, options);
239             return 1;
240         }
241     }
242 
243     /* "is power of 2" algorithm, with 0 exception */
244     if (x && !(x && !(x & (x - 1)))) {
245         LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (multiple data type flags set).", func, options);
246         return 1;
247     }
248 
249     return 0;
250 }
251 
252 int
lyp_mmap(struct ly_ctx * ctx,int fd,size_t addsize,size_t * length,void ** addr)253 lyp_mmap(struct ly_ctx *ctx, int fd, size_t addsize, size_t *length, void **addr)
254 {
255     struct stat sb;
256     long pagesize;
257     size_t m;
258 
259     assert(fd >= 0);
260     if (fstat(fd, &sb) == -1) {
261         LOGERR(ctx, LY_ESYS, "Failed to stat the file descriptor (%s) for the mmap().", strerror(errno));
262         return 1;
263     }
264     if (!S_ISREG(sb.st_mode)) {
265         LOGERR(ctx, LY_EINVAL, "File to mmap() is not a regular file.");
266         return 1;
267     }
268     if (!sb.st_size) {
269         *addr = NULL;
270         return 0;
271     }
272     pagesize = sysconf(_SC_PAGESIZE);
273     ++addsize;                       /* at least one additional byte for terminating NULL byte */
274 
275     m = sb.st_size % pagesize;
276     if (m && pagesize - m >= addsize) {
277         /* there will be enough space after the file content mapping to provide zeroed additional bytes */
278         *length = sb.st_size + addsize;
279         *addr = mmap(NULL, *length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
280     } else {
281         /* there will not be enough bytes after the file content mapping for the additional bytes and some of them
282          * would overflow into another page that would not be zeroed and any access into it would generate SIGBUS.
283          * Therefore we have to do the following hack with double mapping. First, the required number of bytes
284          * (including the additional bytes) is required as anonymous and thus they will be really provided (actually more
285          * because of using whole pages) and also initialized by zeros. Then, the file is mapped to the same address
286          * where the anonymous mapping starts. */
287         *length = sb.st_size + pagesize;
288         *addr = mmap(NULL, *length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
289         *addr = mmap(*addr, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0);
290     }
291     if (*addr == MAP_FAILED) {
292         LOGERR(ctx, LY_ESYS, "mmap() failed (%s).", strerror(errno));
293         return 1;
294     }
295 
296     return 0;
297 }
298 
299 int
lyp_munmap(void * addr,size_t length)300 lyp_munmap(void *addr, size_t length)
301 {
302     if (!addr) {
303         /* nothing to unmap */
304         return 0;
305     }
306 
307     return munmap(addr, length);
308 }
309 
310 int
lyp_add_ietf_netconf_annotations_config(struct lys_module * mod)311 lyp_add_ietf_netconf_annotations_config(struct lys_module *mod)
312 {
313     void *reallocated;
314     struct lys_ext_instance_complex *op;
315     struct lys_type **type;
316     struct lys_node_anydata *anyxml;
317     int i;
318     struct ly_ctx *ctx = mod->ctx; /* shortcut */
319 
320     reallocated = realloc(mod->ext, (mod->ext_size + 3) * sizeof *mod->ext);
321     LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx), EXIT_FAILURE);
322     mod->ext = reallocated;
323     /* 1) edit-config's operation */
324     op = calloc(1, (sizeof(struct lys_ext_instance_complex) - 1) + 5 * sizeof(void*) + sizeof(uint16_t));
325     LY_CHECK_ERR_RETURN(!op, LOGMEM(ctx), EXIT_FAILURE);
326     mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
327     op->arg_value = lydict_insert(ctx, "operation", 9);
328     op->def = &ctx->models.list[0]->extensions[0];
329     op->ext_type = LYEXT_COMPLEX;
330     op->module = op->parent = mod;
331     op->parent_type = LYEXT_PAR_MODULE;
332     op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
333     op->nodetype = LYS_EXT;
334     type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
335     *type = calloc(1, sizeof(struct lys_type));
336     LY_CHECK_ERR_RETURN(!*type, LOGMEM(ctx), EXIT_FAILURE);
337     (*type)->base = LY_TYPE_ENUM;
338     (*type)->der = ly_types[LY_TYPE_ENUM];
339     (*type)->parent = (struct lys_tpdf *)op;
340     (*type)->info.enums.count = 5;
341     (*type)->info.enums.enm = calloc(5, sizeof *(*type)->info.enums.enm);
342     LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm, LOGMEM(ctx), EXIT_FAILURE);
343     (*type)->info.enums.enm[0].value = 0;
344     (*type)->info.enums.enm[0].name = lydict_insert(ctx, "merge", 5);
345     (*type)->info.enums.enm[1].value = 1;
346     (*type)->info.enums.enm[1].name = lydict_insert(ctx, "replace", 7);
347     (*type)->info.enums.enm[2].value = 2;
348     (*type)->info.enums.enm[2].name = lydict_insert(ctx, "create", 6);
349     (*type)->info.enums.enm[3].value = 3;
350     (*type)->info.enums.enm[3].name = lydict_insert(ctx, "delete", 6);
351     (*type)->info.enums.enm[4].value = 4;
352     (*type)->info.enums.enm[4].name = lydict_insert(ctx, "remove", 6);
353     mod->ext_size++;
354 
355     /* 2) filter's type */
356     op = calloc(1, (sizeof(struct lys_ext_instance_complex) - 1) + 5 * sizeof(void*) + sizeof(uint16_t));
357     LY_CHECK_ERR_RETURN(!op, LOGMEM(ctx), EXIT_FAILURE);
358     mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
359     op->arg_value = lydict_insert(ctx, "type", 4);
360     op->def = &ctx->models.list[0]->extensions[0];
361     op->ext_type = LYEXT_COMPLEX;
362     op->module = op->parent = mod;
363     op->parent_type = LYEXT_PAR_MODULE;
364     op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
365     op->nodetype = LYS_EXT;
366     type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
367     *type = calloc(1, sizeof(struct lys_type));
368     LY_CHECK_ERR_RETURN(!*type, LOGMEM(ctx), EXIT_FAILURE);
369     (*type)->base = LY_TYPE_ENUM;
370     (*type)->der = ly_types[LY_TYPE_ENUM];
371     (*type)->parent = (struct lys_tpdf *)op;
372     (*type)->info.enums.count = 2;
373     (*type)->info.enums.enm = calloc(2, sizeof *(*type)->info.enums.enm);
374     LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm, LOGMEM(ctx), EXIT_FAILURE);
375     (*type)->info.enums.enm[0].value = 0;
376     (*type)->info.enums.enm[0].name = lydict_insert(ctx, "subtree", 7);
377     (*type)->info.enums.enm[1].value = 1;
378     (*type)->info.enums.enm[1].name = lydict_insert(ctx, "xpath", 5);
379     for (i = mod->features_size; i > 0; i--) {
380         if (!strcmp(mod->features[i - 1].name, "xpath")) {
381             (*type)->info.enums.enm[1].iffeature_size = 1;
382             (*type)->info.enums.enm[1].iffeature = calloc(1, sizeof(struct lys_feature));
383             LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm[1].iffeature, LOGMEM(ctx), EXIT_FAILURE);
384             (*type)->info.enums.enm[1].iffeature[0].expr = malloc(sizeof(uint8_t));
385             LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm[1].iffeature[0].expr, LOGMEM(ctx), EXIT_FAILURE);
386             *(*type)->info.enums.enm[1].iffeature[0].expr = 3; /* LYS_IFF_F */
387             (*type)->info.enums.enm[1].iffeature[0].features = malloc(sizeof(struct lys_feature*));
388             LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm[1].iffeature[0].features, LOGMEM(ctx), EXIT_FAILURE);
389             (*type)->info.enums.enm[1].iffeature[0].features[0] = &mod->features[i - 1];
390             break;
391         }
392     }
393     mod->ext_size++;
394 
395     /* 3) filter's select */
396     op = calloc(1, (sizeof(struct lys_ext_instance_complex) - 1) + 5 * sizeof(void*) + sizeof(uint16_t));
397     LY_CHECK_ERR_RETURN(!op, LOGMEM(ctx), EXIT_FAILURE);
398     mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
399     op->arg_value = lydict_insert(ctx, "select", 6);
400     op->def = &ctx->models.list[0]->extensions[0];
401     op->ext_type = LYEXT_COMPLEX;
402     op->module = op->parent = mod;
403     op->parent_type = LYEXT_PAR_MODULE;
404     op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
405     op->nodetype = LYS_EXT;
406     type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
407     *type = calloc(1, sizeof(struct lys_type));
408     LY_CHECK_ERR_RETURN(!*type, LOGMEM(ctx), EXIT_FAILURE);
409     (*type)->base = LY_TYPE_STRING;
410     (*type)->der = ly_types[LY_TYPE_STRING];
411     (*type)->parent = (struct lys_tpdf *)op;
412     mod->ext_size++;
413 
414     /* 4) URL config */
415     anyxml = calloc(1, sizeof *anyxml);
416     LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), EXIT_FAILURE);
417     anyxml->nodetype = LYS_ANYXML;
418     anyxml->prev = (struct lys_node *)anyxml;
419     anyxml->name = lydict_insert(ctx, "config", 0);
420     anyxml->module = mod;
421     anyxml->flags = LYS_CONFIG_W;
422     if (lys_node_addchild(NULL, mod, (struct lys_node *)anyxml, 0)) {
423         return EXIT_FAILURE;
424     }
425 
426     return EXIT_SUCCESS;
427 }
428 
429 /* logs directly
430  * base: 0  - to accept decimal, octal, hexadecimal (in default value)
431  *       10 - to accept only decimal (instance value)
432  */
433 static int
parse_int(const char * val_str,int64_t min,int64_t max,int base,int64_t * ret,struct lyd_node * node)434 parse_int(const char *val_str, int64_t min, int64_t max, int base, int64_t *ret, struct lyd_node *node)
435 {
436     char *strptr;
437 
438     assert(node);
439 
440     if (!val_str || !val_str[0]) {
441         goto error;
442     }
443 
444     /* convert to 64-bit integer, all the redundant characters are handled */
445     errno = 0;
446     strptr = NULL;
447 
448     /* parse the value */
449     *ret = strtoll(val_str, &strptr, base);
450     if (errno || (*ret < min) || (*ret > max)) {
451         goto error;
452     } else if (strptr && *strptr) {
453         while (isspace(*strptr)) {
454             ++strptr;
455         }
456         if (*strptr) {
457             goto error;
458         }
459     }
460 
461     return EXIT_SUCCESS;
462 
463 error:
464     LOGVAL(node->schema->module->ctx, LYE_INVAL, LY_VLOG_LYD, node, val_str ? val_str : "", node->schema->name);
465     return EXIT_FAILURE;
466 }
467 
468 /* logs directly
469  * base: 0  - to accept decimal, octal, hexadecimal (in default value)
470  *       10 - to accept only decimal (instance value)
471  */
472 static int
parse_uint(const char * val_str,uint64_t max,int base,uint64_t * ret,struct lyd_node * node)473 parse_uint(const char *val_str, uint64_t max, int base, uint64_t *ret, struct lyd_node *node)
474 {
475     char *strptr;
476     uint64_t u;
477 
478     assert(node);
479 
480     if (!val_str || !val_str[0]) {
481         goto error;
482     }
483 
484     errno = 0;
485     strptr = NULL;
486     u = strtoull(val_str, &strptr, base);
487     if (errno || (u > max)) {
488         goto error;
489     } else if (strptr && *strptr) {
490         while (isspace(*strptr)) {
491             ++strptr;
492         }
493         if (*strptr) {
494             goto error;
495         }
496     } else if (u != 0 && val_str[0] == '-') {
497         goto error;
498     }
499 
500     *ret = u;
501     return EXIT_SUCCESS;
502 
503 error:
504     LOGVAL(node->schema->module->ctx, LYE_INVAL, LY_VLOG_LYD, node, val_str ? val_str : "", node->schema->name);
505     return EXIT_FAILURE;
506 }
507 
508 /* logs directly
509  *
510  * kind == 0 - unsigned (unum used), 1 - signed (snum used), 2 - floating point (fnum used)
511  */
512 static int
validate_length_range(uint8_t kind,uint64_t unum,int64_t snum,int64_t fnum,uint8_t fnum_dig,struct lys_type * type,const char * val_str,struct lyd_node * node)513 validate_length_range(uint8_t kind, uint64_t unum, int64_t snum, int64_t fnum, uint8_t fnum_dig, struct lys_type *type,
514                       const char *val_str, struct lyd_node *node)
515 {
516     struct lys_restr *restr = NULL;
517     struct len_ran_intv *intv = NULL, *tmp_intv;
518     struct lys_type *cur_type;
519     struct ly_ctx *ctx = type->parent->module->ctx;
520     int match;
521 
522     if (resolve_len_ran_interval(ctx, NULL, type, &intv)) {
523         /* already done during schema parsing */
524         LOGINT(ctx);
525         return EXIT_FAILURE;
526     }
527     if (!intv) {
528         return EXIT_SUCCESS;
529     }
530 
531     /* I know that all intervals belonging to a single restriction share one type pointer */
532     tmp_intv = intv;
533     cur_type = intv->type;
534     do {
535         match = 0;
536         for (; tmp_intv && (tmp_intv->type == cur_type); tmp_intv = tmp_intv->next) {
537             if (match) {
538                 /* just iterate through the rest of this restriction intervals */
539                 continue;
540             }
541 
542             if (((kind == 0) && (unum < tmp_intv->value.uval.min))
543                     || ((kind == 1) && (snum < tmp_intv->value.sval.min))
544                     || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) < 0))) {
545                 break;
546             }
547 
548             if (((kind == 0) && (unum >= tmp_intv->value.uval.min) && (unum <= tmp_intv->value.uval.max))
549                     || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max))
550                     || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) > -1)
551                     && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.max, cur_type->info.dec64.dig) < 1))) {
552                 match = 1;
553             }
554         }
555 
556         if (!match) {
557             break;
558         } else if (tmp_intv) {
559             cur_type = tmp_intv->type;
560         }
561     } while (tmp_intv);
562 
563     while (intv) {
564         tmp_intv = intv->next;
565         free(intv);
566         intv = tmp_intv;
567     }
568 
569     if (!match) {
570         switch (cur_type->base) {
571         case LY_TYPE_BINARY:
572             restr = cur_type->info.binary.length;
573             break;
574         case LY_TYPE_DEC64:
575             restr = cur_type->info.dec64.range;
576             break;
577         case LY_TYPE_INT8:
578         case LY_TYPE_INT16:
579         case LY_TYPE_INT32:
580         case LY_TYPE_INT64:
581         case LY_TYPE_UINT8:
582         case LY_TYPE_UINT16:
583         case LY_TYPE_UINT32:
584         case LY_TYPE_UINT64:
585             restr = cur_type->info.num.range;
586             break;
587         case LY_TYPE_STRING:
588             restr = cur_type->info.str.length;
589             break;
590         default:
591             LOGINT(ctx);
592             return EXIT_FAILURE;
593         }
594 
595         LOGVAL(ctx, LYE_NOCONSTR, LY_VLOG_LYS, node->schema, (val_str ? val_str : ""), restr ? restr->expr : "");
596         if (restr && restr->emsg) {
597             ly_vlog_str(ctx, LY_VLOG_PREV, restr->emsg);
598         }
599         if (restr && restr->eapptag) {
600             ly_err_last_set_apptag(ctx, restr->eapptag);
601         }
602         return EXIT_FAILURE;
603     }
604     return EXIT_SUCCESS;
605 }
606 
607 /* logs directly */
608 static int
validate_pattern(struct ly_ctx * ctx,const char * val_str,struct lys_type * type,struct lyd_node * node)609 validate_pattern(struct ly_ctx *ctx, const char *val_str, struct lys_type *type, struct lyd_node *node)
610 {
611     int rc;
612     unsigned int i;
613 #ifndef LY_ENABLED_CACHE
614     pcre *precomp;
615 #endif
616 
617     assert(ctx && (type->base == LY_TYPE_STRING));
618 
619     if (!val_str) {
620         val_str = "";
621     }
622 
623     if (type->der && validate_pattern(ctx, val_str, &type->der->type, node)) {
624         return EXIT_FAILURE;
625     }
626 
627 #ifdef LY_ENABLED_CACHE
628     /* there is no cache, build it */
629     if (!type->info.str.patterns_pcre && type->info.str.pat_count) {
630         type->info.str.patterns_pcre = malloc(2 * type->info.str.pat_count * sizeof *type->info.str.patterns_pcre);
631         LY_CHECK_ERR_RETURN(!type->info.str.patterns_pcre, LOGMEM(ctx), -1);
632 
633         for (i = 0; i < type->info.str.pat_count; ++i) {
634             if (lyp_precompile_pattern(ctx, &type->info.str.patterns[i].expr[1],
635                                        (pcre**)&type->info.str.patterns_pcre[i * 2],
636                                        (pcre_extra**)&type->info.str.patterns_pcre[i * 2 + 1])) {
637                 return EXIT_FAILURE;
638             }
639         }
640     }
641 #endif
642 
643     for (i = 0; i < type->info.str.pat_count; ++i) {
644 #ifdef LY_ENABLED_CACHE
645         rc = pcre_exec((pcre *)type->info.str.patterns_pcre[2 * i], (pcre_extra *)type->info.str.patterns_pcre[2 * i + 1],
646                        val_str, strlen(val_str), 0, 0, NULL, 0);
647 #else
648         if (lyp_check_pattern(ctx, &type->info.str.patterns[i].expr[1], &precomp)) {
649             return EXIT_FAILURE;
650         }
651         rc = pcre_exec(precomp, NULL, val_str, strlen(val_str), 0, 0, NULL, 0);
652         free(precomp);
653 #endif
654         if ((rc && type->info.str.patterns[i].expr[0] == 0x06) || (!rc && type->info.str.patterns[i].expr[0] == 0x15)) {
655             LOGVAL(ctx, LYE_NOCONSTR, LY_VLOG_LYD, node, val_str, &type->info.str.patterns[i].expr[1]);
656             if (type->info.str.patterns[i].emsg) {
657                 ly_vlog_str(ctx, LY_VLOG_PREV, type->info.str.patterns[i].emsg);
658             }
659             if (type->info.str.patterns[i].eapptag) {
660                 ly_err_last_set_apptag(ctx, type->info.str.patterns[i].eapptag);
661             }
662             return EXIT_FAILURE;
663         }
664     }
665 
666     return EXIT_SUCCESS;
667 }
668 
669 static void
check_number(const char * str_num,const char ** num_end,LY_DATA_TYPE base)670 check_number(const char *str_num, const char **num_end, LY_DATA_TYPE base)
671 {
672     if (!isdigit(str_num[0]) && (str_num[0] != '-') && (str_num[0] != '+')) {
673         *num_end = str_num;
674         return;
675     }
676 
677     if ((str_num[0] == '-') || (str_num[0] == '+')) {
678         ++str_num;
679     }
680 
681     while (isdigit(str_num[0])) {
682         ++str_num;
683     }
684 
685     if ((base != LY_TYPE_DEC64) || (str_num[0] != '.') || !isdigit(str_num[1])) {
686         *num_end = str_num;
687         return;
688     }
689 
690     ++str_num;
691     while (isdigit(str_num[0])) {
692         ++str_num;
693     }
694 
695     *num_end = str_num;
696 }
697 
698 /**
699  * @brief Checks the syntax of length or range statement,
700  *        on success checks the semantics as well. Does not log.
701  *
702  * @param[in] expr Length or range expression.
703  * @param[in] type Type with the restriction.
704  *
705  * @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise.
706  */
707 int
lyp_check_length_range(struct ly_ctx * ctx,const char * expr,struct lys_type * type)708 lyp_check_length_range(struct ly_ctx *ctx, const char *expr, struct lys_type *type)
709 {
710     struct len_ran_intv *intv = NULL, *tmp_intv;
711     const char *c = expr, *tail;
712     int ret = EXIT_FAILURE, flg = 1; /* first run flag */
713 
714     assert(expr);
715 
716 lengthpart:
717 
718     while (isspace(*c)) {
719         c++;
720     }
721 
722     /* lower boundary or explicit number */
723     if (!strncmp(c, "max", 3)) {
724 max:
725         c += 3;
726         while (isspace(*c)) {
727             c++;
728         }
729         if (*c != '\0') {
730             goto error;
731         }
732 
733         goto syntax_ok;
734 
735     } else if (!strncmp(c, "min", 3)) {
736         if (!flg) {
737             /* min cannot be used elsewhere than in the first length-part */
738             goto error;
739         } else {
740             flg = 0;
741         }
742         c += 3;
743         while (isspace(*c)) {
744             c++;
745         }
746 
747         if (*c == '|') {
748             c++;
749             /* process next length-part */
750             goto lengthpart;
751         } else if (*c == '\0') {
752             goto syntax_ok;
753         } else if (!strncmp(c, "..", 2)) {
754 upper:
755             c += 2;
756             while (isspace(*c)) {
757                 c++;
758             }
759             if (*c == '\0') {
760                 goto error;
761             }
762 
763             /* upper boundary */
764             if (!strncmp(c, "max", 3)) {
765                 goto max;
766             }
767 
768             check_number(c, &tail, type->base);
769             if (c == tail) {
770                 goto error;
771             }
772             c = tail;
773             while (isspace(*c)) {
774                 c++;
775             }
776             if (*c == '\0') {
777                 goto syntax_ok;
778             } else if (*c == '|') {
779                 c++;
780                 /* process next length-part */
781                 goto lengthpart;
782             } else {
783                 goto error;
784             }
785         } else {
786             goto error;
787         }
788 
789     } else if (isdigit(*c) || (*c == '-') || (*c == '+')) {
790         /* number */
791         check_number(c, &tail, type->base);
792         if (c == tail) {
793             goto error;
794         }
795         c = tail;
796 
797         while (isspace(*c)) {
798             c++;
799         }
800 
801         if (*c == '|') {
802             c++;
803             /* process next length-part */
804             goto lengthpart;
805         } else if (*c == '\0') {
806             goto syntax_ok;
807         } else if (!strncmp(c, "..", 2)) {
808             goto upper;
809         }
810 
811     } else {
812         goto error;
813     }
814 
815 syntax_ok:
816     if (resolve_len_ran_interval(ctx, expr, type, &intv)) {
817         goto error;
818     }
819 
820     ret = EXIT_SUCCESS;
821 
822 error:
823     while (intv) {
824         tmp_intv = intv->next;
825         free(intv);
826         intv = tmp_intv;
827     }
828 
829     return ret;
830 }
831 
832 /**
833  * @brief Checks pattern syntax. Logs directly.
834  *
835  * @param[in] pattern Pattern to check.
836  * @param[out] pcre_precomp Precompiled PCRE pattern. Can be NULL.
837  * @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise.
838  */
839 int
lyp_check_pattern(struct ly_ctx * ctx,const char * pattern,pcre ** pcre_precomp)840 lyp_check_pattern(struct ly_ctx *ctx, const char *pattern, pcre **pcre_precomp)
841 {
842     int idx, idx2, start, end, err_offset, count, end_anchor = 0;
843     char *perl_regex, *ptr;
844     const char *err_msg, *orig_ptr;
845     pcre *precomp;
846 
847     /*
848      * adjust the expression to a Perl equivalent
849      *
850      * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs
851      */
852 
853     /* we need to replace all "$" with "\$", count them now */
854     for (count = 0, ptr = strchr(pattern, '$'); ptr; ++count, ptr = strchr(ptr + 1, '$'));
855 
856     perl_regex = malloc((strlen(pattern) + 4 + count) * sizeof(char));
857     LY_CHECK_ERR_RETURN(!perl_regex, LOGMEM(ctx), EXIT_FAILURE);
858     perl_regex[0] = '\0';
859 
860     ptr = perl_regex;
861 
862     if ((strlen(pattern) > 1) && strncmp(pattern + strlen(pattern) - 2, ".*", 2)) {
863         /* we wil add line-end anchoring */
864         end_anchor = 1;
865 
866         ptr[0] = '(';
867         ++ptr;
868     }
869 
870     for (orig_ptr = pattern; orig_ptr[0]; ++orig_ptr) {
871         if (orig_ptr[0] == '$') {
872             ptr += sprintf(ptr, "\\$");
873         } else {
874             ptr[0] = orig_ptr[0];
875             ++ptr;
876         }
877     }
878 
879     if (end_anchor) {
880         ptr += sprintf(ptr, ")$");
881     } else {
882         ptr[0] = '\0';
883         ++ptr;
884     }
885 
886     /* substitute Unicode Character Blocks with exact Character Ranges */
887     while ((ptr = strstr(perl_regex, "\\p{Is"))) {
888         start = ptr - perl_regex;
889 
890         ptr = strchr(ptr, '}');
891         if (!ptr) {
892             LOGVAL(ctx, LYE_INREGEX, LY_VLOG_NONE, NULL, pattern, perl_regex + start + 2, "unterminated character property");
893             free(perl_regex);
894             return EXIT_FAILURE;
895         }
896 
897         end = (ptr - perl_regex) + 1;
898 
899         /* need more space */
900         if (end - start < LYP_URANGE_LEN) {
901             perl_regex = ly_realloc(perl_regex, strlen(perl_regex) + (LYP_URANGE_LEN - (end - start)) + 1);
902             LY_CHECK_ERR_RETURN(!perl_regex, LOGMEM(ctx); free(perl_regex), EXIT_FAILURE);
903         }
904 
905         /* find our range */
906         for (idx = 0; lyp_ublock2urange[idx][0]; ++idx) {
907             if (!strncmp(perl_regex + start + 5, lyp_ublock2urange[idx][0], strlen(lyp_ublock2urange[idx][0]))) {
908                 break;
909             }
910         }
911         if (!lyp_ublock2urange[idx][0]) {
912             LOGVAL(ctx, LYE_INREGEX, LY_VLOG_NONE, NULL, pattern, perl_regex + start + 5, "unknown block name");
913             free(perl_regex);
914             return EXIT_FAILURE;
915         }
916 
917         /* make the space in the string and replace the block (but we cannot include brackets if it was already enclosed in them) */
918         for (idx2 = 0, count = 0; idx2 < start; ++idx2) {
919             if ((perl_regex[idx2] == '[') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
920                 ++count;
921             }
922             if ((perl_regex[idx2] == ']') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
923                 --count;
924             }
925         }
926         if (count) {
927             /* skip brackets */
928             memmove(perl_regex + start + (LYP_URANGE_LEN - 2), perl_regex + end, strlen(perl_regex + end) + 1);
929             memcpy(perl_regex + start, lyp_ublock2urange[idx][1] + 1, LYP_URANGE_LEN - 2);
930         } else {
931             memmove(perl_regex + start + LYP_URANGE_LEN, perl_regex + end, strlen(perl_regex + end) + 1);
932             memcpy(perl_regex + start, lyp_ublock2urange[idx][1], LYP_URANGE_LEN);
933         }
934     }
935 
936     /* must return 0, already checked during parsing */
937     precomp = pcre_compile(perl_regex, PCRE_UTF8 | PCRE_ANCHORED | PCRE_DOLLAR_ENDONLY | PCRE_NO_AUTO_CAPTURE,
938                            &err_msg, &err_offset, NULL);
939     if (!precomp) {
940         LOGVAL(ctx, LYE_INREGEX, LY_VLOG_NONE, NULL, pattern, perl_regex + err_offset, err_msg);
941         free(perl_regex);
942         return EXIT_FAILURE;
943     }
944     free(perl_regex);
945 
946     if (pcre_precomp) {
947         *pcre_precomp = precomp;
948     } else {
949         free(precomp);
950     }
951 
952     return EXIT_SUCCESS;
953 }
954 
955 int
lyp_precompile_pattern(struct ly_ctx * ctx,const char * pattern,pcre ** pcre_cmp,pcre_extra ** pcre_std)956 lyp_precompile_pattern(struct ly_ctx *ctx, const char *pattern, pcre** pcre_cmp, pcre_extra **pcre_std)
957 {
958     const char *err_msg = NULL;
959 
960     if (lyp_check_pattern(ctx, pattern, pcre_cmp)) {
961         return EXIT_FAILURE;
962     }
963 
964     if (pcre_std && pcre_cmp) {
965         (*pcre_std) = pcre_study(*pcre_cmp, 0, &err_msg);
966         if (err_msg) {
967             LOGWRN(ctx, "Studying pattern \"%s\" failed (%s).", pattern, err_msg);
968         }
969     }
970 
971     return EXIT_SUCCESS;
972 }
973 
974 /**
975  * @brief Change the value into its canonical form. In libyang, additionally to the RFC,
976  * all identities have their module as a prefix in their canonical form.
977  *
978  * @param[in] ctx
979  * @param[in] type Type of the value.
980  * @param[in,out] value Original and then canonical value.
981  * @param[in] data1 If \p type is #LY_TYPE_BITS: (struct lys_type_bit **) type bit field,
982  *                                #LY_TYPE_DEC64: (int64_t *) parsed digits of the number itself without floating point,
983  *                                #LY_TYPE_IDENT: (const char *) local module name (identityref node module),
984  *                                #LY_TYPE_INT*: (int64_t *) parsed int number itself,
985  *                                #LY_TYPE_UINT*: (uint64_t *) parsed uint number itself,
986  *                                otherwise ignored.
987  * @param[in] data2 If \p type is #LY_TYPE_BITS: (int *) type bit field length,
988  *                                #LY_TYPE_DEC64: (uint8_t *) number of fraction digits (position of the floating point),
989  *                                otherwise ignored.
990  * @return 1 if a conversion took place, 0 if the value was kept the same, -1 on error.
991  */
992 static int
make_canonical(struct ly_ctx * ctx,int type,const char ** value,void * data1,void * data2)993 make_canonical(struct ly_ctx *ctx, int type, const char **value, void *data1, void *data2)
994 {
995     const uint16_t buf_len = 511;
996     char buf[buf_len + 1];
997     struct lys_type_bit **bits = NULL;
998     struct lyxp_expr *exp;
999     const char *module_name, *cur_expr, *end;
1000     int i, j, count;
1001     int64_t num;
1002     uint64_t unum;
1003     uint8_t c;
1004 
1005 #define LOGBUF(str) LOGERR(ctx, LY_EINVAL, "Value \"%s\" is too long.", str)
1006 
1007     switch (type) {
1008     case LY_TYPE_BITS:
1009         bits = (struct lys_type_bit **)data1;
1010         count = *((int *)data2);
1011         /* in canonical form, the bits are ordered by their position */
1012         buf[0] = '\0';
1013         for (i = 0; i < count; i++) {
1014             if (!bits[i]) {
1015                 /* bit not set */
1016                 continue;
1017             }
1018             if (buf[0]) {
1019                 LY_CHECK_ERR_RETURN(strlen(buf) + 1 + strlen(bits[i]->name) > buf_len, LOGBUF(bits[i]->name), -1);
1020                 sprintf(buf + strlen(buf), " %s", bits[i]->name);
1021             } else {
1022                 LY_CHECK_ERR_RETURN(strlen(bits[i]->name) > buf_len, LOGBUF(bits[i]->name), -1);
1023                 strcpy(buf, bits[i]->name);
1024             }
1025         }
1026         break;
1027 
1028     case LY_TYPE_IDENT:
1029         module_name = (const char *)data1;
1030         /* identity must always have a prefix */
1031         if (!strchr(*value, ':')) {
1032             LY_CHECK_ERR_RETURN(strlen(module_name) + 1 + strlen(*value) > buf_len, LOGBUF(*value), -1);
1033             sprintf(buf, "%s:%s", module_name, *value);
1034         } else {
1035             LY_CHECK_ERR_RETURN(strlen(*value) > buf_len, LOGBUF(*value), -1);
1036             strcpy(buf, *value);
1037         }
1038         break;
1039 
1040     case LY_TYPE_INST:
1041         exp = lyxp_parse_expr(ctx, *value);
1042         LY_CHECK_ERR_RETURN(!exp, LOGINT(ctx), -1);
1043 
1044         module_name = NULL;
1045         count = 0;
1046         for (i = 0; (unsigned)i < exp->used; ++i) {
1047             cur_expr = &exp->expr[exp->expr_pos[i]];
1048 
1049             /* copy WS */
1050             if (i && ((end = exp->expr + exp->expr_pos[i - 1] + exp->tok_len[i - 1]) != cur_expr)) {
1051                 if (count + (cur_expr - end) > buf_len) {
1052                     LOGBUF(end);
1053                     lyxp_expr_free(exp);
1054                     return -1;
1055                 }
1056                 strncpy(&buf[count], end, cur_expr - end);
1057                 count += cur_expr - end;
1058             }
1059 
1060             if ((exp->tokens[i] == LYXP_TOKEN_NAMETEST) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
1061                 /* get the module name with ":" */
1062                 ++end;
1063                 j = end - cur_expr;
1064 
1065                 if (!module_name || strncmp(cur_expr, module_name, j)) {
1066                     /* print module name with colon, it does not equal to the parent one */
1067                     if (count + j > buf_len) {
1068                         LOGBUF(cur_expr);
1069                         lyxp_expr_free(exp);
1070                         return -1;
1071                     }
1072                     strncpy(&buf[count], cur_expr, j);
1073                     count += j;
1074                 }
1075                 module_name = cur_expr;
1076 
1077                 /* copy the rest */
1078                 if (count + (exp->tok_len[i] - j) > buf_len) {
1079                     LOGBUF(end);
1080                     lyxp_expr_free(exp);
1081                     return -1;
1082                 }
1083                 strncpy(&buf[count], end, exp->tok_len[i] - j);
1084                 count += exp->tok_len[i] - j;
1085             } else {
1086                 if (count + exp->tok_len[i] > buf_len) {
1087                     LOGBUF(&exp->expr[exp->expr_pos[i]]);
1088                     lyxp_expr_free(exp);
1089                     return -1;
1090                 }
1091                 strncpy(&buf[count], &exp->expr[exp->expr_pos[i]], exp->tok_len[i]);
1092                 count += exp->tok_len[i];
1093             }
1094         }
1095         if (count > buf_len) {
1096             LOGINT(ctx);
1097             lyxp_expr_free(exp);
1098             return -1;
1099         }
1100         buf[count] = '\0';
1101 
1102         lyxp_expr_free(exp);
1103         break;
1104 
1105     case LY_TYPE_DEC64:
1106         num = *((int64_t *)data1);
1107         c = *((uint8_t *)data2);
1108         if (num) {
1109             count = sprintf(buf, "%"PRId64" ", num);
1110             if ( (num > 0 && (count - 1) <= c)
1111                  || (count - 2) <= c ) {
1112                 /* we have 0. value, print the value with the leading zeros
1113                  * (one for 0. and also keep the correct with of num according
1114                  * to fraction-digits value)
1115                  * for (num<0) - extra character for '-' sign */
1116                 count = sprintf(buf, "%0*"PRId64" ", (num > 0) ? (c + 1) : (c + 2), num);
1117             }
1118             for (i = c, j = 1; i > 0 ; i--) {
1119                 if (j && i > 1 && buf[count - 2] == '0') {
1120                     /* we have trailing zero to skip */
1121                     buf[count - 1] = '\0';
1122                 } else {
1123                     j = 0;
1124                     buf[count - 1] = buf[count - 2];
1125                 }
1126                 count--;
1127             }
1128             buf[count - 1] = '.';
1129         } else {
1130             /* zero */
1131             sprintf(buf, "0.0");
1132         }
1133         break;
1134 
1135     case LY_TYPE_INT8:
1136     case LY_TYPE_INT16:
1137     case LY_TYPE_INT32:
1138     case LY_TYPE_INT64:
1139         num = *((int64_t *)data1);
1140         sprintf(buf, "%"PRId64, num);
1141         break;
1142 
1143     case LY_TYPE_UINT8:
1144     case LY_TYPE_UINT16:
1145     case LY_TYPE_UINT32:
1146     case LY_TYPE_UINT64:
1147         unum = *((uint64_t *)data1);
1148         sprintf(buf, "%"PRIu64, unum);
1149         break;
1150 
1151     default:
1152         /* should not be even called - just do nothing */
1153         return 0;
1154     }
1155 
1156     if (strcmp(buf, *value)) {
1157         lydict_remove(ctx, *value);
1158         *value = lydict_insert(ctx, buf, 0);
1159         return 1;
1160     }
1161 
1162     return 0;
1163 
1164 #undef LOGBUF
1165 }
1166 
1167 static const char *
ident_val_add_module_prefix(const char * value,const struct lyxml_elem * xml,struct ly_ctx * ctx)1168 ident_val_add_module_prefix(const char *value, const struct lyxml_elem *xml, struct ly_ctx *ctx)
1169 {
1170     const struct lyxml_ns *ns;
1171     const struct lys_module *mod;
1172     char *str;
1173 
1174     do {
1175         LY_TREE_FOR((struct lyxml_ns *)xml->attr, ns) {
1176             if ((ns->type == LYXML_ATTR_NS) && !ns->prefix) {
1177                 /* match */
1178                 break;
1179             }
1180         }
1181         if (!ns) {
1182             xml = xml->parent;
1183         }
1184     } while (!ns && xml);
1185 
1186     if (!ns) {
1187         /* no default namespace */
1188         LOGERR(ctx, LY_EINVAL, "Identity \"%s\" has no namespace.", value);
1189         return NULL;
1190     }
1191 
1192     /* find module */
1193     mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL, 1);
1194     if (!mod) {
1195         LOGINT(ctx);
1196         return NULL;
1197     }
1198 
1199     if (asprintf(&str, "%s:%s", mod->name, value) == -1) {
1200         LOGMEM(ctx);
1201         return NULL;
1202     }
1203     lydict_remove(ctx, value);
1204 
1205     return lydict_insert_zc(ctx, str);
1206 }
1207 
1208 /*
1209  * xml  - optional for converting instance-identifier and identityref into JSON format
1210  * leaf - mandatory to know the context (necessary e.g. for prefixes in idenitytref values)
1211  * attr - alternative to leaf in case of parsing value in annotations (attributes)
1212  * local_mod - optional if the local module dos not match the module of leaf/attr
1213  * store - flag for union resolution - we do not want to store the result, we are just learning the type
1214  * dflt - whether the value is a default value from the schema
1215  */
1216 struct lys_type *
lyp_parse_value(struct lys_type * type,const char ** value_,struct lyxml_elem * xml,struct lyd_node_leaf_list * leaf,struct lyd_attr * attr,struct lys_module * local_mod,int store,int dflt)1217 lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *xml,
1218                 struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct lys_module *local_mod,
1219                 int store, int dflt)
1220 {
1221     struct lys_type *ret = NULL, *t;
1222     struct lys_tpdf *tpdf;
1223     enum int_log_opts prev_ilo;
1224     int c, len, found = 0;
1225     unsigned int i, j;
1226     int64_t num;
1227     uint64_t unum, uind, u = 0;
1228     const char *ptr, *value = *value_, *itemname, *old_val_str = NULL;
1229     struct lys_type_bit **bits = NULL;
1230     struct lys_ident *ident;
1231     lyd_val *val, old_val;
1232     LY_DATA_TYPE *val_type, old_val_type;
1233     uint8_t *val_flags, old_val_flags;
1234     struct lyd_node *contextnode;
1235     struct ly_ctx *ctx = type->parent->module->ctx;
1236 
1237     assert(leaf || attr);
1238 
1239     if (leaf) {
1240         assert(!attr);
1241         if (!local_mod) {
1242             local_mod = leaf->schema->module;
1243         }
1244         val = &leaf->value;
1245         val_type = &leaf->value_type;
1246         val_flags = &leaf->value_flags;
1247         contextnode = (struct lyd_node *)leaf;
1248         itemname = leaf->schema->name;
1249     } else {
1250         assert(!leaf);
1251         if (!local_mod) {
1252             local_mod = attr->annotation->module;
1253         }
1254         val = &attr->value;
1255         val_type = &attr->value_type;
1256         val_flags = &attr->value_flags;
1257         contextnode = attr->parent;
1258         itemname = attr->name;
1259     }
1260 
1261     /* fully clear the value */
1262     if (store) {
1263         if (leaf) {
1264             old_val_str = lydict_insert(ctx, leaf->value_str, 0);
1265         } else {
1266             old_val_str = lydict_insert(ctx, attr->value_str, 0);
1267         }
1268         lyd_free_value(*val, *val_type, *val_flags, type, old_val_str, &old_val, &old_val_type, &old_val_flags);
1269         *val_flags &= ~LY_VALUE_UNRES;
1270         *val_flags &= ~LY_VALUE_USER;
1271     }
1272 
1273     ret = type;
1274     switch (type->base) {
1275     case LY_TYPE_BINARY:
1276         /* get number of octets for length validation */
1277         unum = 0;
1278         ptr = NULL;
1279         if (value) {
1280             /* silently skip leading/trailing whitespaces */
1281             for (uind = 0; isspace(value[uind]); ++uind);
1282             ptr = &value[uind];
1283             u = strlen(ptr);
1284             while (u && isspace(ptr[u - 1])) {
1285                 --u;
1286             }
1287             unum = u;
1288             for (uind = 0; uind < u; ++uind) {
1289                 if (ptr[uind] == '\n') {
1290                     unum--;
1291                 } else if ((ptr[uind] < '/' && ptr[uind] != '+') ||
1292                     (ptr[uind] > '9' && ptr[uind] < 'A') ||
1293                     (ptr[uind] > 'Z' && ptr[uind] < 'a') || ptr[uind] > 'z') {
1294                     if (ptr[uind] == '=') {
1295                         /* padding */
1296                         if (uind == u - 2 && ptr[uind + 1] == '=') {
1297                             found = 2;
1298                             uind++;
1299                         } else if (uind == u - 1) {
1300                             found = 1;
1301                         }
1302                     }
1303                     if (!found) {
1304                         /* error */
1305                         LOGVAL(ctx, LYE_INCHAR, LY_VLOG_LYD, contextnode, ptr[uind], &ptr[uind]);
1306                         LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Invalid Base64 character.");
1307                         goto error;
1308                     }
1309                 }
1310             }
1311         }
1312 
1313         if (unum & 3) {
1314             /* base64 length must be multiple of 4 chars */
1315             if (leaf) {
1316                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1317             } else {
1318                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1319             }
1320             LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Base64 encoded value length must be divisible by 4.");
1321             goto error;
1322         }
1323 
1324         /* length of the encoded string */
1325         len = ((unum / 4) * 3) - found;
1326         if (validate_length_range(0, len, 0, 0, 0, type, value, contextnode)) {
1327             goto error;
1328         }
1329 
1330         if (value && (ptr != value || ptr[u] != '\0')) {
1331             /* update the changed value */
1332             ptr = lydict_insert(ctx, ptr, u);
1333             lydict_remove(ctx, *value_);
1334             *value_ = ptr;
1335         }
1336 
1337         if (store) {
1338             /* store the result */
1339             val->binary = value;
1340             *val_type = LY_TYPE_BINARY;
1341         }
1342         break;
1343 
1344     case LY_TYPE_BITS:
1345         /* locate bits structure with the bits definitions
1346          * since YANG 1.1 allows restricted bits, it is the first
1347          * bits type with some explicit bit specification */
1348         for (; !type->info.bits.count; type = &type->der->type);
1349 
1350         if (value || store) {
1351             /* allocate the array of pointers to bits definition */
1352             bits = calloc(type->info.bits.count, sizeof *bits);
1353             LY_CHECK_ERR_GOTO(!bits, LOGMEM(ctx), error);
1354         }
1355 
1356         if (!value) {
1357             /* no bits set */
1358             if (store) {
1359                 /* store empty array */
1360                 val->bit = bits;
1361                 *val_type = LY_TYPE_BITS;
1362             }
1363             break;
1364         }
1365 
1366         c = 0;
1367         i = 0;
1368         while (value[c]) {
1369             /* skip leading whitespaces */
1370             while (isspace(value[c])) {
1371                 c++;
1372             }
1373             if (!value[c]) {
1374                 /* trailing white spaces */
1375                 break;
1376             }
1377 
1378             /* get the length of the bit identifier */
1379             for (len = 0; value[c] && !isspace(value[c]); c++, len++);
1380 
1381             /* go back to the beginning of the identifier */
1382             c = c - len;
1383 
1384             /* find bit definition, identifiers appear ordered by their position */
1385             for (found = i = 0; i < type->info.bits.count; i++) {
1386                 if (!strncmp(type->info.bits.bit[i].name, &value[c], len) && !type->info.bits.bit[i].name[len]) {
1387                     if (!dflt) {
1388                         /* we have match, check if the value is enabled ... */
1389                         for (j = 0; j < type->info.bits.bit[i].iffeature_size; j++) {
1390                             if (!resolve_iffeature(&type->info.bits.bit[i].iffeature[j])) {
1391                                 if (leaf) {
1392                                     LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1393                                 } else {
1394                                     LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1395                                 }
1396                                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
1397                                     "Bit \"%s\" is disabled by its %d. if-feature condition.",
1398                                     type->info.bits.bit[i].name, j + 1);
1399                                 free(bits);
1400                                 goto error;
1401                             }
1402                         }
1403                     }
1404                     /* check that the value was not already set */
1405                     if (bits[i]) {
1406                         if (leaf) {
1407                             LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1408                         } else {
1409                             LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1410                         }
1411                         LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Bit \"%s\" used multiple times.",
1412                                type->info.bits.bit[i].name);
1413                         free(bits);
1414                         goto error;
1415                     }
1416                     /* ... and then store the pointer */
1417                     bits[i] = &type->info.bits.bit[i];
1418 
1419                     /* stop searching */
1420                     found = 1;
1421                     break;
1422                 }
1423             }
1424 
1425             if (!found) {
1426                 /* referenced bit value does not exist */
1427                 if (leaf) {
1428                     LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1429                 } else {
1430                     LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1431                 }
1432                 free(bits);
1433                 goto error;
1434             }
1435             c = c + len;
1436         }
1437 
1438         if (make_canonical(ctx, LY_TYPE_BITS, value_, bits, &type->info.bits.count) == -1) {
1439             free(bits);
1440             goto error;
1441         }
1442 
1443         if (store) {
1444             /* store the result */
1445             val->bit = bits;
1446             *val_type = LY_TYPE_BITS;
1447         } else {
1448             free(bits);
1449         }
1450         break;
1451 
1452     case LY_TYPE_BOOL:
1453         if (value && !strcmp(value, "true")) {
1454             if (store) {
1455                 val->bln = 1;
1456             }
1457         } else if (!value || strcmp(value, "false")) {
1458             if (leaf) {
1459                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value ? value : "", itemname);
1460             } else {
1461                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value ? value : "");
1462             }
1463             goto error;
1464         } else {
1465             if (store) {
1466                 val->bln = 0;
1467             }
1468         }
1469 
1470         if (store) {
1471             *val_type = LY_TYPE_BOOL;
1472         }
1473         break;
1474 
1475     case LY_TYPE_DEC64:
1476         if (!value || !value[0]) {
1477             if (leaf) {
1478                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1479             } else {
1480                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1481             }
1482             goto error;
1483         }
1484 
1485         ptr = value;
1486         if (parse_range_dec64(&ptr, type->info.dec64.dig, &num) || ptr[0]) {
1487             if (leaf) {
1488                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1489             } else {
1490                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1491             }
1492             goto error;
1493         }
1494 
1495         if (validate_length_range(2, 0, 0, num, type->info.dec64.dig, type, value, contextnode)) {
1496             goto error;
1497         }
1498 
1499         if (make_canonical(ctx, LY_TYPE_DEC64, value_, &num, &type->info.dec64.dig) == -1) {
1500             goto error;
1501         }
1502 
1503         if (store) {
1504             /* store the result */
1505             val->dec64 = num;
1506             *val_type = LY_TYPE_DEC64;
1507         }
1508         break;
1509 
1510     case LY_TYPE_EMPTY:
1511         if (value && value[0]) {
1512             if (leaf) {
1513                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1514             } else {
1515                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1516             }
1517             goto error;
1518         }
1519 
1520         if (store) {
1521             *val_type = LY_TYPE_EMPTY;
1522         }
1523         break;
1524 
1525     case LY_TYPE_ENUM:
1526         /* locate enums structure with the enumeration definitions,
1527          * since YANG 1.1 allows restricted enums, it is the first
1528          * enum type with some explicit enum specification */
1529         for (; !type->info.enums.count; type = &type->der->type);
1530 
1531         /* find matching enumeration value */
1532         for (i = found = 0; i < type->info.enums.count; i++) {
1533             if (value && !strcmp(value, type->info.enums.enm[i].name)) {
1534                 if (!dflt) {
1535                     /* we have match, check if the value is enabled ... */
1536                     for (j = 0; j < type->info.enums.enm[i].iffeature_size; j++) {
1537                         if (!resolve_iffeature(&type->info.enums.enm[i].iffeature[j])) {
1538                             if (leaf) {
1539                                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1540                             } else {
1541                                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1542                             }
1543                             LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Enum \"%s\" is disabled by its %d. if-feature condition.",
1544                                 value, j + 1);
1545                             goto error;
1546                         }
1547                     }
1548                 }
1549                 /* ... and store pointer to the definition */
1550                 if (store) {
1551                     val->enm = &type->info.enums.enm[i];
1552                     *val_type = LY_TYPE_ENUM;
1553                 }
1554                 found = 1;
1555                 break;
1556             }
1557         }
1558 
1559         if (!found) {
1560             if (leaf) {
1561                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value ? value : "", itemname);
1562             } else {
1563                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value ? value : "");
1564             }
1565             goto error;
1566         }
1567         break;
1568 
1569     case LY_TYPE_IDENT:
1570         if (!value) {
1571             if (leaf) {
1572                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1573             } else {
1574                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1575             }
1576             goto error;
1577         }
1578 
1579         if (xml) {
1580             ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1581             /* first, convert value into the json format, silently */
1582             value = transform_xml2json(ctx, value, xml, 0, 0);
1583             ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1584             if (!value) {
1585                 /* invalid identityref format */
1586                 if (leaf) {
1587                     LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_, itemname);
1588                 } else {
1589                     LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1590                 }
1591                 goto error;
1592             }
1593 
1594             /* the value has no prefix (default namespace), but the element's namespace has a prefix, find default namespace */
1595             if (!strchr(value, ':') && xml->ns->prefix) {
1596                 value = ident_val_add_module_prefix(value, xml, ctx);
1597                 if (!value) {
1598                     goto error;
1599                 }
1600             }
1601         } else if (dflt) {
1602             ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1603             /* the value actually uses module's prefixes instead of the module names as in JSON format,
1604              * we have to convert it */
1605             value = transform_schema2json(local_mod, value);
1606             ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1607             if (!value) {
1608                 /* invalid identityref format or it was already transformed, so ignore the error here */
1609                 value = lydict_insert(ctx, *value_, 0);
1610             }
1611         } else {
1612             value = lydict_insert(ctx, *value_, 0);
1613         }
1614         /* value is now in the dictionary, whether it differs from *value_ or not */
1615 
1616         ident = resolve_identref(type, value, contextnode, local_mod, dflt);
1617         if (!ident) {
1618             lydict_remove(ctx, value);
1619             goto error;
1620         } else if (store) {
1621             /* store the result */
1622             val->ident = ident;
1623             *val_type = LY_TYPE_IDENT;
1624         }
1625 
1626         /* the value is always changed and includes prefix */
1627         if (dflt) {
1628             type->parent->flags |= LYS_DFLTJSON;
1629         }
1630 
1631         if (make_canonical(ctx, LY_TYPE_IDENT, &value, (void*)lys_main_module(local_mod)->name, NULL) == -1) {
1632             lydict_remove(ctx, value);
1633             goto error;
1634         }
1635 
1636         /* replace the old value with the new one (even if they may be the same) */
1637         lydict_remove(ctx, *value_);
1638         *value_ = value;
1639         break;
1640 
1641     case LY_TYPE_INST:
1642         if (!value) {
1643             if (leaf) {
1644                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1645             } else {
1646                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1647             }
1648             goto error;
1649         }
1650 
1651         if (xml) {
1652             ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1653             /* first, convert value into the json format, silently */
1654             value = transform_xml2json(ctx, value, xml, 1, 1);
1655             ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1656             if (!value) {
1657                 /* invalid instance-identifier format */
1658                 if (leaf) {
1659                     LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_, itemname);
1660                 } else {
1661                     LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1662                 }
1663                 goto error;
1664             } else if (ly_strequal(value, *value_, 1)) {
1665                 /* we have actually created the same expression (prefixes are the same as the module names)
1666                  * so we have just increased dictionary's refcount - fix it */
1667                 lydict_remove(ctx, value);
1668             }
1669         } else if (dflt) {
1670             /* turn logging off */
1671             ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1672 
1673             /* the value actually uses module's prefixes instead of the module names as in JSON format,
1674              * we have to convert it */
1675             value = transform_schema2json(local_mod, value);
1676             if (!value) {
1677                 /* invalid identityref format or it was already transformed, so ignore the error here */
1678                 value = *value_;
1679             } else if (ly_strequal(value, *value_, 1)) {
1680                 /* we have actually created the same expression (prefixes are the same as the module names)
1681                  * so we have just increased dictionary's refcount - fix it */
1682                 lydict_remove(ctx, value);
1683             }
1684             /* turn logging back on */
1685             ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1686         } else {
1687             if ((c = make_canonical(ctx, LY_TYPE_INST, &value, NULL, NULL))) {
1688                 if (c == -1) {
1689                     goto error;
1690                 }
1691 
1692                 /* if a change occurred, value was removed from the dictionary so fix the pointers */
1693                 *value_ = value;
1694             }
1695         }
1696 
1697         if (store) {
1698             /* note that the data node is an unresolved instance-identifier */
1699             val->instance = NULL;
1700             *val_type = LY_TYPE_INST;
1701             *val_flags |= LY_VALUE_UNRES;
1702         }
1703 
1704         if (!ly_strequal(value, *value_, 1)) {
1705             /* update the changed value */
1706             lydict_remove(ctx, *value_);
1707             *value_ = value;
1708 
1709             /* we have to remember the conversion into JSON format to be able to print it in correct form */
1710             if (dflt) {
1711                 type->parent->flags |= LYS_DFLTJSON;
1712             }
1713         }
1714         break;
1715 
1716     case LY_TYPE_LEAFREF:
1717         if (!value) {
1718             if (leaf) {
1719                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1720             } else {
1721                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1722             }
1723             goto error;
1724         }
1725 
1726         /* it is called not only to get the final type, but mainly to update value to canonical or JSON form
1727          * if needed */
1728         t = lyp_parse_value(&type->info.lref.target->type, value_, xml, leaf, attr, NULL, store, dflt);
1729         value = *value_; /* refresh possibly changed value */
1730         if (!t) {
1731             /* already logged */
1732             goto error;
1733         }
1734 
1735         if (store) {
1736             /* make the note that the data node is an unresolved leafref (value union was already filled) */
1737             *val_flags |= LY_VALUE_UNRES;
1738         }
1739 
1740         ret = t;
1741         break;
1742 
1743     case LY_TYPE_STRING:
1744         if (validate_length_range(0, (value ? ly_strlen_utf8(value) : 0), 0, 0, 0, type, value, contextnode)) {
1745             goto error;
1746         }
1747 
1748         if (validate_pattern(ctx, value, type, contextnode)) {
1749             goto error;
1750         }
1751 
1752         /* special handling of ietf-yang-types xpath1.0 */
1753         for (tpdf = type->der;
1754              tpdf->module && (strcmp(tpdf->name, "xpath1.0") || strcmp(tpdf->module->name, "ietf-yang-types"));
1755              tpdf = tpdf->type.der);
1756         if (tpdf->module && xml) {
1757             /* convert value into the json format */
1758             value = transform_xml2json(ctx, value ? value : "", xml, 1, 1);
1759             if (!value) {
1760                 /* invalid instance-identifier format */
1761                 if (leaf) {
1762                     LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_, itemname);
1763                 } else {
1764                     LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1765                 }
1766                 goto error;
1767             }
1768 
1769             if (!ly_strequal(value, *value_, 1)) {
1770                 /* update the changed value */
1771                 lydict_remove(ctx, *value_);
1772                 *value_ = value;
1773             }
1774         }
1775 
1776         if (store) {
1777             /* store the result */
1778             val->string = value;
1779             *val_type = LY_TYPE_STRING;
1780         }
1781         break;
1782 
1783     case LY_TYPE_INT8:
1784         if (parse_int(value, __INT64_C(-128), __INT64_C(127), dflt ? 0 : 10, &num, contextnode)
1785                 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1786             goto error;
1787         }
1788 
1789         if (make_canonical(ctx, LY_TYPE_INT8, value_, &num, NULL) == -1) {
1790             goto error;
1791         }
1792 
1793         if (store) {
1794             /* store the result */
1795             val->int8 = (int8_t)num;
1796             *val_type = LY_TYPE_INT8;
1797         }
1798         break;
1799 
1800     case LY_TYPE_INT16:
1801         if (parse_int(value, __INT64_C(-32768), __INT64_C(32767), dflt ? 0 : 10, &num, contextnode)
1802                 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1803             goto error;
1804         }
1805 
1806         if (make_canonical(ctx, LY_TYPE_INT16, value_, &num, NULL) == -1) {
1807             goto error;
1808         }
1809 
1810         if (store) {
1811             /* store the result */
1812             val->int16 = (int16_t)num;
1813             *val_type = LY_TYPE_INT16;
1814         }
1815         break;
1816 
1817     case LY_TYPE_INT32:
1818         if (parse_int(value, __INT64_C(-2147483648), __INT64_C(2147483647), dflt ? 0 : 10, &num, contextnode)
1819                 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1820             goto error;
1821         }
1822 
1823         if (make_canonical(ctx, LY_TYPE_INT32, value_, &num, NULL) == -1) {
1824             goto error;
1825         }
1826 
1827         if (store) {
1828             /* store the result */
1829             val->int32 = (int32_t)num;
1830             *val_type = LY_TYPE_INT32;
1831         }
1832         break;
1833 
1834     case LY_TYPE_INT64:
1835         if (parse_int(value, __INT64_C(-9223372036854775807) - __INT64_C(1), __INT64_C(9223372036854775807),
1836                       dflt ? 0 : 10, &num, contextnode)
1837                 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1838             goto error;
1839         }
1840 
1841         if (make_canonical(ctx, LY_TYPE_INT64, value_, &num, NULL) == -1) {
1842             goto error;
1843         }
1844 
1845         if (store) {
1846             /* store the result */
1847             val->int64 = num;
1848             *val_type = LY_TYPE_INT64;
1849         }
1850         break;
1851 
1852     case LY_TYPE_UINT8:
1853         if (parse_uint(value, __UINT64_C(255), dflt ? 0 : 10, &unum, contextnode)
1854                 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1855             goto error;
1856         }
1857 
1858         if (make_canonical(ctx, LY_TYPE_UINT8, value_, &unum, NULL) == -1) {
1859             goto error;
1860         }
1861 
1862         if (store) {
1863             /* store the result */
1864             val->uint8 = (uint8_t)unum;
1865             *val_type = LY_TYPE_UINT8;
1866         }
1867         break;
1868 
1869     case LY_TYPE_UINT16:
1870         if (parse_uint(value, __UINT64_C(65535), dflt ? 0 : 10, &unum, contextnode)
1871                 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1872             goto error;
1873         }
1874 
1875         if (make_canonical(ctx, LY_TYPE_UINT16, value_, &unum, NULL) == -1) {
1876             goto error;
1877         }
1878 
1879         if (store) {
1880             /* store the result */
1881             val->uint16 = (uint16_t)unum;
1882             *val_type = LY_TYPE_UINT16;
1883         }
1884         break;
1885 
1886     case LY_TYPE_UINT32:
1887         if (parse_uint(value, __UINT64_C(4294967295), dflt ? 0 : 10, &unum, contextnode)
1888                 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1889             goto error;
1890         }
1891 
1892         if (make_canonical(ctx, LY_TYPE_UINT32, value_, &unum, NULL) == -1) {
1893             goto error;
1894         }
1895 
1896         if (store) {
1897             /* store the result */
1898             val->uint32 = (uint32_t)unum;
1899             *val_type = LY_TYPE_UINT32;
1900         }
1901         break;
1902 
1903     case LY_TYPE_UINT64:
1904         if (parse_uint(value, __UINT64_C(18446744073709551615), dflt ? 0 : 10, &unum, contextnode)
1905                 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1906             goto error;
1907         }
1908 
1909         if (make_canonical(ctx, LY_TYPE_UINT64, value_, &unum, NULL) == -1) {
1910             goto error;
1911         }
1912 
1913         if (store) {
1914             /* store the result */
1915             val->uint64 = unum;
1916             *val_type = LY_TYPE_UINT64;
1917         }
1918         break;
1919 
1920     case LY_TYPE_UNION:
1921         if (store) {
1922             /* unresolved union type */
1923             memset(val, 0, sizeof(lyd_val));
1924             *val_type = LY_TYPE_UNION;
1925         }
1926 
1927         if (type->info.uni.has_ptr_type) {
1928             /* we are not resolving anything here, only parsing, and in this case we cannot decide
1929              * the type without resolving it -> we return the union type (resolve it with resolve_union()) */
1930             if (xml) {
1931                 /* in case it should resolve into a instance-identifier, we can only do the JSON conversion here */
1932                 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1933                 value = transform_xml2json(ctx, value, xml, 1, 1);
1934                 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1935 
1936                 /* update the changed value */
1937                 if (value) {
1938                     lydict_remove(ctx, *value_);
1939                     *value_ = value;
1940                 } else {
1941                     value = *value_;
1942                 }
1943 
1944                 if (store) {
1945                     /* store the (unresolved) result */
1946                     val->string = lydict_insert(ctx, value, 0);
1947                 }
1948             }
1949             break;
1950         }
1951 
1952         t = NULL;
1953         found = 0;
1954 
1955         /* turn logging off, we are going to try to validate the value with all the types in order */
1956         ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1957 
1958         while ((t = lyp_get_next_union_type(type, t, &found))) {
1959             found = 0;
1960             ret = lyp_parse_value(t, value_, xml, leaf, attr, NULL, store, dflt);
1961             if (ret) {
1962                 /* we have the result */
1963                 break;
1964             }
1965 
1966             if (store) {
1967                 /* erase possible present and invalid value data */
1968                 lyd_free_value(*val, *val_type, *val_flags, t, *value_, NULL, NULL, NULL);
1969                 memset(val, 0, sizeof(lyd_val));
1970             }
1971         }
1972 
1973         /* turn logging back on */
1974         ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1975 
1976         if (!t) {
1977             /* not found */
1978             if (store) {
1979                 *val_type = 0;
1980             }
1981             if (leaf) {
1982                 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_ ? *value_ : "", itemname);
1983             } else {
1984                 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1985             }
1986             goto error;
1987         }
1988         break;
1989 
1990     default:
1991         LOGINT(ctx);
1992         goto error;
1993     }
1994 
1995     /* search user types in case this value is supposed to be stored in a custom way */
1996     if (store && ret->der && ret->der->module) {
1997         c = lytype_store(ret->der->module, ret->der->name, value_, val);
1998         if (c == -1) {
1999             if (leaf) {
2000                 LOGPATH(ctx, LY_VLOG_LYD, leaf);
2001             }
2002             goto error;
2003         } else if (!c) {
2004             *val_flags |= LY_VALUE_USER;
2005         }
2006     }
2007 
2008     /* free backup (using the original type, unless we were parsing a leafref - then this was freed in the recursive call) */
2009     if (store) {
2010         if (type->base != LY_TYPE_LEAFREF) {
2011             lyd_free_value(old_val, old_val_type, old_val_flags, type, old_val_str, NULL, NULL, NULL);
2012         }
2013         lydict_remove(ctx, old_val_str);
2014     }
2015     return ret;
2016 
2017 error:
2018     /* restore the backup */
2019     if (store) {
2020         *val = old_val;
2021         *val_type = old_val_type;
2022         *val_flags = old_val_flags;
2023         lydict_remove(ctx, old_val_str);
2024     }
2025     return NULL;
2026 }
2027 
2028 /* does not log, cannot fail */
2029 struct lys_type *
lyp_get_next_union_type(struct lys_type * type,struct lys_type * prev_type,int * found)2030 lyp_get_next_union_type(struct lys_type *type, struct lys_type *prev_type, int *found)
2031 {
2032     unsigned int i;
2033     struct lys_type *ret = NULL;
2034 
2035     while (!type->info.uni.count) {
2036         assert(type->der); /* at least the direct union type has to have type specified */
2037         type = &type->der->type;
2038     }
2039 
2040     for (i = 0; i < type->info.uni.count; ++i) {
2041         if (type->info.uni.types[i].base == LY_TYPE_UNION) {
2042             ret = lyp_get_next_union_type(&type->info.uni.types[i], prev_type, found);
2043             if (ret) {
2044                 break;
2045             }
2046             continue;
2047         }
2048 
2049         if (!prev_type || *found) {
2050             ret = &type->info.uni.types[i];
2051             break;
2052         }
2053 
2054         if (&type->info.uni.types[i] == prev_type) {
2055             *found = 1;
2056         }
2057     }
2058 
2059     return ret;
2060 }
2061 
2062 /* ret 0 - ret set, ret 1 - ret not set, no log, ret -1 - ret not set, fatal error */
2063 int
lyp_fill_attr(struct ly_ctx * ctx,struct lyd_node * parent,const char * module_ns,const char * module_name,const char * attr_name,const char * attr_value,struct lyxml_elem * xml,struct lyd_attr ** ret)2064 lyp_fill_attr(struct ly_ctx *ctx, struct lyd_node *parent, const char *module_ns, const char *module_name,
2065               const char *attr_name, const char *attr_value, struct lyxml_elem *xml, struct lyd_attr **ret)
2066 {
2067     const struct lys_module *mod = NULL;
2068     const struct lys_submodule *submod = NULL;
2069     struct lys_type **type;
2070     struct lyd_attr *dattr;
2071     int pos, i, j, k;
2072 
2073     /* first, get module where the annotation should be defined */
2074     if (module_ns) {
2075         mod = (struct lys_module *)ly_ctx_get_module_by_ns(ctx, module_ns, NULL, 0);
2076     } else if (module_name) {
2077         mod = (struct lys_module *)ly_ctx_get_module(ctx, module_name, NULL, 0);
2078     } else {
2079         LOGINT(ctx);
2080         return -1;
2081     }
2082     if (!mod) {
2083         return 1;
2084     }
2085 
2086     /* then, find the appropriate annotation definition */
2087     pos = -1;
2088     for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
2089         j = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
2090         if (j == -1) {
2091             break;
2092         }
2093         if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
2094             pos = i + j;
2095             break;
2096         }
2097     }
2098 
2099     /* try submodules */
2100     if (pos == -1) {
2101         for (k = 0; k < mod->inc_size; ++k) {
2102             submod = mod->inc[k].submodule;
2103             for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
2104                 j = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
2105                 if (j == -1) {
2106                     break;
2107                 }
2108                 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
2109                     pos = i + j;
2110                     break;
2111                 }
2112             }
2113         }
2114     }
2115 
2116     if (pos == -1) {
2117         return 1;
2118     }
2119 
2120     /* allocate and fill the data attribute structure */
2121     dattr = calloc(1, sizeof *dattr);
2122     LY_CHECK_ERR_RETURN(!dattr, LOGMEM(ctx), -1);
2123 
2124     dattr->parent = parent;
2125     dattr->next = NULL;
2126     dattr->annotation = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] :
2127                                  (struct lys_ext_instance_complex *)mod->ext[pos];
2128     dattr->name = lydict_insert(ctx, attr_name, 0);
2129     dattr->value_str = lydict_insert(ctx, attr_value, 0);
2130 
2131     /* the value is here converted to a JSON format if needed in case of LY_TYPE_IDENT and LY_TYPE_INST or to a
2132      * canonical form of the value */
2133     type = lys_ext_complex_get_substmt(LY_STMT_TYPE, dattr->annotation, NULL);
2134     if (!type || !lyp_parse_value(*type, &dattr->value_str, xml, NULL, dattr, NULL, 1, 0)) {
2135         lydict_remove(ctx, dattr->name);
2136         lydict_remove(ctx, dattr->value_str);
2137         free(dattr);
2138         return -1;
2139     }
2140 
2141     *ret = dattr;
2142     return 0;
2143 }
2144 
2145 int
lyp_check_edit_attr(struct ly_ctx * ctx,struct lyd_attr * attr,struct lyd_node * parent,int * editbits)2146 lyp_check_edit_attr(struct ly_ctx *ctx, struct lyd_attr *attr, struct lyd_node *parent, int *editbits)
2147 {
2148     struct lyd_attr *last = NULL;
2149     int bits = 0;
2150 
2151     /* 0x01 - insert attribute present
2152      * 0x02 - insert is relative (before or after)
2153      * 0x04 - value attribute present
2154      * 0x08 - key attribute present
2155      * 0x10 - operation attribute present
2156      * 0x20 - operation not allowing insert attribute (delete or remove)
2157      */
2158     LY_TREE_FOR(attr, attr) {
2159         last = NULL;
2160         if (!strcmp(attr->annotation->arg_value, "operation") &&
2161                 !strcmp(attr->annotation->module->name, "ietf-netconf")) {
2162             if (bits & 0x10) {
2163                 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "operation attributes", parent->schema->name);
2164                 return -1;
2165             }
2166 
2167             bits |= 0x10;
2168             if (attr->value.enm->value >= 3) {
2169                 /* delete or remove */
2170                 bits |= 0x20;
2171             }
2172         } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
2173                 !strcmp(attr->annotation->arg_value, "insert")) {
2174             /* 'insert' attribute present */
2175             if (!(parent->schema->flags & LYS_USERORDERED)) {
2176                 /* ... but it is not expected */
2177                 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, "insert");
2178                 return -1;
2179             }
2180             if (bits & 0x01) {
2181                 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "insert attributes", parent->schema->name);
2182                 return -1;
2183             }
2184 
2185             bits |= 0x01;
2186             if (attr->value.enm->value >= 2) {
2187                 /* before or after */
2188                 bits |= 0x02;
2189             }
2190             last = attr;
2191         } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
2192                 !strcmp(attr->annotation->arg_value, "value")) {
2193             if (bits & 0x04) {
2194                 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "value attributes", parent->schema->name);
2195                 return -1;
2196             } else if (parent->schema->nodetype & LYS_LIST) {
2197                 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, attr->name);
2198                 return -1;
2199             }
2200             bits |= 0x04;
2201             last = attr;
2202         } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
2203                 !strcmp(attr->annotation->arg_value, "key")) {
2204             if (bits & 0x08) {
2205                 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "key attributes", parent->schema->name);
2206                 return -1;
2207             } else if (parent->schema->nodetype & LYS_LEAFLIST) {
2208                 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, attr->name);
2209                 return -1;
2210             }
2211             bits |= 0x08;
2212             last = attr;
2213         }
2214     }
2215 
2216     /* report errors */
2217     if (last && (!(parent->schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) || !(parent->schema->flags & LYS_USERORDERED))) {
2218         /* moving attributes in wrong elements (not an user ordered list or not a list at all) */
2219         LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, last->name);
2220         return -1;
2221     } else if (bits == 3) {
2222         /* 0x01 | 0x02 - relative position, but value/key is missing */
2223         if (parent->schema->nodetype & LYS_LIST) {
2224             LOGVAL(ctx, LYE_MISSATTR, LY_VLOG_LYD, parent, "key", parent->schema->name);
2225         } else { /* LYS_LEAFLIST */
2226             LOGVAL(ctx, LYE_MISSATTR, LY_VLOG_LYD, parent, "value", parent->schema->name);
2227         }
2228         return -1;
2229     } else if ((bits & (0x04 | 0x08)) && !(bits & 0x02)) {
2230         /* key/value without relative position */
2231         LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, (bits & 0x04) ? "value" : "key");
2232         return -1;
2233     } else if ((bits & 0x21) == 0x21) {
2234         /* insert in delete/remove */
2235         LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, "insert");
2236         return -1;
2237     }
2238 
2239     if (editbits) {
2240         *editbits = bits;
2241     }
2242     return 0;
2243 }
2244 
2245 /* does not log */
2246 static int
dup_identity_check(const char * id,struct lys_ident * ident,uint32_t size)2247 dup_identity_check(const char *id, struct lys_ident *ident, uint32_t size)
2248 {
2249     uint32_t i;
2250 
2251     for (i = 0; i < size; i++) {
2252         if (ly_strequal(id, ident[i].name, 1)) {
2253             /* name collision */
2254             return EXIT_FAILURE;
2255         }
2256     }
2257 
2258     return EXIT_SUCCESS;
2259 }
2260 
2261 int
dup_identities_check(const char * id,struct lys_module * module)2262 dup_identities_check(const char *id, struct lys_module *module)
2263 {
2264     struct lys_module *mainmod;
2265     int i;
2266 
2267     if (dup_identity_check(id, module->ident, module->ident_size)) {
2268         LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "identity", id);
2269         return EXIT_FAILURE;
2270     }
2271 
2272     /* check identity in submodules */
2273     mainmod = lys_main_module(module);
2274     for (i = 0; i < mainmod->inc_size && mainmod->inc[i].submodule; ++i) {
2275         if (dup_identity_check(id, mainmod->inc[i].submodule->ident, mainmod->inc[i].submodule->ident_size)) {
2276             LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "identity", id);
2277             return EXIT_FAILURE;
2278         }
2279     }
2280 
2281     return EXIT_SUCCESS;
2282 }
2283 
2284 /* does not log */
2285 int
dup_typedef_check(const char * type,struct lys_tpdf * tpdf,int size)2286 dup_typedef_check(const char *type, struct lys_tpdf *tpdf, int size)
2287 {
2288     int i;
2289 
2290     for (i = 0; i < size; i++) {
2291         if (!strcmp(type, tpdf[i].name)) {
2292             /* name collision */
2293             return EXIT_FAILURE;
2294         }
2295     }
2296 
2297     return EXIT_SUCCESS;
2298 }
2299 
2300 /* does not log */
2301 static int
dup_feature_check(const char * id,struct lys_module * module)2302 dup_feature_check(const char *id, struct lys_module *module)
2303 {
2304     int i;
2305 
2306     for (i = 0; i < module->features_size; i++) {
2307         if (!strcmp(id, module->features[i].name)) {
2308             return EXIT_FAILURE;
2309         }
2310     }
2311 
2312     return EXIT_SUCCESS;
2313 }
2314 
2315 /* does not log */
2316 static int
dup_prefix_check(const char * prefix,struct lys_module * module)2317 dup_prefix_check(const char *prefix, struct lys_module *module)
2318 {
2319     int i;
2320 
2321     if (module->prefix && !strcmp(module->prefix, prefix)) {
2322         return EXIT_FAILURE;
2323     }
2324     for (i = 0; i < module->imp_size; i++) {
2325         if (!strcmp(module->imp[i].prefix, prefix)) {
2326             return EXIT_FAILURE;
2327         }
2328     }
2329 
2330     return EXIT_SUCCESS;
2331 }
2332 
2333 /* logs directly */
2334 int
lyp_check_identifier(struct ly_ctx * ctx,const char * id,enum LY_IDENT type,struct lys_module * module,struct lys_node * parent)2335 lyp_check_identifier(struct ly_ctx *ctx, const char *id, enum LY_IDENT type, struct lys_module *module,
2336                      struct lys_node *parent)
2337 {
2338     int i, j;
2339     int size;
2340     struct lys_tpdf *tpdf;
2341     struct lys_node *node;
2342     struct lys_module *mainmod;
2343     struct lys_submodule *submod;
2344 
2345     assert(ctx && id);
2346 
2347     /* check id syntax */
2348     if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
2349         LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "invalid start character");
2350         return EXIT_FAILURE;
2351     }
2352     for (i = 1; id[i]; i++) {
2353         if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
2354                 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
2355             LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "invalid character");
2356             return EXIT_FAILURE;
2357         }
2358     }
2359 
2360     if (i > 64) {
2361         LOGWRN(ctx, "Identifier \"%s\" is long, you should use something shorter.", id);
2362     }
2363 
2364     switch (type) {
2365     case LY_IDENT_NAME:
2366         /* check uniqueness of the node within its siblings */
2367         if (!parent) {
2368             break;
2369         }
2370 
2371         LY_TREE_FOR(parent->child, node) {
2372             if (ly_strequal(node->name, id, 1)) {
2373                 LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "name duplication");
2374                 return EXIT_FAILURE;
2375             }
2376         }
2377         break;
2378     case LY_IDENT_TYPE:
2379         assert(module);
2380         mainmod = lys_main_module(module);
2381 
2382         /* check collision with the built-in types */
2383         if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
2384                 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
2385                 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
2386                 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
2387                 !strcmp(id, "int8") || !strcmp(id, "int16") ||
2388                 !strcmp(id, "int32") || !strcmp(id, "int64") ||
2389                 !strcmp(id, "leafref") || !strcmp(id, "string") ||
2390                 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
2391                 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
2392             LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, id, "typedef");
2393             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Typedef name duplicates a built-in type.");
2394             return EXIT_FAILURE;
2395         }
2396 
2397         /* check locally scoped typedefs (avoid name shadowing) */
2398         for (; parent; parent = lys_parent(parent)) {
2399             switch (parent->nodetype) {
2400             case LYS_CONTAINER:
2401                 size = ((struct lys_node_container *)parent)->tpdf_size;
2402                 tpdf = ((struct lys_node_container *)parent)->tpdf;
2403                 break;
2404             case LYS_LIST:
2405                 size = ((struct lys_node_list *)parent)->tpdf_size;
2406                 tpdf = ((struct lys_node_list *)parent)->tpdf;
2407                 break;
2408             case LYS_GROUPING:
2409                 size = ((struct lys_node_grp *)parent)->tpdf_size;
2410                 tpdf = ((struct lys_node_grp *)parent)->tpdf;
2411                 break;
2412             default:
2413                 continue;
2414             }
2415 
2416             if (dup_typedef_check(id, tpdf, size)) {
2417                 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
2418                 return EXIT_FAILURE;
2419             }
2420         }
2421 
2422         /* check top-level names */
2423         if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
2424             LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
2425             return EXIT_FAILURE;
2426         }
2427 
2428         /* check submodule's top-level names */
2429         for (i = 0; i < mainmod->inc_size && mainmod->inc[i].submodule; i++) {
2430             if (dup_typedef_check(id, mainmod->inc[i].submodule->tpdf, mainmod->inc[i].submodule->tpdf_size)) {
2431                 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
2432                 return EXIT_FAILURE;
2433             }
2434         }
2435 
2436         break;
2437     case LY_IDENT_PREFIX:
2438         assert(module);
2439 
2440         /* check the module itself */
2441         if (dup_prefix_check(id, module)) {
2442             LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "prefix", id);
2443             return EXIT_FAILURE;
2444         }
2445         break;
2446     case LY_IDENT_FEATURE:
2447         assert(module);
2448         mainmod = lys_main_module(module);
2449 
2450         /* check feature name uniqueness*/
2451         /* check features in the current module */
2452         if (dup_feature_check(id, module)) {
2453             LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "feature", id);
2454             return EXIT_FAILURE;
2455         }
2456 
2457         /* and all its submodules */
2458         for (i = 0; i < mainmod->inc_size && mainmod->inc[i].submodule; i++) {
2459             if (dup_feature_check(id, (struct lys_module *)mainmod->inc[i].submodule)) {
2460                 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "feature", id);
2461                 return EXIT_FAILURE;
2462             }
2463         }
2464         break;
2465 
2466     case LY_IDENT_EXTENSION:
2467         assert(module);
2468         mainmod = lys_main_module(module);
2469 
2470         /* check extension name uniqueness in the main module ... */
2471         for (i = 0; i < mainmod->extensions_size; i++) {
2472             if (ly_strequal(id, mainmod->extensions[i].name, 1)) {
2473                 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "extension", id);
2474                 return EXIT_FAILURE;
2475             }
2476         }
2477 
2478         /* ... and all its submodules */
2479         for (j = 0; j < mainmod->inc_size && mainmod->inc[j].submodule; j++) {
2480             submod = mainmod->inc[j].submodule; /* shortcut */
2481             for (i = 0; i < submod->extensions_size; i++) {
2482                 if (ly_strequal(id, submod->extensions[i].name, 1)) {
2483                     LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "extension", id);
2484                     return EXIT_FAILURE;
2485                 }
2486             }
2487         }
2488 
2489         break;
2490 
2491     default:
2492         /* no check required */
2493         break;
2494     }
2495 
2496     return EXIT_SUCCESS;
2497 }
2498 
2499 /* logs directly */
2500 int
lyp_check_date(struct ly_ctx * ctx,const char * date)2501 lyp_check_date(struct ly_ctx *ctx, const char *date)
2502 {
2503     int i;
2504     struct tm tm, tm_;
2505     time_t t;
2506     char *r;
2507 
2508     assert(date);
2509 
2510     /* check format */
2511     for (i = 0; i < LY_REV_SIZE - 1; i++) {
2512         if (i == 4 || i == 7) {
2513             if (date[i] != '-') {
2514                 goto error;
2515             }
2516         } else if (!isdigit(date[i])) {
2517             goto error;
2518         }
2519     }
2520 
2521     /* pre-fill tm with valid data */
2522     t = time(NULL);
2523     localtime_r(&t, &tm);
2524 
2525     /* check content, e.g. 2018-02-31 */
2526     r = strptime(date, "%Y-%m-%d", &tm);
2527     if (!r || r != &date[LY_REV_SIZE - 1]) {
2528         goto error;
2529     }
2530 
2531     memcpy(&tm_, &tm, sizeof tm);
2532     tm_.tm_isdst = -1; /* mktime corrects DST mismatches, this stops it from doing that */
2533     mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
2534     if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
2535         /* checking days is enough, since other errors
2536          * have been checked by strptime() */
2537         goto error;
2538     }
2539 
2540     return EXIT_SUCCESS;
2541 
2542 error:
2543     LOGVAL(ctx, LYE_INDATE, LY_VLOG_NONE, NULL, date);
2544     return EXIT_FAILURE;
2545 }
2546 
2547 /**
2548  * @return
2549  * NULL - success
2550  * root - not yet resolvable
2551  * other node - mandatory node under the root
2552  */
2553 static const struct lys_node *
lyp_check_mandatory_(const struct lys_node * root)2554 lyp_check_mandatory_(const struct lys_node *root)
2555 {
2556     int mand_flag = 0;
2557     const struct lys_node *iter = NULL;
2558 
2559     while ((iter = lys_getnext(iter, root, NULL, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHUSES | LYS_GETNEXT_INTOUSES
2560             | LYS_GETNEXT_INTONPCONT | LYS_GETNEXT_NOSTATECHECK))) {
2561         if (iter->nodetype == LYS_USES) {
2562             if (!((struct lys_node_uses *)iter)->grp) {
2563                 /* not yet resolved uses */
2564                 return root;
2565             } else {
2566                 /* go into uses */
2567                 continue;
2568             }
2569         }
2570         if (iter->nodetype == LYS_CHOICE) {
2571             /* skip it, it was already checked for direct mandatory node in default */
2572             continue;
2573         }
2574         if (iter->nodetype == LYS_LIST) {
2575             if (((struct lys_node_list *)iter)->min) {
2576                 mand_flag = 1;
2577             }
2578         } else if (iter->nodetype == LYS_LEAFLIST) {
2579             if (((struct lys_node_leaflist *)iter)->min) {
2580                 mand_flag = 1;
2581             }
2582         } else if (iter->flags & LYS_MAND_TRUE) {
2583             mand_flag = 1;
2584         }
2585 
2586         if (mand_flag) {
2587             return iter;
2588         }
2589     }
2590 
2591     return NULL;
2592 }
2593 
2594 /* logs directly */
2595 int
lyp_check_mandatory_augment(struct lys_node_augment * aug,const struct lys_node * target)2596 lyp_check_mandatory_augment(struct lys_node_augment *aug, const struct lys_node *target)
2597 {
2598     const struct lys_node *node;
2599 
2600     if (aug->when || target->nodetype == LYS_CHOICE) {
2601         /* - mandatory nodes in new cases are ok;
2602          * clarification from YANG 1.1 - augmentation can add mandatory nodes when it is
2603          * conditional with a when statement */
2604         return EXIT_SUCCESS;
2605     }
2606 
2607     if ((node = lyp_check_mandatory_((struct lys_node *)aug))) {
2608         if (node != (struct lys_node *)aug) {
2609             LOGVAL(target->module->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2610             LOGVAL(target->module->ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
2611                    "Mandatory node \"%s\" appears in augment of \"%s\" without when condition.",
2612                    node->name, aug->target_name);
2613             return -1;
2614         }
2615         return EXIT_FAILURE;
2616     }
2617 
2618     return EXIT_SUCCESS;
2619 }
2620 
2621 /**
2622  * @brief check that a mandatory node is not directly under the default case.
2623  * @param[in] node choice with default node
2624  * @return EXIT_SUCCESS if the constraint is fulfilled, EXIT_FAILURE otherwise
2625  */
2626 int
lyp_check_mandatory_choice(struct lys_node * node)2627 lyp_check_mandatory_choice(struct lys_node *node)
2628 {
2629     const struct lys_node *mand, *dflt = ((struct lys_node_choice *)node)->dflt;
2630 
2631     if ((mand = lyp_check_mandatory_(dflt))) {
2632         if (mand != dflt) {
2633             LOGVAL(node->module->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2634             LOGVAL(node->module->ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
2635                    "Mandatory node \"%s\" is directly under the default case \"%s\" of the \"%s\" choice.",
2636                    mand->name, dflt->name, node->name);
2637             return -1;
2638         }
2639         return EXIT_FAILURE;
2640     }
2641 
2642     return EXIT_SUCCESS;
2643 }
2644 
2645 /**
2646  * @brief Check status for invalid combination.
2647  *
2648  * @param[in] flags1 Flags of the referencing node.
2649  * @param[in] mod1 Module of the referencing node,
2650  * @param[in] name1 Schema node name of the referencing node.
2651  * @param[in] flags2 Flags of the referenced node.
2652  * @param[in] mod2 Module of the referenced node,
2653  * @param[in] name2 Schema node name of the referenced node.
2654  * @return EXIT_SUCCES on success, EXIT_FAILURE on invalid reference.
2655  */
2656 int
lyp_check_status(uint16_t flags1,struct lys_module * mod1,const char * name1,uint16_t flags2,struct lys_module * mod2,const char * name2,const struct lys_node * node)2657 lyp_check_status(uint16_t flags1, struct lys_module *mod1, const char *name1,
2658                  uint16_t flags2, struct lys_module *mod2, const char *name2,
2659                  const struct lys_node *node)
2660 {
2661     uint16_t flg1, flg2;
2662 
2663     flg1 = (flags1 & LYS_STATUS_MASK) ? (flags1 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
2664     flg2 = (flags2 & LYS_STATUS_MASK) ? (flags2 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
2665 
2666     if ((flg1 < flg2) && (lys_main_module(mod1) == lys_main_module(mod2))) {
2667         LOGVAL(mod1->ctx, LYE_INSTATUS, node ? LY_VLOG_LYS : LY_VLOG_NONE, node,
2668                flg1 == LYS_STATUS_CURR ? "current" : "deprecated", name1, "references",
2669                flg2 == LYS_STATUS_OBSLT ? "obsolete" : "deprecated", name2);
2670         return EXIT_FAILURE;
2671     }
2672 
2673     return EXIT_SUCCESS;
2674 }
2675 
2676 void
lyp_del_includedup(struct lys_module * mod,int free_subs)2677 lyp_del_includedup(struct lys_module *mod, int free_subs)
2678 {
2679     struct ly_modules_list *models = &mod->ctx->models;
2680     uint8_t i;
2681 
2682     assert(mod && !mod->type);
2683 
2684     if (models->parsed_submodules_count) {
2685         for (i = models->parsed_submodules_count - 1; models->parsed_submodules[i]->type; --i);
2686         if (models->parsed_submodules[i] == mod) {
2687             if (free_subs) {
2688                 for (i = models->parsed_submodules_count - 1; models->parsed_submodules[i]->type; --i) {
2689                     lys_sub_module_remove_devs_augs((struct lys_module *)models->parsed_submodules[i]);
2690                     lys_submodule_module_data_free((struct lys_submodule *)models->parsed_submodules[i]);
2691                     lys_submodule_free((struct lys_submodule *)models->parsed_submodules[i], NULL);
2692                 }
2693             }
2694 
2695             models->parsed_submodules_count = i;
2696             if (!models->parsed_submodules_count) {
2697                 free(models->parsed_submodules);
2698                 models->parsed_submodules = NULL;
2699             }
2700         }
2701     }
2702 }
2703 
2704 static void
lyp_add_includedup(struct lys_module * sub_mod,struct lys_submodule * parsed_submod)2705 lyp_add_includedup(struct lys_module *sub_mod, struct lys_submodule *parsed_submod)
2706 {
2707     struct ly_modules_list *models = &sub_mod->ctx->models;
2708     int16_t i;
2709 
2710     /* store main module if first include */
2711     if (models->parsed_submodules_count) {
2712         for (i = models->parsed_submodules_count - 1; models->parsed_submodules[i]->type; --i);
2713     } else {
2714         i = -1;
2715     }
2716     if ((i == -1) || (models->parsed_submodules[i] != lys_main_module(sub_mod))) {
2717         ++models->parsed_submodules_count;
2718         models->parsed_submodules = ly_realloc(models->parsed_submodules,
2719                                                models->parsed_submodules_count * sizeof *models->parsed_submodules);
2720         LY_CHECK_ERR_RETURN(!models->parsed_submodules, LOGMEM(sub_mod->ctx), );
2721         models->parsed_submodules[models->parsed_submodules_count - 1] = lys_main_module(sub_mod);
2722     }
2723 
2724     /* store parsed submodule */
2725     ++models->parsed_submodules_count;
2726     models->parsed_submodules = ly_realloc(models->parsed_submodules,
2727                                            models->parsed_submodules_count * sizeof *models->parsed_submodules);
2728     LY_CHECK_ERR_RETURN(!models->parsed_submodules, LOGMEM(sub_mod->ctx), );
2729     models->parsed_submodules[models->parsed_submodules_count - 1] = (struct lys_module *)parsed_submod;
2730 }
2731 
2732 /*
2733  * types: 0 - include, 1 - import
2734  */
2735 static int
lyp_check_circmod(struct lys_module * module,const char * value,int type)2736 lyp_check_circmod(struct lys_module *module, const char *value, int type)
2737 {
2738     LY_ECODE code = type ? LYE_CIRC_IMPORTS : LYE_CIRC_INCLUDES;
2739     struct ly_modules_list *models = &module->ctx->models;
2740     uint8_t i;
2741 
2742     /* include/import itself */
2743     if (ly_strequal(module->name, value, 1)) {
2744         LOGVAL(module->ctx, code, LY_VLOG_NONE, NULL, value);
2745         return -1;
2746     }
2747 
2748     /* currently parsed modules */
2749     for (i = 0; i < models->parsing_sub_modules_count; i++) {
2750         if (ly_strequal(models->parsing_sub_modules[i]->name, value, 1)) {
2751             LOGVAL(module->ctx, code, LY_VLOG_NONE, NULL, value);
2752             return -1;
2753         }
2754     }
2755 
2756     return 0;
2757 }
2758 
2759 int
lyp_check_circmod_add(struct lys_module * module)2760 lyp_check_circmod_add(struct lys_module *module)
2761 {
2762     struct ly_modules_list *models = &module->ctx->models;
2763 
2764     /* storing - enlarge the list of modules being currently parsed */
2765     ++models->parsing_sub_modules_count;
2766     models->parsing_sub_modules = ly_realloc(models->parsing_sub_modules,
2767                                              models->parsing_sub_modules_count * sizeof *models->parsing_sub_modules);
2768     LY_CHECK_ERR_RETURN(!models->parsing_sub_modules, LOGMEM(module->ctx), -1);
2769     models->parsing_sub_modules[models->parsing_sub_modules_count - 1] = module;
2770 
2771     return 0;
2772 }
2773 
2774 void
lyp_check_circmod_pop(struct ly_ctx * ctx)2775 lyp_check_circmod_pop(struct ly_ctx *ctx)
2776 {
2777     if (!ctx->models.parsing_sub_modules_count) {
2778         LOGINT(ctx);
2779         return;
2780     }
2781 
2782     /* update the list of currently being parsed modules */
2783     ctx->models.parsing_sub_modules_count--;
2784     if (!ctx->models.parsing_sub_modules_count) {
2785         free(ctx->models.parsing_sub_modules);
2786         ctx->models.parsing_sub_modules = NULL;
2787     }
2788 }
2789 
2790 /*
2791  * -1 - error - invalid duplicities)
2792  *  0 - success, no duplicity
2793  *  1 - success, valid duplicity found and stored in *sub
2794  */
2795 static int
lyp_check_includedup(struct lys_module * mod,const char * name,struct lys_include * inc,struct lys_submodule ** sub)2796 lyp_check_includedup(struct lys_module *mod, const char *name, struct lys_include *inc, struct lys_submodule **sub)
2797 {
2798     struct lys_module **parsed_sub = mod->ctx->models.parsed_submodules;
2799     uint8_t i, parsed_sub_count = mod->ctx->models.parsed_submodules_count;
2800 
2801     assert(sub);
2802 
2803     for (i = 0; i < mod->inc_size; ++i) {
2804         if (ly_strequal(mod->inc[i].submodule->name, name, 1)) {
2805             /* the same module is already included in the same module - error */
2806             LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "include");
2807             LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Submodule \"%s\" included twice in the same module \"%s\".",
2808                    name, mod->name);
2809             return -1;
2810         }
2811     }
2812 
2813     if (parsed_sub_count) {
2814         assert(!parsed_sub[0]->type);
2815         for (i = parsed_sub_count - 1; parsed_sub[i]->type; --i) {
2816             if (ly_strequal(parsed_sub[i]->name, name, 1)) {
2817                 /* check revisions, including multiple revisions of a single module is error */
2818                 if (inc->rev[0] && (!parsed_sub[i]->rev_size || strcmp(parsed_sub[i]->rev[0].date, inc->rev))) {
2819                     /* the already included submodule has
2820                      * - no revision, but here we require some
2821                      * - different revision than the one required here */
2822                     LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "include");
2823                     LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Including multiple revisions of submodule \"%s\".", name);
2824                     return -1;
2825                 }
2826 
2827                 /* the same module is already included in some other submodule, return it */
2828                 (*sub) = (struct lys_submodule *)parsed_sub[i];
2829                 return 1;
2830             }
2831         }
2832     }
2833 
2834     /* no duplicity found */
2835     return 0;
2836 }
2837 
2838 /* returns:
2839  *  0 - inc successfully filled
2840  * -1 - error
2841  */
2842 int
lyp_check_include(struct lys_module * module,const char * value,struct lys_include * inc,struct unres_schema * unres)2843 lyp_check_include(struct lys_module *module, const char *value, struct lys_include *inc, struct unres_schema *unres)
2844 {
2845     int i;
2846 
2847     /* check that the submodule was not included yet */
2848     i = lyp_check_includedup(module, value, inc, &inc->submodule);
2849     if (i == -1) {
2850         return -1;
2851     } else if (i == 1) {
2852         return 0;
2853     }
2854     /* submodule is not yet loaded */
2855 
2856     /* circular include check */
2857     if (lyp_check_circmod(module, value, 0)) {
2858         return -1;
2859     }
2860 
2861     /* try to load the submodule */
2862     inc->submodule = (struct lys_submodule *)ly_ctx_load_sub_module(module->ctx, module, value,
2863                                                                     inc->rev[0] ? inc->rev : NULL, 1, unres);
2864 
2865     /* check the result */
2866     if (!inc->submodule) {
2867         if (ly_errno != LY_EVALID) {
2868             LOGVAL(module->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "include");
2869         }
2870         LOGERR(module->ctx, LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2871         return -1;
2872     }
2873 
2874     /* check the revision */
2875     if (inc->rev[0] && inc->submodule->rev_size && strcmp(inc->rev, inc->submodule->rev[0].date)) {
2876         LOGERR(module->ctx, LY_EVALID, "\"%s\" include of submodule \"%s\" in revision \"%s\" not found.",
2877                module->name, value, inc->rev);
2878         unres_schema_free((struct lys_module *)inc->submodule, &unres, 0);
2879         lys_sub_module_remove_devs_augs((struct lys_module *)inc->submodule);
2880         lys_submodule_module_data_free((struct lys_submodule *)inc->submodule);
2881         lys_submodule_free(inc->submodule, NULL);
2882         inc->submodule = NULL;
2883         return -1;
2884     }
2885 
2886     /* store the submodule as successfully parsed */
2887     lyp_add_includedup(module, inc->submodule);
2888 
2889     return 0;
2890 }
2891 
2892 static int
lyp_check_include_missing_recursive(struct lys_module * main_module,struct lys_submodule * sub)2893 lyp_check_include_missing_recursive(struct lys_module *main_module, struct lys_submodule *sub)
2894 {
2895     uint8_t i, j;
2896     void *reallocated;
2897     int ret = 0, tmp;
2898     struct ly_ctx *ctx = main_module->ctx;
2899 
2900     for (i = 0; i < sub->inc_size; i++) {
2901         /* check that the include is also present in the main module */
2902         for (j = 0; j < main_module->inc_size; j++) {
2903             if (main_module->inc[j].submodule == sub->inc[i].submodule) {
2904                 break;
2905             }
2906         }
2907 
2908         if (j == main_module->inc_size) {
2909             /* match not found */
2910             if (main_module->version >= LYS_VERSION_1_1) {
2911                 LOGVAL(ctx, LYE_MISSSTMT, LY_VLOG_NONE, NULL, "include");
2912                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
2913                        "The main module \"%s\" misses include of the \"%s\" submodule used in another submodule \"%s\".",
2914                        main_module->name, sub->inc[i].submodule->name, sub->name);
2915                 /* now we should return error, but due to the issues with freeing the module, we actually have
2916                  * to go through the all includes and, as in case of 1.0, add them into the main module and fail
2917                  * at the end when all the includes are in the main module and we can free them */
2918                 ret = 1;
2919             } else {
2920                 /* not strictly an error in YANG 1.0 */
2921                 LOGWRN(ctx, "The main module \"%s\" misses include of the \"%s\" submodule used in another submodule \"%s\".",
2922                        main_module->name, sub->inc[i].submodule->name, sub->name);
2923                 LOGWRN(ctx, "To avoid further issues, adding submodule \"%s\" into the main module \"%s\".",
2924                        sub->inc[i].submodule->name, main_module->name);
2925                 /* but since it is a good practise and because we expect all the includes in the main module
2926                  * when searching it and also when freeing the module, put it into it */
2927             }
2928             main_module->inc_size++;
2929             reallocated = realloc(main_module->inc, main_module->inc_size * sizeof *main_module->inc);
2930             LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx), 1);
2931             main_module->inc = reallocated;
2932             memset(&main_module->inc[main_module->inc_size - 1], 0, sizeof *main_module->inc);
2933             /* to avoid unexpected consequences, copy just a link to the submodule and the revision,
2934              * all other substatements of the include are ignored */
2935             memcpy(&main_module->inc[main_module->inc_size - 1].rev, sub->inc[i].rev, LY_REV_SIZE - 1);
2936             main_module->inc[main_module->inc_size - 1].submodule = sub->inc[i].submodule;
2937         }
2938 
2939         /* recursion */
2940         tmp = lyp_check_include_missing_recursive(main_module, sub->inc[i].submodule);
2941         if (!ret && tmp) {
2942             ret = 1;
2943         }
2944     }
2945 
2946     return ret;
2947 }
2948 
2949 int
lyp_check_include_missing(struct lys_module * main_module)2950 lyp_check_include_missing(struct lys_module *main_module)
2951 {
2952     int ret = 0;
2953     uint8_t i;
2954 
2955     /* in YANG 1.1, all the submodules must be in the main module, check it even for
2956      * 1.0 where it will be printed as warning and the include will be added into the main module */
2957     for (i = 0; i < main_module->inc_size; i++) {
2958         if (lyp_check_include_missing_recursive(main_module, main_module->inc[i].submodule)) {
2959             ret = 1;
2960         }
2961     }
2962 
2963     return ret;
2964 }
2965 
2966 /* returns:
2967  *  0 - imp successfully filled
2968  * -1 - error, imp not cleaned
2969  */
2970 int
lyp_check_import(struct lys_module * module,const char * value,struct lys_import * imp)2971 lyp_check_import(struct lys_module *module, const char *value, struct lys_import *imp)
2972 {
2973     int i;
2974     struct lys_module *dup = NULL;
2975     struct ly_ctx *ctx = module->ctx;
2976 
2977     /* check for importing a single module in multiple revisions */
2978     for (i = 0; i < module->imp_size; i++) {
2979         if (!module->imp[i].module) {
2980             /* skip the not yet filled records */
2981             continue;
2982         }
2983         if (ly_strequal(module->imp[i].module->name, value, 1)) {
2984             /* check revisions, including multiple revisions of a single module is error */
2985             if (imp->rev[0] && (!module->imp[i].module->rev_size || strcmp(module->imp[i].module->rev[0].date, imp->rev))) {
2986                 /* the already imported module has
2987                  * - no revision, but here we require some
2988                  * - different revision than the one required here */
2989                 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "import");
2990                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Importing multiple revisions of module \"%s\".", value);
2991                 return -1;
2992             } else if (!imp->rev[0]) {
2993                 /* no revision, remember the duplication, but check revisions after loading the module
2994                  * because the current revision can be the same (then it is ok) or it can differ (then it
2995                  * is error */
2996                 dup = module->imp[i].module;
2997                 break;
2998             }
2999 
3000             /* there is duplication, but since prefixes differs (checked in caller of this function),
3001              * it is ok */
3002             imp->module = module->imp[i].module;
3003             return 0;
3004         }
3005     }
3006 
3007     /* circular import check */
3008     if (lyp_check_circmod(module, value, 1)) {
3009         return -1;
3010     }
3011 
3012     /* load module - in specific situations it tries to get the module from the context */
3013     imp->module = (struct lys_module *)ly_ctx_load_sub_module(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL,
3014                                                               module->ctx->models.flags & LY_CTX_ALLIMPLEMENTED ? 1 : 0,
3015                                                               NULL);
3016 
3017     /* check the result */
3018     if (!imp->module) {
3019         LOGERR(ctx, LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
3020         return -1;
3021     }
3022 
3023     if (imp->rev[0] && imp->module->rev_size && strcmp(imp->rev, imp->module->rev[0].date)) {
3024         LOGERR(ctx, LY_EVALID, "\"%s\" import of module \"%s\" in revision \"%s\" not found.",
3025                module->name, value, imp->rev);
3026         return -1;
3027     }
3028 
3029     if ((module->version < 2) && imp->rev[0] && (imp->module->version == 2)) {
3030         LOGERR(ctx, LY_EVALID, "YANG 1.0 module \"%s\" import with revision of YANG 1.1 module \"%s\".",
3031                module->name, imp->module->name);
3032         return -1;
3033     }
3034 
3035     if (dup) {
3036         /* check the revisions */
3037         if ((dup != imp->module) ||
3038                 (dup->rev_size != imp->module->rev_size && (!dup->rev_size || imp->module->rev_size)) ||
3039                 (dup->rev_size && strcmp(dup->rev[0].date, imp->module->rev[0].date))) {
3040             /* - modules are not the same
3041              * - one of modules has no revision (except they both has no revision)
3042              * - revisions of the modules are not the same */
3043             LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "import");
3044             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Importing multiple revisions of module \"%s\".", value);
3045             return -1;
3046         } else {
3047             LOGWRN(ctx, "Module \"%s\" is imported by \"%s\" multiple times with different prefixes.", dup->name, module->name);
3048         }
3049     }
3050 
3051     return 0;
3052 }
3053 
3054 /*
3055  * put the newest revision to the first position
3056  */
3057 void
lyp_sort_revisions(struct lys_module * module)3058 lyp_sort_revisions(struct lys_module *module)
3059 {
3060     uint8_t i, r;
3061     struct lys_revision rev;
3062 
3063     for (i = 1, r = 0; i < module->rev_size; i++) {
3064         if (strcmp(module->rev[i].date, module->rev[r].date) > 0) {
3065             r = i;
3066         }
3067     }
3068 
3069     if (r) {
3070         /* the newest revision is not on position 0, switch them */
3071         memcpy(&rev, &module->rev[0], sizeof rev);
3072         memcpy(&module->rev[0], &module->rev[r], sizeof rev);
3073         memcpy(&module->rev[r], &rev, sizeof rev);
3074     }
3075 }
3076 
3077 void
lyp_ext_instance_rm(struct ly_ctx * ctx,struct lys_ext_instance *** ext,uint8_t * size,uint8_t index)3078 lyp_ext_instance_rm(struct ly_ctx *ctx, struct lys_ext_instance ***ext, uint8_t *size, uint8_t index)
3079 {
3080     uint8_t i;
3081 
3082     lys_extension_instances_free(ctx, (*ext)[index]->ext, (*ext)[index]->ext_size, NULL);
3083     lydict_remove(ctx, (*ext)[index]->arg_value);
3084     free((*ext)[index]);
3085 
3086     /* move the rest of the array */
3087     for (i = index + 1; i < (*size); i++) {
3088         (*ext)[i - 1] = (*ext)[i];
3089     }
3090     /* clean the last cell in the array structure */
3091     (*ext)[(*size) - 1] = NULL;
3092     /* the array is not reallocated here, just change its size */
3093     (*size) = (*size) - 1;
3094 
3095     if (!(*size)) {
3096         /* ext array is empty */
3097         free((*ext));
3098         ext = NULL;
3099     }
3100 }
3101 
3102 static int
lyp_rfn_apply_ext_(struct lys_refine * rfn,struct lys_node * target,LYEXT_SUBSTMT substmt,struct lys_ext * extdef)3103 lyp_rfn_apply_ext_(struct lys_refine *rfn, struct lys_node *target, LYEXT_SUBSTMT substmt, struct lys_ext *extdef)
3104 {
3105     struct ly_ctx *ctx;
3106     int m, n;
3107     struct lys_ext_instance *new;
3108     void *reallocated;
3109 
3110     ctx = target->module->ctx; /* shortcut */
3111 
3112     m = n = -1;
3113     while ((m = lys_ext_iter(rfn->ext, rfn->ext_size, m + 1, substmt)) != -1) {
3114         /* refine's substatement includes extensions, copy them to the target, replacing the previous
3115          * substatement's extensions if any. In case of refining the extension itself, we are going to
3116          * replace only the same extension (pointing to the same definition) */
3117         if (substmt == LYEXT_SUBSTMT_SELF && rfn->ext[m]->def != extdef) {
3118             continue;
3119         }
3120 
3121         /* get the index of the extension to replace in the target node */
3122         do {
3123             n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt);
3124         } while (n != -1 && substmt == LYEXT_SUBSTMT_SELF && target->ext[n]->def != extdef);
3125 
3126         /* TODO cover complex extension instances */
3127         if (n == -1) {
3128             /* nothing to replace, we are going to add it - reallocate */
3129             new = malloc(sizeof **target->ext);
3130             LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3131             reallocated = realloc(target->ext, (target->ext_size + 1) * sizeof *target->ext);
3132             LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx); free(new), EXIT_FAILURE);
3133             target->ext = reallocated;
3134             target->ext_size++;
3135 
3136             /* init */
3137             n = target->ext_size - 1;
3138             target->ext[n] = new;
3139             target->ext[n]->parent = target;
3140             target->ext[n]->parent_type = LYEXT_PAR_NODE;
3141             target->ext[n]->flags = 0;
3142             target->ext[n]->insubstmt = substmt;
3143             target->ext[n]->priv = NULL;
3144             target->ext[n]->nodetype = LYS_EXT;
3145             target->ext[n]->module = target->module;
3146         } else {
3147             /* replacing - first remove the allocated data from target */
3148             lys_extension_instances_free(ctx, target->ext[n]->ext, target->ext[n]->ext_size, NULL);
3149             lydict_remove(ctx, target->ext[n]->arg_value);
3150         }
3151         /* common part for adding and replacing */
3152         target->ext[n]->def = rfn->ext[m]->def;
3153         /* parent and parent_type do not change */
3154         target->ext[n]->arg_value = lydict_insert(ctx, rfn->ext[m]->arg_value, 0);
3155         /* flags do not change */
3156         target->ext[n]->ext_size = rfn->ext[m]->ext_size;
3157         lys_ext_dup(ctx, target->module, rfn->ext[m]->ext, rfn->ext[m]->ext_size, target, LYEXT_PAR_NODE,
3158                     &target->ext[n]->ext, 0, NULL);
3159         /* substmt does not change, but the index must be taken from the refine */
3160         target->ext[n]->insubstmt_index = rfn->ext[m]->insubstmt_index;
3161     }
3162 
3163     /* remove the rest of extensions belonging to the original substatement in the target node */
3164     while ((n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt)) != -1) {
3165         if (substmt == LYEXT_SUBSTMT_SELF && target->ext[n]->def != extdef) {
3166             /* keep this extension */
3167             continue;
3168         }
3169 
3170         /* remove the item */
3171         lyp_ext_instance_rm(ctx, &target->ext, &target->ext_size, n);
3172         --n;
3173     }
3174 
3175     return EXIT_SUCCESS;
3176 }
3177 
3178 /*
3179  * apply extension instances defined under refine's substatements.
3180  * It cannot be done immediately when applying the refine because there can be
3181  * still unresolved data (e.g. type) and mainly the targeted extension instances.
3182  */
3183 int
lyp_rfn_apply_ext(struct lys_module * module)3184 lyp_rfn_apply_ext(struct lys_module *module)
3185 {
3186     int i, k, a = 0;
3187     struct lys_node *root, *nextroot, *next, *node;
3188     struct lys_node *target;
3189     struct lys_node_uses *uses;
3190     struct lys_refine *rfn;
3191     struct ly_set *extset;
3192 
3193     /* refines in uses */
3194     LY_TREE_FOR_SAFE(module->data, nextroot, root) {
3195         /* go through the data tree of the module and all the defined augments */
3196 
3197         LY_TREE_DFS_BEGIN(root, next, node) {
3198             if (node->nodetype == LYS_USES) {
3199                 uses = (struct lys_node_uses *)node;
3200 
3201                 for (i = 0; i < uses->refine_size; i++) {
3202                     if (!uses->refine[i].ext_size) {
3203                         /* no extensions in refine */
3204                         continue;
3205                     }
3206                     rfn = &uses->refine[i]; /* shortcut */
3207 
3208                     /* get the target node */
3209                     target = NULL;
3210                     resolve_descendant_schema_nodeid(rfn->target_name, uses->child,
3211                                                      LYS_NO_RPC_NOTIF_NODE | LYS_ACTION | LYS_NOTIF,
3212                                                      0, (const struct lys_node **)&target);
3213                     if (!target) {
3214                         /* it should always succeed since the target_name was already resolved at least
3215                          * once when the refine itself was being resolved */
3216                         LOGINT(module->ctx);;
3217                         return EXIT_FAILURE;
3218                     }
3219 
3220                     /* extensions */
3221                     extset = ly_set_new();
3222                     k = -1;
3223                     while ((k = lys_ext_iter(rfn->ext, rfn->ext_size, k + 1, LYEXT_SUBSTMT_SELF)) != -1) {
3224                         ly_set_add(extset, rfn->ext[k]->def, 0);
3225                     }
3226                     for (k = 0; (unsigned int)k < extset->number; k++) {
3227                         if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_SELF, (struct lys_ext *)extset->set.g[k])) {
3228                             ly_set_free(extset);
3229                             return EXIT_FAILURE;
3230                         }
3231                     }
3232                     ly_set_free(extset);
3233 
3234                     /* description */
3235                     if (rfn->dsc && lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_DESCRIPTION, NULL)) {
3236                         return EXIT_FAILURE;
3237                     }
3238                     /* reference */
3239                     if (rfn->ref && lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_REFERENCE, NULL)) {
3240                         return EXIT_FAILURE;
3241                     }
3242                     /* config, in case of notification or rpc/action{notif, the config is not applicable
3243                      * (there is no config status) */
3244                     if ((rfn->flags & LYS_CONFIG_MASK) && (target->flags & LYS_CONFIG_MASK)) {
3245                         if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_CONFIG, NULL)) {
3246                             return EXIT_FAILURE;
3247                         }
3248                     }
3249                     /* default value */
3250                     if (rfn->dflt_size && lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_DEFAULT, NULL)) {
3251                         return EXIT_FAILURE;
3252                     }
3253                     /* mandatory */
3254                     if (rfn->flags & LYS_MAND_MASK) {
3255                         if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_MANDATORY, NULL)) {
3256                             return EXIT_FAILURE;
3257                         }
3258                     }
3259                     /* presence */
3260                     if ((target->nodetype & LYS_CONTAINER) && rfn->mod.presence) {
3261                         if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_PRESENCE, NULL)) {
3262                             return EXIT_FAILURE;
3263                         }
3264                     }
3265                     /* min/max */
3266                     if (rfn->flags & LYS_RFN_MINSET) {
3267                         if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_MIN, NULL)) {
3268                             return EXIT_FAILURE;
3269                         }
3270                     }
3271                     if (rfn->flags & LYS_RFN_MAXSET) {
3272                         if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_MAX, NULL)) {
3273                             return EXIT_FAILURE;
3274                         }
3275                     }
3276                     /* must and if-feature contain extensions on their own, not needed to be solved here */
3277 
3278                     if (target->ext_size) {
3279                         /* the allocated target's extension array can be now longer than needed in case
3280                          * there is less refine substatement's extensions than in original. Since we are
3281                          * going to reduce or keep the same memory, it is not necessary to test realloc's result */
3282                         target->ext = realloc(target->ext, target->ext_size * sizeof *target->ext);
3283                     }
3284                 }
3285             }
3286             LY_TREE_DFS_END(root, next, node)
3287         }
3288 
3289         if (!nextroot && a < module->augment_size) {
3290             nextroot = module->augment[a].child;
3291             a++;
3292         }
3293     }
3294 
3295     return EXIT_SUCCESS;
3296 }
3297 
3298 /*
3299  * check mandatory substatements defined under extension instances.
3300  */
3301 int
lyp_mand_check_ext(struct lys_ext_instance_complex * ext,const char * ext_name)3302 lyp_mand_check_ext(struct lys_ext_instance_complex *ext, const char *ext_name)
3303 {
3304     void *p;
3305     int i;
3306     struct ly_ctx *ctx = ext->module->ctx;
3307 
3308     /* check for mandatory substatements */
3309     for (i = 0; ext->substmt[i].stmt; i++) {
3310         if (ext->substmt[i].cardinality == LY_STMT_CARD_OPT || ext->substmt[i].cardinality == LY_STMT_CARD_ANY) {
3311             /* not a mandatory */
3312             continue;
3313         } else if (ext->substmt[i].cardinality == LY_STMT_CARD_SOME) {
3314             goto array;
3315         }
3316 
3317         /*
3318          * LY_STMT_ORDEREDBY - not checked, has a default value which is the same as explicit system order
3319          * LY_STMT_MODIFIER, LY_STMT_STATUS, LY_STMT_MANDATORY, LY_STMT_CONFIG - checked, but mandatory requirement
3320          * does not make sense since there is also a default value specified
3321          */
3322         switch(ext->substmt[i].stmt) {
3323         case LY_STMT_ORDEREDBY:
3324             /* always ok */
3325             break;
3326         case LY_STMT_REQINSTANCE:
3327         case LY_STMT_DIGITS:
3328         case LY_STMT_MODIFIER:
3329             p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3330             if (!*(uint8_t*)p) {
3331                 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3332                 goto error;
3333             }
3334             break;
3335         case LY_STMT_STATUS:
3336             p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3337             if (!(*(uint16_t*)p & LYS_STATUS_MASK)) {
3338                 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3339                 goto error;
3340             }
3341             break;
3342         case LY_STMT_MANDATORY:
3343             p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3344             if (!(*(uint16_t*)p & LYS_MAND_MASK)) {
3345                 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3346                 goto error;
3347             }
3348             break;
3349         case LY_STMT_CONFIG:
3350             p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3351             if (!(*(uint16_t*)p & LYS_CONFIG_MASK)) {
3352                 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3353                 goto error;
3354             }
3355             break;
3356         default:
3357 array:
3358             /* stored as a pointer */
3359             p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3360             if (!(*(void**)p)) {
3361                 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3362                 goto error;
3363             }
3364             break;
3365         }
3366     }
3367 
3368     return EXIT_SUCCESS;
3369 
3370 error:
3371     return EXIT_FAILURE;
3372 }
3373 
3374 static int
check_deviate_config(struct lys_node * node)3375 check_deviate_config(struct lys_node *node)
3376 {
3377     struct ly_ctx *ctx = node->module->ctx;
3378     struct lys_node *parent = lys_parent(node);
3379 
3380     /* from rfc7950#page-86: All key leafs in a list MUST have the same value
3381      * for their "config" as the list itself.
3382      */
3383     if (lys_is_key((struct lys_node_leaf *)node, NULL) &&
3384             ((parent->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK))) {
3385         LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
3386         LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The deviate statement causes a violation of \"config\" rules in"
3387                 " a key leaf. The \"config\" value in the key leaf must be the same as in the list to which belongs.");
3388         return EXIT_FAILURE;
3389     }
3390 
3391     /* from rfc7950#page-135: If the parent node is a case node,
3392      * the value is the same as the case node's parent choice node.
3393      */
3394     if (node->nodetype == LYS_CASE) {
3395         assert(parent && (parent->nodetype == LYS_CHOICE));
3396         if ((parent->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK)) {
3397             LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
3398             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
3399                     "The deviate statement causes a violation of \"config\" rules in a case node. "
3400                     "The \"config\" value in the case must be the same as in the choice to which belongs.");
3401             return EXIT_FAILURE;
3402         }
3403     }
3404 
3405     /* from rfc7950#page-135: If a node has "config" set to "false",
3406      * no node underneath it can have "config" set to "true".
3407      */
3408     if (parent && (node->flags & LYS_CONFIG_W) && (parent->flags & LYS_CONFIG_R)) {
3409         LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
3410         LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
3411                 "The deviate statement causes a violation of \"config\" nesting rules. The config for node \"%s\" is"
3412                 " \"true\" while for its parent \"%s\" is \"false\".", node->name, parent->name);
3413         return EXIT_FAILURE;
3414     }
3415 
3416     return EXIT_SUCCESS;
3417 }
3418 
3419 int
lyp_deviate_inherit_config_r(struct lys_node * node)3420 lyp_deviate_inherit_config_r(struct lys_node *node)
3421 {
3422     struct lys_node *child;
3423 
3424     /* check node */
3425     if (check_deviate_config(node)) {
3426         return EXIT_FAILURE;
3427     }
3428 
3429     /* recursive check and inherit (operations ignore config so it can be skipped) */
3430     if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
3431         LY_TREE_FOR(node->child, child) {
3432             if (child->flags & LYS_CONFIG_SET) {
3433                 /* keep the explicit config, but check it is fine because it may depend on the parent config */
3434                 if (check_deviate_config(child)) {
3435                     return EXIT_FAILURE;
3436                 }
3437             } else {
3438                 /* inherit config from the parent */
3439                 child->flags &= ~LYS_CONFIG_MASK;
3440                 child->flags |= (node->flags & LYS_CONFIG_MASK);
3441 
3442                 /* recursive call */
3443                 if (lyp_deviate_inherit_config_r(child)) {
3444                     return EXIT_FAILURE;
3445                 }
3446             }
3447         }
3448     }
3449 
3450     return EXIT_SUCCESS;
3451 }
3452 
3453 static int
lyp_deviate_del_ext(struct lys_node * target,struct lys_ext_instance * ext)3454 lyp_deviate_del_ext(struct lys_node *target, struct lys_ext_instance *ext)
3455 {
3456     int n = -1, found = 0;
3457     char *path;
3458 
3459     while ((n = lys_ext_iter(target->ext, target->ext_size, n + 1, ext->insubstmt)) != -1) {
3460         if (target->ext[n]->def != ext->def) {
3461             continue;
3462         }
3463 
3464         if (ext->def->argument) {
3465             /* check matching arguments */
3466             if (!ly_strequal(target->ext[n]->arg_value, ext->arg_value, 1)) {
3467                 continue;
3468             }
3469         }
3470 
3471         /* we have the matching extension - remove it */
3472         ++found;
3473         lyp_ext_instance_rm(target->module->ctx, &target->ext, &target->ext_size, n);
3474         --n;
3475     }
3476 
3477     if (!found) {
3478         path = lys_path(target, LYS_PATH_FIRST_PREFIX);
3479         LOGERR(target->module->ctx, LY_EVALID, "Extension deviation: extension \"%s\" to delete not found in \"%s\".",
3480                ext->def->name, path)
3481         free(path);
3482         return EXIT_FAILURE;
3483     }
3484     return EXIT_SUCCESS;
3485 }
3486 
3487 static int
lyp_deviate_apply_ext(struct lys_deviate * dev,struct lys_node * target,LYEXT_SUBSTMT substmt,struct lys_ext * extdef)3488 lyp_deviate_apply_ext(struct lys_deviate *dev, struct lys_node *target, LYEXT_SUBSTMT substmt, struct lys_ext *extdef)
3489 {
3490     struct ly_ctx *ctx;
3491     int m, n;
3492     struct lys_ext_instance *new;
3493     void *reallocated;
3494 
3495     /* LY_DEVIATE_ADD and LY_DEVIATE_RPL are very similar so they are implement the same way - in replacing,
3496      * there can be some extension instances in the target, in case of adding, there should not be any so we
3497      * will be just adding. */
3498 
3499     ctx = target->module->ctx; /* shortcut */
3500     m = n = -1;
3501 
3502     while ((m = lys_ext_iter(dev->ext, dev->ext_size, m + 1, substmt)) != -1) {
3503         /* deviate and its substatements include extensions, copy them to the target, replacing the previous
3504          * extensions if any. In case of deviating extension itself, we have to deviate only the same type
3505          * of the extension as specified in the deviation */
3506         if (substmt == LYEXT_SUBSTMT_SELF && dev->ext[m]->def != extdef) {
3507             continue;
3508         }
3509 
3510         if (substmt == LYEXT_SUBSTMT_SELF && dev->mod == LY_DEVIATE_ADD) {
3511             /* in case of adding extension, we will be replacing only the inherited extensions */
3512             do {
3513                 n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt);
3514             } while (n != -1 && (target->ext[n]->def != extdef || !(target->ext[n]->flags & LYEXT_OPT_INHERIT)));
3515         } else {
3516             /* get the index of the extension to replace in the target node */
3517             do {
3518                 n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt);
3519                 /* if we are applying extension deviation, we have to deviate only the same type of the extension */
3520             } while (n != -1 && substmt == LYEXT_SUBSTMT_SELF && target->ext[n]->def != extdef);
3521         }
3522 
3523         if (n == -1) {
3524             /* nothing to replace, we are going to add it - reallocate */
3525             new = malloc(sizeof **target->ext);
3526             LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3527             reallocated = realloc(target->ext, (target->ext_size + 1) * sizeof *target->ext);
3528             LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx); free(new), EXIT_FAILURE);
3529             target->ext = reallocated;
3530             target->ext_size++;
3531 
3532             n = target->ext_size - 1;
3533         } else {
3534             /* replacing - the original set of extensions is actually backuped together with the
3535              * node itself, so we are supposed only to free the allocated data here ... */
3536             lys_extension_instances_free(ctx, target->ext[n]->ext, target->ext[n]->ext_size, NULL);
3537             lydict_remove(ctx, target->ext[n]->arg_value);
3538             free(target->ext[n]);
3539 
3540             /* and prepare the new structure */
3541             new = malloc(sizeof **target->ext);
3542             LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3543         }
3544         /* common part for adding and replacing - fill the newly created / replaced cell */
3545         target->ext[n] = new;
3546         target->ext[n]->def = dev->ext[m]->def;
3547         target->ext[n]->arg_value = lydict_insert(ctx, dev->ext[m]->arg_value, 0);
3548         target->ext[n]->flags = 0;
3549         target->ext[n]->parent = target;
3550         target->ext[n]->parent_type = LYEXT_PAR_NODE;
3551         target->ext[n]->insubstmt = substmt;
3552         target->ext[n]->insubstmt_index = dev->ext[m]->insubstmt_index;
3553         target->ext[n]->ext_size = dev->ext[m]->ext_size;
3554         lys_ext_dup(ctx, target->module, dev->ext[m]->ext, dev->ext[m]->ext_size, target, LYEXT_PAR_NODE,
3555                     &target->ext[n]->ext, 1, NULL);
3556         target->ext[n]->nodetype = LYS_EXT;
3557         target->ext[n]->module = target->module;
3558         target->ext[n]->priv = NULL;
3559 
3560         /* TODO cover complex extension instances */
3561     }
3562 
3563     /* remove the rest of extensions belonging to the original substatement in the target node,
3564      * due to possible reverting of the deviation effect, they are actually not removed, just moved
3565      * to the backup of the original node when the original node is backuped, here we just have to
3566      * free the replaced / deleted originals */
3567     while ((n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt)) != -1) {
3568         if (substmt == LYEXT_SUBSTMT_SELF) {
3569             /* if we are applying extension deviation, we are going to remove only
3570              * - the same type of the extension in case of replacing
3571              * - the same type of the extension which was inherited in case of adding
3572              * note - delete deviation is covered in lyp_deviate_del_ext */
3573             if (target->ext[n]->def != extdef ||
3574                     (dev->mod == LY_DEVIATE_ADD && !(target->ext[n]->flags & LYEXT_OPT_INHERIT))) {
3575                 /* keep this extension */
3576                 continue;
3577             }
3578 
3579         }
3580 
3581         /* remove the item */
3582         lyp_ext_instance_rm(ctx, &target->ext, &target->ext_size, n);
3583         --n;
3584     }
3585 
3586     return EXIT_SUCCESS;
3587 }
3588 
3589 /*
3590  * not-supported deviations are not processed since they affect the complete node, not just their substatements
3591  */
3592 int
lyp_deviation_apply_ext(struct lys_module * module)3593 lyp_deviation_apply_ext(struct lys_module *module)
3594 {
3595     int i, j, k;
3596     struct lys_deviate *dev;
3597     struct lys_node *target;
3598     struct ly_set *extset;
3599 
3600     for (i = 0; i < module->deviation_size; i++) {
3601         target = NULL;
3602         extset = NULL;
3603         j = resolve_schema_nodeid(module->deviation[i].target_name, NULL, module, &extset, 0, 0);
3604         if (j == -1) {
3605             return EXIT_FAILURE;
3606         } else if (!extset) {
3607             /* LY_DEVIATE_NO */
3608             ly_set_free(extset);
3609             continue;
3610         }
3611         target = extset->set.s[0];
3612         ly_set_free(extset);
3613 
3614         for (j = 0; j < module->deviation[i].deviate_size; j++) {
3615             dev = &module->deviation[i].deviate[j];
3616             if (!dev->ext_size) {
3617                 /* no extensions in deviate and its substatement, nothing to do here */
3618                 continue;
3619             }
3620 
3621             /* extensions */
3622             if (dev->mod == LY_DEVIATE_DEL) {
3623                 k = -1;
3624                 while ((k = lys_ext_iter(dev->ext, dev->ext_size, k + 1, LYEXT_SUBSTMT_SELF)) != -1) {
3625                     if (lyp_deviate_del_ext(target, dev->ext[k])) {
3626                         return EXIT_FAILURE;
3627                     }
3628                 }
3629 
3630                 /* In case of LY_DEVIATE_DEL, we are applying only extension deviation, removing
3631                  * of the substatement's extensions was already done when the substatement was applied.
3632                  * Extension deviation could not be applied by the parser since the extension could be unresolved,
3633                  * which is not the issue of the other substatements. */
3634                 continue;
3635             } else {
3636                 extset = ly_set_new();
3637                 k = -1;
3638                 while ((k = lys_ext_iter(dev->ext, dev->ext_size, k + 1, LYEXT_SUBSTMT_SELF)) != -1) {
3639                     ly_set_add(extset, dev->ext[k]->def, 0);
3640                 }
3641                 for (k = 0; (unsigned int)k < extset->number; k++) {
3642                     if (lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_SELF, (struct lys_ext *)extset->set.g[k])) {
3643                         ly_set_free(extset);
3644                         return EXIT_FAILURE;
3645                     }
3646                 }
3647                 ly_set_free(extset);
3648             }
3649 
3650             /* unique */
3651             if (dev->unique_size && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_UNIQUE, NULL)) {
3652                 return EXIT_FAILURE;
3653             }
3654             /* units */
3655             if (dev->units && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_UNITS, NULL)) {
3656                 return EXIT_FAILURE;
3657             }
3658             /* default */
3659             if (dev->dflt_size && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_DEFAULT, NULL)) {
3660                 return EXIT_FAILURE;
3661             }
3662             /* config */
3663             if ((dev->flags & LYS_CONFIG_MASK) && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_CONFIG, NULL)) {
3664                 return EXIT_FAILURE;
3665             }
3666             /* mandatory */
3667             if ((dev->flags & LYS_MAND_MASK) && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_MANDATORY, NULL)) {
3668                 return EXIT_FAILURE;
3669             }
3670             /* min/max */
3671             if (dev->min_set && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_MIN, NULL)) {
3672                 return EXIT_FAILURE;
3673             }
3674             if (dev->min_set && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_MAX, NULL)) {
3675                 return EXIT_FAILURE;
3676             }
3677             /* type and must contain extension instances in their structures */
3678         }
3679     }
3680 
3681     return EXIT_SUCCESS;
3682 }
3683 
3684 int
lyp_ctx_check_module(struct lys_module * module)3685 lyp_ctx_check_module(struct lys_module *module)
3686 {
3687     struct ly_ctx *ctx;
3688     int i, match_i = -1, to_implement;
3689     const char *last_rev = NULL;
3690 
3691     assert(module);
3692     to_implement = 0;
3693     ctx = module->ctx;
3694 
3695     /* find latest revision */
3696     for (i = 0; i < module->rev_size; ++i) {
3697         if (!last_rev || (strcmp(last_rev, module->rev[i].date) < 0)) {
3698             last_rev = module->rev[i].date;
3699         }
3700     }
3701 
3702     for (i = 0; i < ctx->models.used; i++) {
3703         /* check name (name/revision) and namespace uniqueness */
3704         if (!strcmp(ctx->models.list[i]->name, module->name)) {
3705             if (to_implement) {
3706                 if (i == match_i) {
3707                     continue;
3708                 }
3709                 LOGERR(ctx, LY_EINVAL, "Module \"%s@%s\" in another revision \"%s\" already implemented.",
3710                        module->name, last_rev ? last_rev : "<latest>", ctx->models.list[i]->rev[0].date);
3711                 return -1;
3712             } else if (!ctx->models.list[i]->rev_size && module->rev_size) {
3713                 LOGERR(ctx, LY_EINVAL, "Module \"%s\" without revision already in context.", module->name);
3714                 return -1;
3715             } else if (ctx->models.list[i]->rev_size && !module->rev_size) {
3716                 LOGERR(ctx, LY_EINVAL, "Module \"%s\" with revision \"%s\" already in context.",
3717                        module->name, ctx->models.list[i]->rev[0].date);
3718                 return -1;
3719             } else if ((!module->rev_size && !ctx->models.list[i]->rev_size)
3720                     || !strcmp(ctx->models.list[i]->rev[0].date, last_rev)) {
3721 
3722                 LOGVRB("Module \"%s@%s\" already in context.", module->name, last_rev ? last_rev : "<latest>");
3723 
3724                 /* if disabled, enable first */
3725                 if (ctx->models.list[i]->disabled) {
3726                     lys_set_enabled(ctx->models.list[i]);
3727                 }
3728 
3729                 to_implement = module->implemented;
3730                 match_i = i;
3731                 if (to_implement && !ctx->models.list[i]->implemented) {
3732                     /* check first that it is okay to change it to implemented */
3733                     i = -1;
3734                     continue;
3735                 }
3736                 return 1;
3737 
3738             } else if (module->implemented && ctx->models.list[i]->implemented) {
3739                 LOGERR(ctx, LY_EINVAL, "Module \"%s@%s\" in another revision \"%s\" already implemented.",
3740                        module->name, last_rev ? last_rev : "<latest>", ctx->models.list[i]->rev[0].date);
3741                 return -1;
3742             }
3743             /* else keep searching, for now the caller is just adding
3744              * another revision of an already present schema
3745              */
3746         } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
3747             LOGERR(ctx, LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
3748                    ctx->models.list[i]->name, module->name, module->ns);
3749             return -1;
3750         }
3751     }
3752 
3753     if (to_implement) {
3754         if (lys_set_implemented(ctx->models.list[match_i])) {
3755             return -1;
3756         }
3757         return 1;
3758     }
3759 
3760     return 0;
3761 }
3762 
3763 int
lyp_ctx_add_module(struct lys_module * module)3764 lyp_ctx_add_module(struct lys_module *module)
3765 {
3766     struct lys_module **newlist = NULL;
3767     int i;
3768 
3769     assert(!lyp_ctx_check_module(module));
3770 
3771 #ifndef NDEBUG
3772     int j;
3773     /* check that all augments are resolved */
3774     for (i = 0; i < module->augment_size; ++i) {
3775         assert(module->augment[i].target);
3776     }
3777     for (i = 0; i < module->inc_size; ++i) {
3778         for (j = 0; j < module->inc[i].submodule->augment_size; ++j) {
3779             assert(module->inc[i].submodule->augment[j].target);
3780         }
3781     }
3782 #endif
3783 
3784     /* add to the context's list of modules */
3785     if (module->ctx->models.used == module->ctx->models.size) {
3786         newlist = realloc(module->ctx->models.list, (2 * module->ctx->models.size) * sizeof *newlist);
3787         LY_CHECK_ERR_RETURN(!newlist, LOGMEM(module->ctx), -1);
3788         for (i = module->ctx->models.size; i < module->ctx->models.size * 2; i++) {
3789             newlist[i] = NULL;
3790         }
3791         module->ctx->models.size *= 2;
3792         module->ctx->models.list = newlist;
3793     }
3794     module->ctx->models.list[module->ctx->models.used++] = module;
3795     module->ctx->models.module_set_id++;
3796 
3797     return 0;
3798 }
3799 
3800 /**
3801  * Store UTF-8 character specified as 4byte integer into the dst buffer.
3802  * Returns number of written bytes (4 max), expects that dst has enough space.
3803  *
3804  * UTF-8 mapping:
3805  * 00000000 -- 0000007F:    0xxxxxxx
3806  * 00000080 -- 000007FF:    110xxxxx 10xxxxxx
3807  * 00000800 -- 0000FFFF:    1110xxxx 10xxxxxx 10xxxxxx
3808  * 00010000 -- 001FFFFF:    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
3809  *
3810  * Includes checking for valid characters (following RFC 7950, sec 9.4)
3811  */
3812 unsigned int
pututf8(struct ly_ctx * ctx,char * dst,int32_t value)3813 pututf8(struct ly_ctx *ctx, char *dst, int32_t value)
3814 {
3815     if (value < 0x80) {
3816         /* one byte character */
3817         if (value < 0x20 &&
3818                 value != 0x09 &&
3819                 value != 0x0a &&
3820                 value != 0x0d) {
3821             goto error;
3822         }
3823 
3824         dst[0] = value;
3825         return 1;
3826     } else if (value < 0x800) {
3827         /* two bytes character */
3828         dst[0] = 0xc0 | (value >> 6);
3829         dst[1] = 0x80 | (value & 0x3f);
3830         return 2;
3831     } else if (value < 0xfffe) {
3832         /* three bytes character */
3833         if (((value & 0xf800) == 0xd800) ||
3834                 (value >= 0xfdd0 && value <= 0xfdef)) {
3835             /* exclude surrogate blocks %xD800-DFFF */
3836             /* exclude noncharacters %xFDD0-FDEF */
3837             goto error;
3838         }
3839 
3840         dst[0] = 0xe0 | (value >> 12);
3841         dst[1] = 0x80 | ((value >> 6) & 0x3f);
3842         dst[2] = 0x80 | (value & 0x3f);
3843 
3844         return 3;
3845     } else if (value < 0x10fffe) {
3846         if ((value & 0xffe) == 0xffe) {
3847             /* exclude noncharacters %xFFFE-FFFF, %x1FFFE-1FFFF, %x2FFFE-2FFFF, %x3FFFE-3FFFF, %x4FFFE-4FFFF,
3848              * %x5FFFE-5FFFF, %x6FFFE-6FFFF, %x7FFFE-7FFFF, %x8FFFE-8FFFF, %x9FFFE-9FFFF, %xAFFFE-AFFFF,
3849              * %xBFFFE-BFFFF, %xCFFFE-CFFFF, %xDFFFE-DFFFF, %xEFFFE-EFFFF, %xFFFFE-FFFFF, %x10FFFE-10FFFF */
3850             goto error;
3851         }
3852         /* four bytes character */
3853         dst[0] = 0xf0 | (value >> 18);
3854         dst[1] = 0x80 | ((value >> 12) & 0x3f);
3855         dst[2] = 0x80 | ((value >> 6) & 0x3f);
3856         dst[3] = 0x80 | (value & 0x3f);
3857 
3858         return 4;
3859     }
3860 
3861 error:
3862     /* out of range */
3863     LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, NULL);
3864     LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%08x", value);
3865     return 0;
3866 }
3867 
3868 unsigned int
copyutf8(struct ly_ctx * ctx,char * dst,const char * src)3869 copyutf8(struct ly_ctx *ctx, char *dst, const char *src)
3870 {
3871     uint32_t value;
3872 
3873     /* unicode characters */
3874     if (!(src[0] & 0x80)) {
3875         /* one byte character */
3876         if (src[0] < 0x20 &&
3877                 src[0] != 0x09 &&
3878                 src[0] != 0x0a &&
3879                 src[0] != 0x0d) {
3880             LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3881             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x", src[0]);
3882             return 0;
3883         }
3884 
3885         dst[0] = src[0];
3886         return 1;
3887     } else if ((src[0] & 0xe0) == 0xc0) {
3888         /* two bytes character */
3889         if ((src[1] & 0xc0) != 0x80) {
3890             LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3891             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x 0x%02x",
3892                     (unsigned char)src[0], (unsigned char)src[1])
3893             return 0;
3894         }
3895 
3896         dst[0] = src[0];
3897         dst[1] = src[1];
3898         return 2;
3899     } else if ((src[0] & 0xf0) == 0xe0) {
3900         /* three bytes character */
3901         if ((src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80) {
3902             LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3903             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x 0x%02x 0x%02x",
3904                     (unsigned char)src[0], (unsigned char)src[1], (src[1] ? (unsigned char)src[2] : 0))
3905             return 0;
3906         }
3907 
3908         value = ((uint32_t)(src[0] & 0xf) << 12) | ((uint32_t)(src[1] & 0x3f) << 6) | (src[2] & 0x3f);
3909         if (((value & 0xf800) == 0xd800) ||
3910                 (value >= 0xfdd0 && value <= 0xfdef) ||
3911                 (value & 0xffe) == 0xffe) {
3912             /* exclude surrogate blocks %xD800-DFFF */
3913             /* exclude noncharacters %xFDD0-FDEF */
3914             /* exclude noncharacters %xFFFE-FFFF */
3915             LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3916             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%08x", value);
3917             return 0;
3918         }
3919 
3920         dst[0] = src[0];
3921         dst[1] = src[1];
3922         dst[2] = src[2];
3923         return 3;
3924     } else if ((src[0] & 0xf8) == 0xf0) {
3925         /* four bytes character */
3926         if ((src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80 || (src[3] & 0xc0) != 0x80) {
3927             LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3928             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x 0x%02x 0x%02x 0x%02x",
3929                     (unsigned char)src[0], (unsigned char)src[1],
3930                     (src[1] ? (unsigned char)src[2] : 0), ((src[1] && src[2]) ? (unsigned char)src[3] : 0));
3931             return 0;
3932         }
3933 
3934         value = ((uint32_t)(src[0] & 0x7) << 18) | ((uint32_t)(src[1] & 0x3f) << 12) | ((uint32_t)(src[2] & 0x3f) << 6) | (src[3] & 0x3f);
3935         if ((value & 0xffe) == 0xffe) {
3936             /* exclude noncharacters %x1FFFE-1FFFF, %x2FFFE-2FFFF, %x3FFFE-3FFFF, %x4FFFE-4FFFF,
3937              * %x5FFFE-5FFFF, %x6FFFE-6FFFF, %x7FFFE-7FFFF, %x8FFFE-8FFFF, %x9FFFE-9FFFF, %xAFFFE-AFFFF,
3938              * %xBFFFE-BFFFF, %xCFFFE-CFFFF, %xDFFFE-DFFFF, %xEFFFE-EFFFF, %xFFFFE-FFFFF, %x10FFFE-10FFFF */
3939             LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3940             LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%08x", value);
3941             return 0;
3942         }
3943         dst[0] = src[0];
3944         dst[1] = src[1];
3945         dst[2] = src[2];
3946         dst[3] = src[3];
3947         return 4;
3948     } else {
3949         LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3950         LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 leading byte 0x%02x", src[0]);
3951         return 0;
3952     }
3953 }
3954 
3955 const struct lys_module *
lyp_get_module(const struct lys_module * module,const char * prefix,int pref_len,const char * name,int name_len,int in_data)3956 lyp_get_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len, int in_data)
3957 {
3958     const struct lys_module *main_module;
3959     char *str;
3960     int i;
3961 
3962     assert(!prefix || !name);
3963 
3964     if (prefix && !pref_len) {
3965         pref_len = strlen(prefix);
3966     }
3967     if (name && !name_len) {
3968         name_len = strlen(name);
3969     }
3970 
3971     main_module = lys_main_module(module);
3972 
3973     /* module own prefix, submodule own prefix, (sub)module own name */
3974     if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
3975                  || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
3976             && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
3977         return main_module;
3978     }
3979 
3980     /* standard import */
3981     for (i = 0; i < module->imp_size; ++i) {
3982         if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
3983                 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
3984             return module->imp[i].module;
3985         }
3986     }
3987 
3988     /* module required by a foreign grouping, deviation, or submodule */
3989     if (name) {
3990         str = strndup(name, name_len);
3991         if (!str) {
3992             LOGMEM(module->ctx);
3993             return NULL;
3994         }
3995         main_module = ly_ctx_get_module(module->ctx, str, NULL, 0);
3996 
3997         /* try data callback */
3998         if (!main_module && in_data && module->ctx->data_clb) {
3999             main_module = module->ctx->data_clb(module->ctx, str, NULL, 0, module->ctx->data_clb_data);
4000         }
4001 
4002         free(str);
4003         return main_module;
4004     }
4005 
4006     return NULL;
4007 }
4008 
4009 const struct lys_module *
lyp_get_import_module_ns(const struct lys_module * module,const char * ns)4010 lyp_get_import_module_ns(const struct lys_module *module, const char *ns)
4011 {
4012     int i;
4013     const struct lys_module *mod = NULL;
4014 
4015     assert(module && ns);
4016 
4017     if (module->type) {
4018         /* the module is actually submodule and to get the namespace, we need the main module */
4019         if (ly_strequal(((struct lys_submodule *)module)->belongsto->ns, ns, 0)) {
4020             return ((struct lys_submodule *)module)->belongsto;
4021         }
4022     } else {
4023         /* module's own namespace */
4024         if (ly_strequal(module->ns, ns, 0)) {
4025             return module;
4026         }
4027     }
4028 
4029     /* imported modules */
4030     for (i = 0; i < module->imp_size; ++i) {
4031         if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
4032             return module->imp[i].module;
4033         }
4034     }
4035 
4036     return mod;
4037 }
4038 
4039 const char *
lyp_get_yang_data_template_name(const struct lyd_node * node)4040 lyp_get_yang_data_template_name(const struct lyd_node *node)
4041 {
4042     struct lys_node *snode;
4043 
4044     snode = lys_parent(node->schema);
4045     while (snode && snode->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE)) {
4046         snode = lys_parent(snode);
4047     }
4048 
4049     if (snode && snode->nodetype == LYS_EXT && strcmp(((struct lys_ext_instance_complex *)snode)->def->name, "yang-data") == 0) {
4050         return ((struct lys_ext_instance_complex *)snode)->arg_value;
4051     } else {
4052         return NULL;
4053     }
4054 }
4055 
4056 const struct lys_node *
lyp_get_yang_data_template(const struct lys_module * module,const char * yang_data_name,int yang_data_name_len)4057 lyp_get_yang_data_template(const struct lys_module *module, const char *yang_data_name, int yang_data_name_len)
4058 {
4059     int i, j;
4060     const struct lys_node *ret = NULL;
4061     const struct lys_submodule *submodule;
4062 
4063     for(i = 0; i < module->ext_size; ++i) {
4064         if (!strcmp(module->ext[i]->def->name, "yang-data") && !strncmp(module->ext[i]->arg_value, yang_data_name, yang_data_name_len)
4065             && !module->ext[i]->arg_value[yang_data_name_len]) {
4066             ret = (struct lys_node *)module->ext[i];
4067             break;
4068         }
4069     }
4070 
4071     for(j = 0; !ret && j < module->inc_size; ++j) {
4072         submodule = module->inc[j].submodule;
4073         for(i = 0; i < submodule->ext_size; ++i) {
4074             if (!strcmp(submodule->ext[i]->def->name, "yang-data") && !strncmp(submodule->ext[i]->arg_value, yang_data_name, yang_data_name_len)
4075                 && !submodule->ext[i]->arg_value[yang_data_name_len]) {
4076                 ret = (struct lys_node *)submodule->ext[i];
4077                 break;
4078             }
4079         }
4080     }
4081 
4082     return ret;
4083 }
4084 
4085 int
lyp_get_ext_list(struct ly_ctx * ctx,void * elem,LYEXT_PAR elem_type,struct lys_ext_instance **** ext_list,uint8_t ** ext_size,const char ** stmt)4086 lyp_get_ext_list(struct ly_ctx *ctx, void *elem, LYEXT_PAR elem_type,
4087         struct lys_ext_instance ****ext_list, uint8_t **ext_size, const char **stmt)
4088 {
4089     const char *statement = NULL;
4090 
4091     switch (elem_type) {
4092     case LYEXT_PAR_MODULE:
4093         *ext_size = &((struct lys_module *)elem)->ext_size;
4094         *ext_list = &((struct lys_module *)elem)->ext;
4095         statement = ((struct lys_module *)elem)->type ? "submodule" : "module";
4096         break;
4097     case LYEXT_PAR_IMPORT:
4098         *ext_size = &((struct lys_import *)elem)->ext_size;
4099         *ext_list = &((struct lys_import *)elem)->ext;
4100         statement = "import";
4101         break;
4102     case LYEXT_PAR_INCLUDE:
4103         *ext_size = &((struct lys_include *)elem)->ext_size;
4104         *ext_list = &((struct lys_include *)elem)->ext;
4105         statement = "include";
4106         break;
4107     case LYEXT_PAR_REVISION:
4108         *ext_size = &((struct lys_revision *)elem)->ext_size;
4109         *ext_list = &((struct lys_revision *)elem)->ext;
4110         statement = "revision";
4111         break;
4112     case LYEXT_PAR_NODE:
4113         *ext_size = &((struct lys_node *)elem)->ext_size;
4114         *ext_list = &((struct lys_node *)elem)->ext;
4115         statement = strnodetype(((struct lys_node *)elem)->nodetype);
4116         break;
4117     case LYEXT_PAR_IDENT:
4118         *ext_size = &((struct lys_ident *)elem)->ext_size;
4119         *ext_list = &((struct lys_ident *)elem)->ext;
4120         statement = "identity";
4121         break;
4122     case LYEXT_PAR_TYPE:
4123         *ext_size = &((struct lys_type *)elem)->ext_size;
4124         *ext_list = &((struct lys_type *)elem)->ext;
4125         statement = "type";
4126         break;
4127     case LYEXT_PAR_TYPE_BIT:
4128         *ext_size = &((struct lys_type_bit *)elem)->ext_size;
4129         *ext_list = &((struct lys_type_bit *)elem)->ext;
4130         statement = "bit";
4131         break;
4132     case LYEXT_PAR_TYPE_ENUM:
4133         *ext_size = &((struct lys_type_enum *)elem)->ext_size;
4134         *ext_list = &((struct lys_type_enum *)elem)->ext;
4135         statement = "enum";
4136         break;
4137     case LYEXT_PAR_TPDF:
4138         *ext_size = &((struct lys_tpdf *)elem)->ext_size;
4139         *ext_list = &((struct lys_tpdf *)elem)->ext;
4140         statement = "typedef";
4141         break;
4142     case LYEXT_PAR_EXT:
4143         *ext_size = &((struct lys_ext *)elem)->ext_size;
4144         *ext_list = &((struct lys_ext *)elem)->ext;
4145         statement = "extension";
4146         break;
4147     case LYEXT_PAR_EXTINST:
4148         *ext_size = &((struct lys_ext_instance *)elem)->ext_size;
4149         *ext_list = &((struct lys_ext_instance *)elem)->ext;
4150         statement = "extension instance";
4151         break;
4152     case LYEXT_PAR_FEATURE:
4153         *ext_size = &((struct lys_feature *)elem)->ext_size;
4154         *ext_list = &((struct lys_feature *)elem)->ext;
4155         statement = "feature";
4156         break;
4157     case LYEXT_PAR_REFINE:
4158         *ext_size = &((struct lys_refine *)elem)->ext_size;
4159         *ext_list = &((struct lys_refine *)elem)->ext;
4160         statement = "refine";
4161         break;
4162     case LYEXT_PAR_RESTR:
4163         *ext_size = &((struct lys_restr *)elem)->ext_size;
4164         *ext_list = &((struct lys_restr *)elem)->ext;
4165         statement = "YANG restriction";
4166         break;
4167     case LYEXT_PAR_WHEN:
4168         *ext_size = &((struct lys_when *)elem)->ext_size;
4169         *ext_list = &((struct lys_when *)elem)->ext;
4170         statement = "when";
4171         break;
4172     case LYEXT_PAR_DEVIATE:
4173         *ext_size = &((struct lys_deviate *)elem)->ext_size;
4174         *ext_list = &((struct lys_deviate *)elem)->ext;
4175         statement = "deviate";
4176         break;
4177     case LYEXT_PAR_DEVIATION:
4178         *ext_size = &((struct lys_deviation *)elem)->ext_size;
4179         *ext_list = &((struct lys_deviation *)elem)->ext;
4180         statement = "deviation";
4181         break;
4182     default:
4183         LOGERR(ctx, LY_EINT, "parent type %d", elem_type);
4184         return -1;
4185     }
4186 
4187     if (stmt) {
4188         *stmt = statement;
4189     }
4190 
4191     return 0;
4192 }
4193 
4194 inline void
lyp_reduce_ext_list(struct lys_ext_instance *** ext,uint8_t new_size,uint8_t orig_size)4195 lyp_reduce_ext_list(struct lys_ext_instance ***ext, uint8_t new_size, uint8_t orig_size)
4196 {
4197     struct lys_ext_instance **tmp;
4198 
4199     if (new_size != orig_size) {
4200         if (new_size == 0) {
4201             free(*ext);
4202             *ext = NULL;
4203         } else {
4204             tmp = realloc(*ext, new_size * sizeof(*tmp));
4205             if (!tmp) {
4206                 /* we just reduce the size, so this failure is harmless. */
4207                 return;
4208             }
4209             *ext = tmp;
4210         }
4211     }
4212 }
4213 
4214