diff options
75 files changed, 1080 insertions, 876 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef3bfe6..6ab2938 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,13 +64,13 @@ jobs: build-cmd: "make" } - { - name: "Release, macOS 11, clang", - os: "macos-11", + name: "Release, macOS 14, clang", + os: "macos-14", build-type: "Release", cc: "clang", options: "-DENABLE_TESTS=ON -DPATH_EXPECT=", packager: "brew", - packages: "cmocka shunit2", + packages: "cmocka shunit2 tcl-tk", snaps: "", build-cmd: "make" } diff --git a/CMakeLists.txt b/CMakeLists.txt index 75740a9..8d0bb28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,14 +59,14 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # set version of the project set(LIBYANG_MAJOR_VERSION 3) -set(LIBYANG_MINOR_VERSION 1) -set(LIBYANG_MICRO_VERSION 0) +set(LIBYANG_MINOR_VERSION 4) +set(LIBYANG_MICRO_VERSION 2) set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION}) # set version of the library set(LIBYANG_MAJOR_SOVERSION 3) -set(LIBYANG_MINOR_SOVERSION 2) -set(LIBYANG_MICRO_SOVERSION 0) +set(LIBYANG_MINOR_SOVERSION 4) +set(LIBYANG_MICRO_SOVERSION 2) set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION}) set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION}) @@ -106,7 +106,8 @@ set(type_plugins src/plugins_types/date_and_time.c src/plugins_types/hex_string.c src/plugins_types/xpath1.0.c - src/plugins_types/node_instanceid.c) + src/plugins_types/node_instanceid.c + src/plugins_types/time_period.c) set(libsrc src/ly_common.c @@ -471,7 +472,7 @@ endif() # generate API/ABI report if("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK") - lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 708a8bfad983a4095c8d4dc537a9d2a1d5ca65c5) + lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 670385f9595014dc9307615fa6e929b46dba026b) endif() # source code format target for Makefile @@ -58,8 +58,6 @@ the `distro` directory. * C compiler * cmake >= 2.8.12 * libpcre2 >= 10.21 (including devel package) - * note, that PCRE is supposed to be compiled with unicode support (configure's options - `--enable-utf` and `--enable-unicode-properties`) #### Optional diff --git a/src/context.c b/src/context.c index 912f56d..2345cf2 100644 --- a/src/context.c +++ b/src/context.c @@ -721,7 +721,7 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option) ext = &mod->compiled->exts[u]; LY_ARRAY_FOR(ext->substmts, v) { if (ext->substmts[v].stmt & LY_STMT_DATA_NODE_MASK) { - LY_LIST_FOR(*VOIDPTR2_C(ext->substmts[v].storage), root) { + LY_LIST_FOR(*ext->substmts[v].storage_p, root) { lysc_tree_dfs_full(root, lysc_node_clear_priv_dfs_cb, NULL); } } diff --git a/src/context.h b/src/context.h index 31f41b9..a9ad91f 100644 --- a/src/context.h +++ b/src/context.h @@ -602,10 +602,10 @@ LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule2_latest(const LIBYANG_API_DECL uint32_t ly_ctx_internal_modules_count(const struct ly_ctx *ctx); /** - * @brief Try to find the model in the searchpaths of \p ctx and load it into it. If custom missing + * @brief Try to find the model in the searchpaths of @p ctx and load it into it. If custom missing * module callback is set, it is used instead. * - * The context itself is searched for the requested module first. If \p revision is not specified + * The context itself is searched for the requested module first. If @p revision is not specified * (the module of the latest revision is requested) and there is implemented revision of the requested * module in the context, this implemented revision is returned despite there might be a newer revision. * This behavior is cause by the fact that it is not possible to have multiple implemented revisions of @@ -660,7 +660,7 @@ LIBYANG_API_DECL LY_ERR ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct * Note that the data stored by user into the ::lysc_node.priv pointer are kept * untouched and the caller is responsible for freeing this private data. * - * @param[in] ctx libyang context to destroy + * @param[in] ctx Context to destroy. */ LIBYANG_API_DECL void ly_ctx_destroy(struct ly_ctx *ctx); @@ -104,9 +104,6 @@ lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_da str1 = ((struct ly_dict_rec *)val1_p)->value; str2 = ((struct ly_dict_rec *)val2_p)->value; - LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0); - LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0); - if (mod) { /* used when inserting new values */ if (strcmp(str1, str2) == 0) { @@ -177,7 +174,7 @@ finish: return ret; } -LY_ERR +static LY_ERR dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p) { LY_ERR ret = LY_SUCCESS; @@ -221,9 +218,7 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, return ret; } - if (str_p) { - *str_p = match->value; - } + *str_p = match->value; return ret; } @@ -269,3 +264,49 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p) return result; } + +static LY_ERR +dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p) +{ + LY_ERR ret = LY_SUCCESS; + struct ly_dict_rec *match = NULL, rec; + uint32_t hash; + + /* set new callback to only compare memory addresses */ + lyht_value_equal_cb prev = lyht_set_cb(ctx->dict.hash_tab, lydict_resize_val_eq); + + LOGDBG(LY_LDGDICT, "duplicating %s", value); + hash = lyht_hash(value, strlen(value)); + rec.value = value; + + ret = lyht_find(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match); + if (ret == LY_SUCCESS) { + /* record found, increase refcount */ + match->refcount++; + *str_p = match->value; + } + + /* restore callback */ + lyht_set_cb(ctx->dict.hash_tab, prev); + + return ret; +} + +LIBYANG_API_DEF LY_ERR +lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p) +{ + LY_ERR result; + + LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); + + if (!value) { + *str_p = NULL; + return LY_SUCCESS; + } + + pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock); + result = dict_dup(ctx, (char *)value, str_p); + pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock); + + return result; +} @@ -113,6 +113,18 @@ LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value, */ LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value); +/** + * @brief Duplicate string in dictionary. Only a reference counter is incremented. + * + * @param[in] ctx libyang context handler + * @param[in] value NULL-terminated string to be duplicated in the dictionary (reference counter is incremented). + * @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary. + * @return LY_SUCCESS in case the string already exists in the dictionary. + * @return LY_ENOTFOUND in case the string was not found. + * @return LY_ERR on other errors + */ +LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p); + /** @} dict */ #ifdef __cplusplus diff --git a/src/hash_table.c b/src/hash_table.c index f951e6a..4dbfdd1 100644 --- a/src/hash_table.c +++ b/src/hash_table.c @@ -179,6 +179,7 @@ lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p)) * * @param[in] ht Hash table to resize. * @param[in] operation Operation to perform. 1 to enlarge, -1 to shrink, 0 to only rehash all records. + * @param[in] check Whether to check if the value has already been inserted or not. * @return LY_ERR value. */ static LY_ERR @@ -247,7 +248,6 @@ lyht_resize(struct ly_ht *ht, int operation, int check) * @param[in] hash Hash to find. * @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (find). * @param[in] val_equal Callback for checking value equivalence. - * @param[out] crec_p Optional found first record. * @param[out] col Optional collision number of @p rec_p, 0 for no collision. * @param[out] rec_p Found exact matching record, may be a collision of @p crec_p. * @return LY_ENOTFOUND if no record found, @@ -255,15 +255,12 @@ lyht_resize(struct ly_ht *ht, int operation, int check) */ static LY_ERR lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, lyht_value_equal_cb val_equal, - struct ly_ht_rec **crec_p, uint32_t *col, struct ly_ht_rec **rec_p) + uint32_t *col, struct ly_ht_rec **rec_p) { uint32_t hlist_idx = hash & (ht->size - 1); struct ly_ht_rec *rec; uint32_t rec_idx; - if (crec_p) { - *crec_p = NULL; - } if (col) { *col = 0; } @@ -271,9 +268,6 @@ lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, l LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) { if ((rec->hash == hash) && val_equal(val_p, &rec->val, mod, ht->cb_data)) { - if (crec_p) { - *crec_p = rec; - } *rec_p = rec; return LY_SUCCESS; } @@ -292,7 +286,11 @@ lyht_find(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p) { struct ly_ht_rec *rec; - lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, NULL, &rec); + if (match_p) { + *match_p = NULL; + } + + lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, &rec); if (rec && match_p) { *match_p = rec->val; @@ -305,7 +303,7 @@ lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v { struct ly_ht_rec *rec; - lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, NULL, &rec); + lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, &rec); if (rec && match_p) { *match_p = rec->val; @@ -317,12 +315,12 @@ LIBYANG_API_DEF LY_ERR lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb collision_val_equal, void **match_p) { - struct ly_ht_rec *rec, *crec; + struct ly_ht_rec *rec; uint32_t rec_idx; uint32_t i; /* find the record of the previously found value */ - if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &crec, &i, &rec)) { + if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &i, &rec)) { /* not found, cannot happen */ LOGINT_RET(NULL); } @@ -373,7 +371,7 @@ _lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v uint32_t rec_idx; if (check) { - if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &rec) == LY_SUCCESS) { + if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &rec) == LY_SUCCESS) { if (rec && match_p) { *match_p = rec->val; } @@ -459,7 +457,7 @@ lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_va uint32_t prev_rec_idx; uint32_t rec_idx; - if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &found_rec)) { + if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &found_rec)) { LOGARG(NULL, hash); return LY_ENOTFOUND; } @@ -189,10 +189,15 @@ ly_err_get_rec(const struct ly_ctx *ctx) /* prepare record */ rec.tid = pthread_self(); + /* reuse lock */ + /* LOCK */ + pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock); + /* get the pointer to the matching record */ - if (lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match)) { - return NULL; - } + lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match); + + /* UNLOCK */ + pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock); return match; } diff --git a/src/ly_common.c b/src/ly_common.c index 28d7514..449c862 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -40,19 +40,53 @@ #include "version.h" #include "xml.h" -LIBYANG_API_DEF struct ly_version ly_version_so = { - .major = LY_VERSION_MAJOR, - .minor = LY_VERSION_MINOR, - .micro = LY_VERSION_MICRO, - .str = LY_VERSION -}; +LIBYANG_API_DEF uint32_t +ly_version_so_major(void) +{ + return LY_VERSION_MAJOR; +} -LIBYANG_API_DEF struct ly_version ly_version_proj = { - .major = LY_PROJ_VERSION_MAJOR, - .minor = LY_PROJ_VERSION_MINOR, - .micro = LY_PROJ_VERSION_MICRO, - .str = LY_PROJ_VERSION -}; +LIBYANG_API_DEF uint32_t +ly_version_so_minor(void) +{ + return LY_VERSION_MINOR; +} + +LIBYANG_API_DEF uint32_t +ly_version_so_micro(void) +{ + return LY_VERSION_MICRO; +} + +LIBYANG_API_DEF const char * +ly_version_so_str(void) +{ + return LY_VERSION; +} + +LIBYANG_API_DEF uint32_t +ly_version_proj_major(void) +{ + return LY_PROJ_VERSION_MAJOR; +} + +LIBYANG_API_DEF uint32_t +ly_version_proj_minor(void) +{ + return LY_PROJ_VERSION_MINOR; +} + +LIBYANG_API_DEF uint32_t +ly_version_proj_micro(void) +{ + return LY_PROJ_VERSION_MICRO; +} + +LIBYANG_API_DEF const char * +ly_version_proj_str(void) +{ + return LY_PROJ_VERSION; +} void * ly_realloc(void *ptr, size_t size) diff --git a/src/ly_common.h b/src/ly_common.h index 8dc32d7..ec0d3ea 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -61,9 +61,6 @@ struct lysc_node; #define GETMACRO6(_1, _2, _3, _4, _5, _6, NAME, ...) NAME #define GETMACRO7(_1, _2, _3, _4, _5, _6, _7, NAME, ...) NAME -#define VOIDPTR_C(var) ((void *)(uintptr_t)(var)) -#define VOIDPTR2_C(var) ((void **)(uintptr_t)(var)) - /****************************************************************************** * Logger *****************************************************************************/ diff --git a/src/parser_common.c b/src/parser_common.c index 290e3a5..5dadecf 100644 --- a/src/parser_common.c +++ b/src/parser_common.c @@ -3,7 +3,7 @@ * @author Michal Vasko <mvasko@cesnet.cz> * @brief libyang common parser functions. * - * Copyright (c) 2015 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2015 - 2024 CESNET, z.s.p.o. * * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. @@ -70,34 +70,48 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node) { LY_ERR rc = LY_SUCCESS; struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node); - struct lysc_ctx cctx; - const struct lys_module *mod; + struct lysc_ctx cctx = {0}; + const struct lys_module *mod1, *mod2; + const struct lysc_node *schema; LY_ARRAY_COUNT_TYPE u; struct ly_err_item *err = NULL; struct lysp_type *type_p = NULL; struct lysc_pattern **patterns = NULL; const char *value; - LYSC_CTX_INIT_CTX(cctx, ctx); + /* find the used modules, we will either use a compiled leaf or compile the relevant type ourselves */ + mod1 = ly_ctx_get_module_implemented(ctx, "notifications"); + mod2 = ly_ctx_get_module_latest(ctx, "ietf-yang-types"); + assert(mod2); - /* get date-and-time parsed type */ - mod = ly_ctx_get_module_latest(ctx, "ietf-yang-types"); - assert(mod); - LY_ARRAY_FOR(mod->parsed->typedefs, u) { - if (!strcmp(mod->parsed->typedefs[u].name, "date-and-time")) { - type_p = &mod->parsed->typedefs[u].type; - break; + if (mod1 || !mod2->parsed) { + /* get date-and-time leaf */ + schema = lys_find_path(LYD_CTX(node), NULL, "/notifications:notification/eventTime", 0); + LY_CHECK_RET(!schema, LY_ENOTFOUND); + + /* validate the value */ + value = lyd_get_value(node); + LY_CHECK_RET(lyd_value_validate(LYD_CTX(node), schema, value, strlen(value), NULL, NULL, NULL)); + } else { + LYSC_CTX_INIT_CTX(cctx, ctx); + + /* get date-and-time parsed type */ + LY_ARRAY_FOR(mod2->parsed->typedefs, u) { + if (!strcmp(mod2->parsed->typedefs[u].name, "date-and-time")) { + type_p = &mod2->parsed->typedefs[u].type; + break; + } } - } - assert(type_p); + assert(type_p); - /* compile patterns */ - assert(type_p->patterns); - LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup); + /* compile patterns */ + assert(type_p->patterns); + LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup); - /* validate */ - value = lyd_get_value(node); - rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err); + /* validate */ + value = lyd_get_value(node); + rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err); + } cleanup: FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free); @@ -3559,7 +3573,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs { LY_ERR rc = LY_SUCCESS; - if (!substmt->storage) { + if (!substmt->storage_p) { /* nothing to parse, ignored */ goto cleanup; } @@ -3587,7 +3601,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup); /* usually is a linked-list of all the parsed schema nodes */ - pnodes_p = VOIDPTR_C(substmt->storage); + pnodes_p = (struct lysp_node **)substmt->storage_p; while (*pnodes_p) { pnodes_p = &(*pnodes_p)->next; } @@ -3615,7 +3629,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs case LY_STMT_TYPEDEF: case LY_STMT_UNIQUE: /* parse, sized array */ - LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup); + LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup); break; case LY_STMT_ARGUMENT: @@ -3650,50 +3664,50 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs case LY_STMT_YANG_VERSION: case LY_STMT_YIN_ELEMENT: /* single item */ - if (*VOIDPTR2_C(substmt->storage)) { + if (*substmt->storage_p) { LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt); rc = LY_EVALID; goto cleanup; } /* parse */ - LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup); + LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup); break; case LY_STMT_CONFIG: /* single item */ - if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_CONFIG_MASK) { + if ((*(uint16_t *)substmt->storage_p) & LYS_CONFIG_MASK) { LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt); rc = LY_EVALID; goto cleanup; } /* parse */ - LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup); + LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup); break; case LY_STMT_ORDERED_BY: /* single item */ - if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_ORDBY_MASK) { + if ((*(uint16_t *)substmt->storage_p) & LYS_ORDBY_MASK) { LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt); rc = LY_EVALID; goto cleanup; } /* parse */ - LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup); + LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup); break; case LY_STMT_STATUS: /* single item */ - if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_STATUS_MASK) { + if ((*(uint16_t *)substmt->storage_p) & LYS_STATUS_MASK) { LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt); rc = LY_EVALID; goto cleanup; } /* parse */ - LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup); + LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup); break; default: diff --git a/src/parser_xml.c b/src/parser_xml.c index 0db10ca..34d6fdc 100644 --- a/src/parser_xml.c +++ b/src/parser_xml.c @@ -54,6 +54,30 @@ lyd_xml_ctx_free(struct lyd_ctx *lydctx) } /** + * @brief Log namespace error. + * + * @param[in] xmlctx XML context + * @param[in] prefix XML prefix. + * @param[in] prefix_len XML prefix length. + * @param[in] attr_name Current XML attribute name. + * @param[in] attr_len Current XML attribute name length. + */ +static void +lydxml_log_namespace_err(struct lyxml_ctx *xmlctx, const char *prefix, size_t prefix_len, + const char *attr_name, size_t attr_len) +{ + if (prefix_len && attr_len) { + LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\" at attribute \"%.*s\".", + (int)prefix_len, prefix, (int)attr_len, attr_name); + } else if (prefix_len) { + LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", + (int)prefix_len, prefix); + } else { + LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing XML namespace."); + } +} + +/** * @brief Parse and create XML metadata. * * @param[in] lydctx XML data parser context. @@ -109,8 +133,10 @@ lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, str if (lydctx->parse_opts & LYD_PARSE_STRICT) { LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".", (int)xmlctx->name_len, xmlctx->name); - ret = LY_EVALID; - goto cleanup; + /* If LYD_VALIDATE_MULTI_ERROR is set, then continue parsing, because otherwise the parser context + * will remain in a bad state, which will cause termination on some assert or undefined behavior. + */ + LY_DPARSER_ERR_GOTO(LY_EVALID, ret = LY_EVALID, lydctx, cleanup); } /* skip attr */ @@ -123,8 +149,7 @@ lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, str /* get namespace of the attribute to find its annotation definition */ ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len); if (!ns) { - /* unknown namespace, XML error */ - LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)xmlctx->prefix_len, xmlctx->prefix); + lydxml_log_namespace_err(xmlctx, xmlctx->prefix, xmlctx->prefix_len, xmlctx->name, xmlctx->name_len); ret = LY_ENOTFOUND; goto cleanup; } @@ -215,7 +240,7 @@ lydxml_attrs(struct lyxml_ctx *xmlctx, struct lyd_attr **attr) if (prefix_len) { ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len); if (!ns) { - LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix); + lydxml_log_namespace_err(xmlctx, prefix, prefix_len, name, name_len); ret = LY_EVALID; goto cleanup; } @@ -441,7 +466,9 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size { struct lyd_node_opaq *opaq; char *ptr; - long num; + /* this needs to be at least 64bit, and it "should not" be an explicit int64_t + * because the code calls strtoll later on, which "might" return a bigger type */ + long long num; *hints = 0; *anchor = NULL; @@ -453,11 +480,11 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size /* boolean value */ *hints |= LYD_VALHINT_BOOLEAN; } else { - num = strtol(value, &ptr, 10); + num = strtoll(value, &ptr, 10); if ((unsigned)(ptr - value) == value_len) { /* number value */ *hints |= LYD_VALHINT_DECNUM; - if ((num < INT32_MIN) || (num > (long)UINT32_MAX)) { + if ((num < INT32_MIN) || (num > UINT32_MAX)) { /* large number */ *hints |= LYD_VALHINT_NUM64; } @@ -535,12 +562,7 @@ lydxml_subtree_get_snode(struct lyd_xml_ctx *lydctx, const struct lyd_node *pare if (lydctx->int_opts & LYD_INTOPT_ANY) { goto unknown_module; } - - if (prefix_len) { - LOGVAL(ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix); - } else { - LOGVAL(ctx, LYVE_REFERENCE, "Missing XML namespace."); - } + lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0); return LY_EVALID; } @@ -1056,14 +1078,13 @@ lydxml_subtree_r(struct lyd_xml_ctx *lydctx, struct lyd_node *parent, struct lyd /* create metadata/attributes */ if (xmlctx->status == LYXML_ATTRIBUTE) { if (snode) { - rc = lydxml_metadata(lydctx, snode, &meta); - LY_CHECK_GOTO(rc, cleanup); + r = lydxml_metadata(lydctx, snode, &meta); } else { assert(lydctx->parse_opts & LYD_PARSE_OPAQ); - rc = lydxml_attrs(xmlctx, &attr); - LY_CHECK_GOTO(rc, cleanup); + r = lydxml_attrs(xmlctx, &attr); } } + LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup); assert(xmlctx->status == LYXML_ELEM_CONTENT); if (!snode) { @@ -1175,7 +1196,7 @@ lydxml_envelope(struct lyxml_ctx *xmlctx, const char *name, const char *uri, ly_ prefix_len = xmlctx->prefix_len; ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len); if (!ns) { - LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix); + lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0); return LY_EVALID; } else if (strcmp(ns->uri, uri)) { /* different namespace */ @@ -1399,7 +1420,7 @@ lydxml_opaq_r(struct lyxml_ctx *xmlctx, struct lyd_node *parent) prefix_len = xmlctx->prefix_len; ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len); if (!ns) { - LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix); + lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0); return LY_EVALID; } diff --git a/src/parser_yang.c b/src/parser_yang.c index 8511d26..57b5f9b 100644 --- a/src/parser_yang.c +++ b/src/parser_yang.c @@ -596,6 +596,7 @@ get_argument(struct lysp_yang_ctx *ctx, enum yang_arg arg, uint16_t *flags, char size_t buf_len = 0; uint8_t prefix = 0; ly_bool str_end = 0; + int comment; /* word buffer - dynamically allocated */ *word_b = NULL; @@ -627,18 +628,30 @@ get_argument(struct lysp_yang_ctx *ctx, enum yang_arg arg, uint16_t *flags, char str_end = 1; break; case '/': + comment = 0; if (ctx->in->current[1] == '/') { /* one-line comment */ - MOVE_INPUT(ctx, 2); - LY_CHECK_GOTO(ret = skip_comment(ctx, 1), error); + comment = 1; } else if (ctx->in->current[1] == '*') { /* block comment */ - MOVE_INPUT(ctx, 2); - LY_CHECK_GOTO(ret = skip_comment(ctx, 2), error); + comment = 2; } else { /* not a comment after all */ LY_CHECK_GOTO(ret = buf_store_char(ctx, arg, word_p, word_len, word_b, &buf_len, 0, &prefix), error); } + + if (comment) { + if (*word_len) { + /* invalid comment sequence (RFC 7950 sec. 6.1.3.) */ + LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Invalid comment sequence \"%.2s\" in an unquoted string.", ctx->in->current); + ret = LY_EVALID; + goto error; + } + + /* skip the comment */ + MOVE_INPUT(ctx, 2); + LY_CHECK_GOTO(ret = skip_comment(ctx, comment), error); + } break; case ' ': if (*word_len) { @@ -838,6 +851,8 @@ keyword_start: /* fall through */ default: MOVE_INPUT(ctx, 1); + /* fall through */ + case '\0': LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start, "a keyword followed by a separator"); return LY_EVALID; @@ -982,8 +997,16 @@ parse_ext(struct lysp_yang_ctx *ctx, const char *ext_name, size_t ext_name_len, e->parent_stmt_index = parent_stmt_index; YANG_READ_SUBSTMT_FOR_GOTO(ctx, kw, word, word_len, ret, cleanup) { - LY_CHECK_GOTO(ret = parse_ext_substmt(ctx, kw, word, word_len, &e->child), cleanup) - YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, NULL, ret, cleanup); + switch (kw) { + case LY_STMT_EXTENSION_INSTANCE: + LY_CHECK_GOTO(parse_ext(ctx, word, word_len, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts), cleanup); + break; + default: + /* just store all the statements */ + LY_CHECK_GOTO(ret = parse_ext_substmt(ctx, kw, word, word_len, &e->child), cleanup) + break; + } + YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, e->exts, ret, cleanup); } cleanup: diff --git a/src/parser_yin.c b/src/parser_yin.c index 3924d0e..eab9c37 100644 --- a/src/parser_yin.c +++ b/src/parser_yin.c @@ -4,7 +4,7 @@ * @author Michal Vasko <mvasko@cesnet.cz> * @brief YIN parser. * - * Copyright (c) 2015 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2015 - 2024 CESNET, z.s.p.o. * * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. @@ -3409,6 +3409,14 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum if (ctx->xmlctx->ws_only) { LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); while (ctx->xmlctx->status == LYXML_ELEMENT) { + /* BUG nested extensions will not be parsed because we are not able to dinsguish between them + * and the argument of this extension, in case there is one and its 'yin-element' is 'true' + stmt = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, + ctx->xmlctx->prefix_len, LY_STMT_EXTENSION_INSTANCE); + if (stmt == LY_STMT_EXTENSION_INSTANCE) { + LY_CHECK_RET(yin_parse_extension_instance(ctx, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts)); + } else { */ + LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem)); if (!e->child) { e->child = new_subelem; @@ -3420,6 +3428,9 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE); LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); } + + /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */ + LY_CHECK_RET(yin_unres_exts_add(ctx, e->exts)); } else if (ctx->xmlctx->value_len) { /* invalid text content */ LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \"%.*s\".", ext_name, @@ -708,7 +708,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_ /* store the value */ LOG_LOCSET(key, NULL); - ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0, + ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0, NULL, format, prefix_data, LYD_HINT_DATA, key, NULL); LOG_LOCBACK(1, 0); LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup); @@ -736,7 +736,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_ /* names (keys) are unique - it was checked when parsing */ LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.", lys_nodetype2str(ctx_node->nodetype), ctx_node->name); - ly_path_predicates_free(ctx, *predicates); + ly_path_predicates_free(ctx_node->module->ctx, *predicates); *predicates = NULL; ret = LY_EVALID; goto cleanup; @@ -771,12 +771,10 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_ } /* store the value */ - if (ctx_node) { - LOG_LOCSET(ctx_node, NULL); - } - ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0, + LOG_LOCSET(ctx_node, NULL); + ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0, NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL); - LOG_LOCBACK(ctx_node ? 1 : 0, 0); + LOG_LOCBACK(1, 0); LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup); ++(*tok_idx); @@ -1093,7 +1091,7 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node } lref = (const struct lysc_type_leafref *)deref_leaf_node->type; LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup); - ly_path_free(ctx, path2); + ly_path_free(path2); path2 = NULL; /* compile dereferenced leafref expression and append it to the path */ @@ -1101,7 +1099,7 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node &path2), cleanup); node2 = path2[LY_ARRAY_COUNT(path2) - 1].node; LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup); - ly_path_free(ctx, path2); + ly_path_free(path2); path2 = NULL; /* properly parsed path must always continue with ')' and '/' */ @@ -1125,9 +1123,9 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup); cleanup: - ly_path_free(ctx, path2); + ly_path_free(path2); if (ret) { - ly_path_free(ctx, *path); + ly_path_free(*path); *path = NULL; } return ret; @@ -1283,7 +1281,7 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con cleanup: if (ret) { - ly_path_free(ctx, *path); + ly_path_free(*path); *path = NULL; } LOG_LOCBACK(cur_node ? 1 : 0, 0); @@ -1488,7 +1486,7 @@ ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *pred } void -ly_path_free(const struct ly_ctx *ctx, struct ly_path *path) +ly_path_free(struct ly_path *path) { LY_ARRAY_COUNT_TYPE u; @@ -1497,7 +1495,7 @@ ly_path_free(const struct ly_ctx *ctx, struct ly_path *path) } LY_ARRAY_FOR(path, u) { - ly_path_predicates_free(ctx, path[u].predicates); + ly_path_predicates_free(path[u].node->module->ctx, path[u].predicates); } LY_ARRAY_FREE(path); } @@ -257,9 +257,8 @@ void ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate /** * @brief Free ly_path structure. * - * @param[in] ctx libyang context. * @param[in] path The structure ([sized array](@ref sizedarrays)) to free. */ -void ly_path_free(const struct ly_ctx *ctx, struct ly_path *path); +void ly_path_free(struct ly_path *path); #endif /* LY_PATH_H_ */ diff --git a/src/plugins.c b/src/plugins.c index 5ff6616..22c4947 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -81,6 +81,11 @@ extern const struct lyplg_type_record plugins_xpath10[]; extern const struct lyplg_type_record plugins_node_instanceid[]; /* + * libnetconf2-netconf-server + */ +extern const struct lyplg_type_record plugins_time_period[]; + +/* * lyds_tree */ extern const struct lyplg_type_record plugins_lyds_tree[]; @@ -522,6 +527,9 @@ lyplg_init(ly_bool builtin_type_plugins_only) LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_hex_string), error); LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_xpath10), error); + /* libnetconf2-netconf-server */ + LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_time_period), error); + /* ietf-netconf-acm */ LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_node_instanceid), error); diff --git a/src/plugins.h b/src/plugins.h index 3ffc7cf..b635878 100644 --- a/src/plugins.h +++ b/src/plugins.h @@ -38,19 +38,22 @@ extern "C" { * Furthermore, there are several internal plugins, implementing built-in data types and selected derived types and YANG * extensions. These internal plugins uses the same API and can be taken as examples for implementing user plugins. Internal * plugins are always loaded with the first created [context](@ref howtoContext) and unloaded with destroying the last one. - * The external plugins are in the same phase loaded from the default directories specified at compile time via cmake - * variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added for each plugin type) or separately - * via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default directories can be replaced runtime - * using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`. + * The external plugins are in the same phase loaded as dynamic shared objects (shared libraries) from the default directories + * specified at compile time via cmake variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added + * for each plugin type) or separately via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default + * directories can be replaced runtime using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`. + * There is also a separate function ::lyplg_add() to manually add a plugin (dynamic shared object) anytime later. + * Another option to manually add an external plugin is using the ::lyplg_add_extension_plugin() or ::lyplg_add_type_plugin() + * which is useful when loading a dynamic shared object is problematic. These functions allow for setting the necessary callbacks + * for the plugin at runtime. * * Order of the plugins determines their priority. libyang searches for the first match with the extension and type, so the * firstly loaded plugin for the specific item is used. Since the internal plugins are loaded always before the external * plugins, the internal plugins cannot be replaced. * - * There is also a separate function ::lyplg_add() to add a plugin anytime later. Note, that such a plugin is being used - * after it is added with the lowest priority among other already loaded plugins. Also note that since all the plugins are - * unloaded with the destruction of the last context, creating a new context after that starts the standard plugins - * initiation and the manually added plugins are not loaded automatically. + * Note, that manually added plugin via lyplg_add*() function is added with the lowest priority among other already loaded plugins. + * Also note that since all the plugins are unloaded with the destruction of the last context, creating a new context after that + * starts the standard plugins initiation and the manually added plugins are not loaded automatically. * * The following pages contain description of the API for creating user plugins. * diff --git a/src/plugins_exts.c b/src/plugins_exts.c index cffbe53..71449ba 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -4,7 +4,7 @@ * @author Michal Vasko <mvasko@cesnet.cz> * @brief helper functions for extension plugins * - * Copyright (c) 2019 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2019 - 2024 CESNET, z.s.p.o. * * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. @@ -81,34 +81,34 @@ cleanup: * @brief Compile an instance extension statement. * * @param[in] ctx Compile context. - * @param[in] parsed Parsed ext instance substatement structure. + * @param[in] parsed_p Parsed ext instance substatement structure. * @param[in] ext Compiled ext instance. * @param[in] substmt Compled ext instance substatement info. * @return LY_ERR value. */ static LY_ERR -lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc_ext_instance *ext, +lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, void **parsed_p, struct lysc_ext_instance *ext, struct lysc_ext_substmt *substmt) { LY_ERR rc = LY_SUCCESS; ly_bool length_restr = 0; LY_DATA_TYPE basetype; - assert(parsed); + assert(*parsed_p); /* compilation wthout any storage */ if (substmt->stmt == LY_STMT_IF_FEATURE) { ly_bool enabled; /* evaluate */ - LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, VOIDPTR_C(parsed), &enabled), cleanup); + LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, *parsed_p, &enabled), cleanup); if (!enabled) { /* it is disabled, remove the whole extension instance */ rc = LY_ENOT; } } - if (!substmt->storage) { + if (!substmt->storage_p) { /* nothing to store */ goto cleanup; } @@ -133,7 +133,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc struct lysc_node *node; lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags); - pnodes = VOIDPTR_C(parsed); + pnodes = *parsed_p; /* compile nodes */ LY_LIST_FOR(pnodes, pnode) { @@ -163,7 +163,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc case LY_STMT_REFERENCE: case LY_STMT_UNITS: /* just make a copy */ - LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, VOIDPTR_C(parsed), 0, VOIDPTR_C(substmt->storage)), cleanup); + LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, *parsed_p, 0, (const char **)substmt->storage_p), cleanup); break; case LY_STMT_BIT: @@ -175,7 +175,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc } /* compile */ - rc = lys_compile_type_enums(ctx, VOIDPTR_C(parsed), basetype, NULL, VOIDPTR_C(substmt->storage)); + rc = lys_compile_type_enums(ctx, *parsed_p, basetype, NULL, (struct lysc_type_bitenum_item **)substmt->storage_p); LY_CHECK_GOTO(rc, cleanup); break; @@ -183,7 +183,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc uint16_t flags; if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) { - memcpy(&flags, &parsed, 2); + memcpy(&flags, parsed_p, 2); if (flags & LYS_CONFIG_MASK) { /* explicitly set */ flags |= LYS_SET_CONFIG; @@ -194,56 +194,56 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc /* default config */ flags = LYS_CONFIG_W; } - memcpy(VOIDPTR_C(substmt->storage), &flags, 2); + memcpy(substmt->storage_p, &flags, 2); } /* else leave zero */ break; } case LY_STMT_MUST: { - const struct lysp_restr *restrs = VOIDPTR_C(parsed); + const struct lysp_restr *restrs = *parsed_p; /* sized array */ - COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)VOIDPTR_C(substmt->storage), lys_compile_must, rc, cleanup); + COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)substmt->storage_p, lys_compile_must, rc, cleanup); break; } case LY_STMT_WHEN: { const uint16_t flags; - const struct lysp_when *when = VOIDPTR_C(parsed); + const struct lysp_when *when = *parsed_p; /* read compiled status */ lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags); /* compile */ - LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, VOIDPTR_C(substmt->storage)), cleanup); + LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, (struct lysc_when **)substmt->storage_p), cleanup); break; } case LY_STMT_FRACTION_DIGITS: case LY_STMT_REQUIRE_INSTANCE: /* just make a copy */ - memcpy(VOIDPTR_C(substmt->storage), &parsed, 1); + memcpy(substmt->storage_p, parsed_p, 1); break; case LY_STMT_MANDATORY: case LY_STMT_ORDERED_BY: case LY_STMT_STATUS: /* just make a copy */ - memcpy(VOIDPTR_C(substmt->storage), &parsed, 2); + memcpy(substmt->storage_p, parsed_p, 2); break; case LY_STMT_MAX_ELEMENTS: case LY_STMT_MIN_ELEMENTS: /* just make a copy */ - memcpy(VOIDPTR_C(substmt->storage), &parsed, 4); + memcpy(substmt->storage_p, parsed_p, 4); break; case LY_STMT_POSITION: case LY_STMT_VALUE: /* just make a copy */ - memcpy(VOIDPTR_C(substmt->storage), &parsed, 8); + memcpy(substmt->storage_p, parsed_p, 8); break; case LY_STMT_IDENTITY: /* compile */ - rc = lys_identity_precompile(ctx, NULL, NULL, VOIDPTR_C(parsed), VOIDPTR_C(substmt->storage)); + rc = lys_identity_precompile(ctx, NULL, NULL, *parsed_p, (struct lysc_ident **)substmt->storage_p); LY_CHECK_GOTO(rc, cleanup); break; @@ -252,36 +252,36 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc /* fallthrough */ case LY_STMT_RANGE: /* compile, use uint64 default range */ - rc = lys_compile_type_range(ctx, VOIDPTR_C(parsed), LY_TYPE_UINT64, length_restr, 0, NULL, VOIDPTR_C(substmt->storage)); + rc = lys_compile_type_range(ctx, *parsed_p, LY_TYPE_UINT64, length_restr, 0, NULL, (struct lysc_range **)substmt->storage_p); LY_CHECK_GOTO(rc, cleanup); break; case LY_STMT_PATTERN: /* compile */ - rc = lys_compile_type_patterns(ctx, VOIDPTR_C(parsed), NULL, VOIDPTR_C(substmt->storage)); + rc = lys_compile_type_patterns(ctx, *parsed_p, NULL, (struct lysc_pattern ***)substmt->storage_p); LY_CHECK_GOTO(rc, cleanup); break; case LY_STMT_TYPE: { const uint16_t flags; const char *units; - const struct lysp_type *ptype = VOIDPTR_C(parsed); + const struct lysp_type *ptype = *parsed_p; /* read compiled info */ lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags); lyplg_ext_get_storage(ext, LY_STMT_UNITS, sizeof units, (const void **)&units); /* compile */ - rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, VOIDPTR_C(substmt->storage), &units, NULL); + rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, (struct lysc_type **)substmt->storage_p, &units, NULL); LY_CHECK_GOTO(rc, cleanup); - LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)VOIDPTR_C(substmt->storage))->refcount); + LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)substmt->storage_p)->refcount); break; } case LY_STMT_EXTENSION_INSTANCE: { - struct lysp_ext_instance *extps = VOIDPTR_C(parsed); + struct lysp_ext_instance *extps = *parsed_p; /* compile sized array */ - COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)VOIDPTR_C(substmt->storage), ext, rc, cleanup); + COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)substmt->storage_p, ext, rc, cleanup); break; } case LY_STMT_AUGMENT: @@ -330,7 +330,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext LY_ERR rc = LY_SUCCESS; LY_ARRAY_COUNT_TYPE u, v; enum ly_stmt stmtp; - uint64_t storagep; + void **storagep; struct ly_set storagep_compiled = {0}; LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, ctx, extp, ext, LY_EINVAL); @@ -340,9 +340,9 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext LY_ARRAY_FOR(extp->substmts, u) { stmtp = extp->substmts[u].stmt; - storagep = *(uint64_t *)VOIDPTR_C(extp->substmts[u].storage); + storagep = extp->substmts[u].storage_p; - if (!storagep || ly_set_contains(&storagep_compiled, VOIDPTR_C(storagep), NULL)) { + if (!*storagep || ly_set_contains(&storagep_compiled, storagep, NULL)) { /* nothing parsed or already compiled (for example, if it is a linked list of parsed nodes) */ continue; } @@ -361,7 +361,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext } /* compiled */ - ly_set_add(&storagep_compiled, VOIDPTR_C(storagep), 1, NULL); + ly_set_add(&storagep_compiled, storagep, 1, NULL); } cleanup: @@ -420,7 +420,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct uint32_t i; struct lysc_node *schema; - LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL); LY_ARRAY_FOR(ext->substmts, i) { switch (ext->substmts[i].stmt) { @@ -437,7 +437,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct case LY_STMT_LEAF: case LY_STMT_LEAF_LIST: case LY_STMT_LIST: - schema = *VOIDPTR2_C(ext->substmts[i].storage); + schema = *ext->substmts[i].storage_p; if (schema) { rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb); return rc; @@ -458,7 +458,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct uint32_t i; struct lysp_node *schema; - LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL); LY_ARRAY_FOR(ext->substmts, i) { switch (ext->substmts[i].stmt) { @@ -475,7 +475,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct case LY_STMT_LEAF: case LY_STMT_LEAF_LIST: case LY_STMT_LIST: - schema = *VOIDPTR2_C(ext->substmts[i].storage); + schema = *ext->substmts[i].storage_p; if (schema) { rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb); return rc; @@ -494,7 +494,7 @@ lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc { struct lyspr_tree_schema *new; - LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL); if (!nodes) { return LY_SUCCESS; @@ -514,7 +514,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp { struct lyspr_tree_schema *new; - LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL); if (!nodes) { return LY_SUCCESS; @@ -531,7 +531,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp LIBYANG_API_DECL LY_ERR lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_priv, void (*free_clb)(void *plugin_priv)) { - LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL); ((struct lyspr_tree_ctx *)ctx)->plugin_priv = plugin_priv; ((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb; @@ -587,12 +587,12 @@ lyplg_ext_nodetype2stmt(uint16_t nodetype) } LY_ERR -lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t *storage_p) +lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp) { LY_ARRAY_COUNT_TYPE u; enum ly_stmt match = 0; - *storage_p = 0; + *storage_pp = NULL; if (!(stmt & LY_STMT_NODE_MASK)) { /* matching a non-node statement */ @@ -601,7 +601,7 @@ lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t LY_ARRAY_FOR(ext->substmts, u) { if ((match && (ext->substmts[u].stmt == match)) || (!match && (ext->substmts[u].stmt & stmt))) { - *storage_p = ext->substmts[u].storage; + *storage_pp = ext->substmts[u].storage_p; return LY_SUCCESS; } } @@ -613,14 +613,14 @@ LIBYANG_API_DEF LY_ERR lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage) { LY_ERR rc = LY_SUCCESS; - uint64_t s; + void **s_p; /* get pointer to the storage, is set even on error */ - rc = lyplg_ext_get_storage_p(ext, stmt, &s); + rc = lyplg_ext_get_storage_p(ext, stmt, &s_p); /* assign */ - if (s) { - memcpy(storage, VOIDPTR_C(s), storage_size); + if (s_p) { + memcpy(storage, s_p, storage_size); } else { memset(storage, 0, storage_size); } @@ -634,7 +634,9 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint LY_ARRAY_COUNT_TYPE u; const struct lysp_ext_instance *extp = NULL; enum ly_stmt match = 0; - uint64_t s = 0; + void **s_p = NULL; + + LY_CHECK_ARG_RET(NULL, ext, ext->module->parsed, LY_EINVAL); /* find the parsed ext instance */ LY_ARRAY_FOR(ext->module->parsed->exts, u) { @@ -655,14 +657,14 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint /* get the substatement */ LY_ARRAY_FOR(extp->substmts, u) { if ((match && (extp->substmts[u].stmt == match)) || (!match && (extp->substmts[u].stmt & stmt))) { - s = extp->substmts[u].storage; + s_p = extp->substmts[u].storage_p; break; } } /* assign */ - if (s) { - memcpy(storage, VOIDPTR_C(s), storage_size); + if (s_p) { + memcpy(storage, s_p, storage_size); } else { memset(storage, 0, storage_size); } diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 74ce215..4cf80b2 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -109,7 +109,7 @@ extern "C" { /** * @brief Extensions API version */ -#define LYPLG_EXT_API_VERSION 6 +#define LYPLG_EXT_API_VERSION 8 /** * @brief Mask for an operation statement. @@ -393,7 +393,7 @@ struct lysp_stmt { */ struct lysp_ext_substmt { enum ly_stmt stmt; /**< parsed substatement */ - uint64_t storage; /**< (pointer to) the parsed storage of the statement according to the specific + void **storage_p; /**< pointer to the parsed storage of the statement according to the specific lys_ext_substmt::stmt */ }; @@ -419,6 +419,7 @@ struct lysp_ext_instance { parsed data ([sized array](@ref sizedarrays)) */ void *parsed; /**< private plugin parsed data */ struct lysp_stmt *child; /**< list of generic (unknown) YANG statements */ + struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ }; /** @@ -426,7 +427,7 @@ struct lysp_ext_instance { */ struct lysc_ext_substmt { enum ly_stmt stmt; /**< compiled substatement */ - uint64_t storage; /**< (pointer to) the compiled storage of the statement according to the specific + void **storage_p; /**< pointer to the compiled storage of the statement according to the specific lys_ext_substmt::stmt */ }; diff --git a/src/plugins_exts/metadata.c b/src/plugins_exts/metadata.c index aa6cb43..baec86f 100644 --- a/src/plugins_exts/metadata.c +++ b/src/plugins_exts/metadata.c @@ -79,27 +79,27 @@ annotation_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_IF_FEATURE; - ext->substmts[0].storage = (uint64_t)(uintptr_t)&ann_pdata->iffeatures; + ext->substmts[0].storage_p = (void **)&ann_pdata->iffeatures; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_UNITS; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&ann_pdata->units; + ext->substmts[1].storage_p = (void **)&ann_pdata->units; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_STATUS; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&ann_pdata->flags; + ext->substmts[2].storage_p = (void **)&ann_pdata->flags; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[3].stmt = LY_STMT_TYPE; - ext->substmts[3].storage = (uint64_t)(uintptr_t)&ann_pdata->type; + ext->substmts[3].storage_p = (void **)&ann_pdata->type; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[4].stmt = LY_STMT_DESCRIPTION; - ext->substmts[4].storage = (uint64_t)(uintptr_t)&ann_pdata->dsc; + ext->substmts[4].storage_p = (void **)&ann_pdata->dsc; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[5].stmt = LY_STMT_REFERENCE; - ext->substmts[5].storage = (uint64_t)(uintptr_t)&ann_pdata->ref; + ext->substmts[5].storage_p = (void **)&ann_pdata->ref; if ((r = lyplg_ext_parse_extension_instance(pctx, ext))) { return r; @@ -139,27 +139,27 @@ annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_IF_FEATURE; - ext->substmts[0].storage = 0; + ext->substmts[0].storage_p = NULL; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_UNITS; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&ann_cdata->units; + ext->substmts[1].storage_p = (void **)&ann_cdata->units; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_STATUS; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&ann_cdata->flags; + ext->substmts[2].storage_p = (void **)&ann_cdata->flags; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[3].stmt = LY_STMT_TYPE; - ext->substmts[3].storage = (uint64_t)(uintptr_t)&ann_cdata->type; + ext->substmts[3].storage_p = (void **)&ann_cdata->type; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[4].stmt = LY_STMT_DESCRIPTION; - ext->substmts[4].storage = (uint64_t)(uintptr_t)&ann_cdata->dsc; + ext->substmts[4].storage_p = (void **)&ann_cdata->dsc; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[5].stmt = LY_STMT_REFERENCE; - ext->substmts[5].storage = (uint64_t)(uintptr_t)&ann_cdata->ref; + ext->substmts[5].storage_p = (void **)&ann_cdata->ref; ret = lyplg_ext_compile_extension_instance(cctx, extp, ext); return ret; diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c index bc2ea0e..6aa902e 100644 --- a/src/plugins_exts/structure.c +++ b/src/plugins_exts/structure.c @@ -90,60 +90,60 @@ structure_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) /* parse substatements */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_MUST; - ext->substmts[0].storage = (uint64_t)(uintptr_t)&struct_pdata->musts; + ext->substmts[0].storage_p = (void **)&struct_pdata->musts; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_STATUS; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&struct_pdata->flags; + ext->substmts[1].storage_p = (void **)&struct_pdata->flags; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_DESCRIPTION; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&struct_pdata->dsc; + ext->substmts[2].storage_p = (void **)&struct_pdata->dsc; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[3].stmt = LY_STMT_REFERENCE; - ext->substmts[3].storage = (uint64_t)(uintptr_t)&struct_pdata->ref; + ext->substmts[3].storage_p = (void **)&struct_pdata->ref; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[4].stmt = LY_STMT_TYPEDEF; - ext->substmts[4].storage = (uint64_t)(uintptr_t)&struct_pdata->typedefs; + ext->substmts[4].storage_p = (void **)&struct_pdata->typedefs; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[5].stmt = LY_STMT_GROUPING; - ext->substmts[5].storage = (uint64_t)(uintptr_t)&struct_pdata->groupings; + ext->substmts[5].storage_p = (void **)&struct_pdata->groupings; /* data-def-stmt */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[6].stmt = LY_STMT_CONTAINER; - ext->substmts[6].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[6].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[7].stmt = LY_STMT_LEAF; - ext->substmts[7].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[7].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[8].stmt = LY_STMT_LEAF_LIST; - ext->substmts[8].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[8].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[9].stmt = LY_STMT_LIST; - ext->substmts[9].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[9].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[10].stmt = LY_STMT_CHOICE; - ext->substmts[10].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[10].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[11].stmt = LY_STMT_ANYDATA; - ext->substmts[11].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[11].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[12].stmt = LY_STMT_ANYXML; - ext->substmts[12].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[12].storage_p = (void **)&struct_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[13].stmt = LY_STMT_USES; - ext->substmts[13].storage = (uint64_t)(uintptr_t)&struct_pdata->child; + ext->substmts[13].storage_p = (void **)&struct_pdata->child; rc = lyplg_ext_parse_extension_instance(pctx, ext); return rc; @@ -190,60 +190,60 @@ structure_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, s LY_ARRAY_CREATE_GOTO(cctx->ctx, ext->substmts, 14, rc, emem); LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_MUST; - ext->substmts[0].storage = (uint64_t)(uintptr_t)&struct_cdata->musts; + ext->substmts[0].storage_p = (void **)&struct_cdata->musts; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_STATUS; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&struct_cdata->flags; + ext->substmts[1].storage_p = (void **)&struct_cdata->flags; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_DESCRIPTION; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&struct_cdata->dsc; + ext->substmts[2].storage_p = (void **)&struct_cdata->dsc; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[3].stmt = LY_STMT_REFERENCE; - ext->substmts[3].storage = (uint64_t)(uintptr_t)&struct_cdata->ref; + ext->substmts[3].storage_p = (void **)&struct_cdata->ref; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[4].stmt = LY_STMT_TYPEDEF; - ext->substmts[4].storage = 0; + ext->substmts[4].storage_p = 0; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[5].stmt = LY_STMT_GROUPING; - ext->substmts[5].storage = 0; + ext->substmts[5].storage_p = 0; /* data-def-stmt */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[6].stmt = LY_STMT_CONTAINER; - ext->substmts[6].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[6].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[7].stmt = LY_STMT_LEAF; - ext->substmts[7].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[7].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[8].stmt = LY_STMT_LEAF_LIST; - ext->substmts[8].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[8].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[9].stmt = LY_STMT_LIST; - ext->substmts[9].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[9].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[10].stmt = LY_STMT_CHOICE; - ext->substmts[10].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[10].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[11].stmt = LY_STMT_ANYDATA; - ext->substmts[11].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[11].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[12].stmt = LY_STMT_ANYXML; - ext->substmts[12].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[12].storage_p = (void **)&struct_cdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[13].stmt = LY_STMT_USES; - ext->substmts[13].storage = (uint64_t)(uintptr_t)&struct_cdata->child; + ext->substmts[13].storage_p = (void **)&struct_cdata->child; *lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED; rc = lyplg_ext_compile_extension_instance(cctx, extp, ext); @@ -339,53 +339,53 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) /* parse substatements */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_STATUS; - ext->substmts[0].storage = (uint64_t)(uintptr_t)&aug_pdata->flags; + ext->substmts[0].storage_p = (void **)&aug_pdata->flags; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_DESCRIPTION; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&aug_pdata->dsc; + ext->substmts[1].storage_p = (void **)&aug_pdata->dsc; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_REFERENCE; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&aug_pdata->ref; + ext->substmts[2].storage_p = (void **)&aug_pdata->ref; /* data-def-stmt */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[3].stmt = LY_STMT_CONTAINER; - ext->substmts[3].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[3].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[4].stmt = LY_STMT_LEAF; - ext->substmts[4].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[4].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[5].stmt = LY_STMT_LEAF_LIST; - ext->substmts[5].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[5].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[6].stmt = LY_STMT_LIST; - ext->substmts[6].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[6].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[7].stmt = LY_STMT_CHOICE; - ext->substmts[7].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[7].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[8].stmt = LY_STMT_ANYDATA; - ext->substmts[8].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[8].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[9].stmt = LY_STMT_ANYXML; - ext->substmts[9].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[9].storage_p = (void **)&aug_pdata->child; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[10].stmt = LY_STMT_USES; - ext->substmts[10].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[10].storage_p = (void **)&aug_pdata->child; /* case */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[11].stmt = LY_STMT_CASE; - ext->substmts[11].storage = (uint64_t)(uintptr_t)&aug_pdata->child; + ext->substmts[11].storage_p = (void **)&aug_pdata->child; if ((rc = lyplg_ext_parse_extension_instance(pctx, ext))) { return rc; @@ -394,7 +394,7 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) /* add fake parsed augment node */ LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[12].stmt = LY_STMT_AUGMENT; - ext->substmts[12].storage = (uint64_t)(uintptr_t)&aug_pdata->aug; + ext->substmts[12].storage_p = (void **)&aug_pdata->aug; aug_pdata->aug = calloc(1, sizeof *aug_pdata->aug); if (!aug_pdata->aug) { @@ -476,7 +476,7 @@ structure_aug_sprinter_ptree(struct lysp_ext_instance *ext, const struct lyspr_t assert(ctx); - aug = (struct lysp_node_augment **)(uintptr_t)ext->substmts[12].storage; + aug = (struct lysp_node_augment **)ext->substmts[12].storage_p; rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, (*aug)->child, structure_sprinter_pnode); return rc; diff --git a/src/plugins_exts/yangdata.c b/src/plugins_exts/yangdata.c index c9c5dd8..1736abc 100644 --- a/src/plugins_exts/yangdata.c +++ b/src/plugins_exts/yangdata.c @@ -58,15 +58,15 @@ yangdata_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) LY_ARRAY_CREATE_GOTO(lyplg_ext_parse_get_cur_pmod(pctx)->mod->ctx, ext->substmts, 3, ret, emem); LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_CONTAINER; - ext->substmts[0].storage = (uint64_t)(uintptr_t)&ext->parsed; + ext->substmts[0].storage_p = (void **)&ext->parsed; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_CHOICE; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&ext->parsed; + ext->substmts[1].storage_p = (void **)&ext->parsed; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_USES; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&ext->parsed; + ext->substmts[2].storage_p = (void **)&ext->parsed; if ((ret = lyplg_ext_parse_extension_instance(pctx, ext))) { return ret; @@ -96,15 +96,15 @@ yangdata_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, st LY_ARRAY_CREATE_GOTO(cctx->ctx, ext->substmts, 3, ret, emem); LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[0].stmt = LY_STMT_CONTAINER; - ext->substmts[0].storage = (uint64_t)(uintptr_t)&ext->compiled; + ext->substmts[0].storage_p = (void **)&ext->compiled; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[1].stmt = LY_STMT_CHOICE; - ext->substmts[1].storage = (uint64_t)(uintptr_t)&ext->compiled; + ext->substmts[1].storage_p = (void **)&ext->compiled; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[2].stmt = LY_STMT_USES; - ext->substmts[2].storage = (uint64_t)(uintptr_t)&ext->compiled; + ext->substmts[2].storage_p = (void **)&ext->compiled; *lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED; ret = lyplg_ext_compile_extension_instance(cctx, extp, ext); diff --git a/src/plugins_types.c b/src/plugins_types.c index 8305691..3373b0b 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -352,10 +352,16 @@ lyplg_type_print_simple(const struct ly_ctx *UNUSED(ctx), const struct lyd_value LIBYANG_API_DEF LY_ERR lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup) { - memset(dup, 0, sizeof *dup); - LY_CHECK_RET(lydict_insert(ctx, original->_canonical, 0, &dup->_canonical)); + LY_ERR r; + + if ((r = lydict_dup(ctx, original->_canonical, &dup->_canonical))) { + /* in case of error NULL the values so that freeing does not fail */ + memset(dup, 0, sizeof *dup); + return r; + } memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem); dup->realtype = original->realtype; + return LY_SUCCESS; } @@ -831,8 +837,9 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_ uint32_t prefix_opt = 0; struct ly_err_item *e; const char *err_fmt = NULL; + uint16_t oper; - LY_CHECK_ARG_RET(ctx, ctx, value, ctx_node, path, err, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, value, path, err, LY_EINVAL); *path = NULL; *err = NULL; @@ -871,8 +878,8 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_ } /* resolve it on schema tree */ - ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node->flags & LYS_IS_OUTPUT) ? - LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path); + oper = (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT; + ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, oper, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path); if (ret) { err_fmt = "Invalid instance-identifier \"%.*s\" value - semantic error%s%s"; goto cleanup; @@ -888,7 +895,7 @@ cleanup: ly_err_clean((struct ly_ctx *)ctx, e); } - ly_path_free(ctx, *path); + ly_path_free(*path); *path = NULL; } @@ -896,9 +903,9 @@ cleanup: } LIBYANG_API_DEF void -lyplg_type_lypath_free(const struct ly_ctx *ctx, struct ly_path *path) +lyplg_type_lypath_free(const struct ly_ctx *UNUSED(ctx), struct ly_path *path) { - ly_path_free(ctx, path); + ly_path_free(path); } LIBYANG_API_DEF LY_ERR @@ -1007,7 +1014,7 @@ lyplg_type_resolve_leafref_get_target_path(const struct lyxp_expr *path, const s LY_CHECK_GOTO(lyxp_expr_parse(ctx_node->module->ctx, str_path, 0, 1, target_path), cleanup); cleanup: - ly_path_free(ctx_node->module->ctx, p); + ly_path_free(p); free(str_path); return rc; } diff --git a/src/plugins_types.h b/src/plugins_types.h index 8598c5d..06acc38 100644 --- a/src/plugins_types.h +++ b/src/plugins_types.h @@ -475,8 +475,10 @@ LIBYANG_API_DECL LY_ERR lyplg_type_print_xpath10_value(const struct lyd_value_xp #define LYPLG_TYPE_STORE_IMPLEMENT 0x02 /**< If a foreign module is needed to be implemented to successfully instantiate the value, make the module implemented. */ #define LYPLG_TYPE_STORE_IS_UTF8 0x04 /**< The value is guaranteed to be a valid UTF-8 string, if applicable for the type. */ -#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only. The validation must be done using [validate](@ref lyplg_type_validate_clb) */ -/** @} plugintypestoreopts */ +#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only, type-specific validation is skipped (performed before) */ +/** + * @} plugintypestoreopts + */ /** * @brief Callback to store the given @p value according to the given @p type. @@ -490,7 +492,9 @@ LIBYANG_API_DECL LY_ERR lyplg_type_print_xpath10_value(const struct lyd_value_xp * @p value_len is always correct. All store functions have to free a dynamically allocated @p value in all * cases (even on error). * - * @param[in] ctx libyang context + * No unnecessary validation tasks should be performed by this callback and left for ::lyplg_type_validate_clb instead. + * + * @param[in] ctx libyang context. * @param[in] type Type of the value being stored. * @param[in] value Value to be stored. * @param[in] value_len Length (number of bytes) of the given @p value. @@ -513,15 +517,14 @@ LIBYANG_API_DECL typedef LY_ERR (*lyplg_type_store_clb)(const struct ly_ctx *ctx const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err); /** - * @brief Callback to validate the stored value in data. + * @brief Callback to validate the stored value in the accessible data tree. * - * This callback is optional for types that can only be validated in a data tree. It must be called and succeed - * in case the ::lyplg_type_store_clb callback returned ::LY_EINCOMPLETE for the value to be valid. However, this - * callback can be called even in other cases (such as separate/repeated validation). + * This callback is optional and may not be defined for types that do not require the accessible data tree for + * validation (::lyplg_type_store_cb fully stores and validates the value). * - * @param[in] ctx libyang context + * @param[in] ctx libyang context. * @param[in] type Original type of the value (not necessarily the stored one) being validated. - * @param[in] ctx_node The value data context node for validation. + * @param[in] ctx_node Value data context node for validation. * @param[in] tree External data tree (e.g. when validating RPC/Notification) with possibly referenced data. * @param[in,out] storage Storage of the value successfully filled by ::lyplg_type_store_clb. May be modified. * @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic @@ -619,7 +622,7 @@ struct lyplg_type { const char *id; /**< Plugin identification (mainly for distinguish incompatible versions when used by external tools) */ lyplg_type_store_clb store; /**< store and canonize the value in the type-specific way */ - lyplg_type_validate_clb validate; /**< optional, validate the value in the type-specific way in data */ + lyplg_type_validate_clb validate; /**< optional, validate the value in the accessible data tree */ lyplg_type_compare_clb compare; /**< comparison callback to compare 2 values of the same type */ lyplg_type_sort_clb sort; /**< comparison callback for sorting values */ lyplg_type_print_clb print; /**< printer callback to get string representing the value */ @@ -948,18 +951,6 @@ LIBYANG_API_DECL LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err); /** - * @brief Implementation of ::lyplg_type_compare_clb for the built-in instance-identifier type. - */ -LIBYANG_API_DECL LY_ERR lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, - const struct lyd_value *val2); - -/** - * @brief Implementation of ::lyplg_type_sort_clb for the built-in instance-identifier type. - */ -LIBYANG_API_DEF int lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, - const struct lyd_value *val2); - -/** * @brief Implementation of ::lyplg_type_print_clb for the built-in instance-identifier type. */ LIBYANG_API_DECL const void *lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c index c70b4a0..a020438 100644 --- a/src/plugins_types/binary.c +++ b/src/plugins_types/binary.c @@ -42,8 +42,6 @@ */ static const char b64_etable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static LY_ERR lyplg_type_validate_binary(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err); - /** * @brief Encode binary value into a base64 string value. * @@ -260,6 +258,7 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type, struct ly_err_item **err) { LY_ERR ret = LY_SUCCESS; + struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type; struct lyd_value_binary *val; /* init storage */ @@ -312,15 +311,20 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type, ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical); options &= ~LYPLG_TYPE_STORE_DYNAMIC; LY_CHECK_GOTO(ret, cleanup); + + /* value may have been freed */ + value = storage->_canonical; } else { ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical); LY_CHECK_GOTO(ret, cleanup); } if (!(options & LYPLG_TYPE_STORE_ONLY)) { - /* validate value */ - ret = lyplg_type_validate_binary(ctx, type, NULL, NULL, storage, err); - LY_CHECK_GOTO(ret, cleanup); + /* validate length restriction of the binary value */ + if (type_bin->length) { + ret = lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } } cleanup: @@ -334,33 +338,6 @@ cleanup: return ret; } -/** - * @brief Implementation of ::lyplg_type_validate_clb for the binary type. - */ -static LY_ERR -lyplg_type_validate_binary(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), - const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err) -{ - struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type; - struct lyd_value_binary *val; - const void *value; - size_t value_len; - - LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL); - - val = LYPLG_TYPE_VAL_IS_DYN(val) ? (struct lyd_value_binary *)(storage->dyn_mem) : (struct lyd_value_binary *)(storage->fixed_mem); - value = lyd_value_get_canonical(ctx, storage); - value_len = strlen(value); - *err = NULL; - - /* length restriction of the binary value */ - if (type_bin->length) { - LY_CHECK_RET(lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err)); - } - - return LY_SUCCESS; -} - LIBYANG_API_DEF LY_ERR lyplg_type_compare_binary(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2) { @@ -496,7 +473,7 @@ const struct lyplg_type_record plugins_binary[] = { .plugin.id = "libyang 2 - binary, version 1", .plugin.store = lyplg_type_store_binary, - .plugin.validate = lyplg_type_validate_binary, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_binary, .plugin.sort = lyplg_type_sort_binary, .plugin.print = lyplg_type_print_binary, diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c index 1cc0ec4..1d013c1 100644 --- a/src/plugins_types/date_and_time.c +++ b/src/plugins_types/date_and_time.c @@ -53,7 +53,6 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type struct ly_err_item **err) { LY_ERR ret = LY_SUCCESS; - struct lysc_type_str *type_dat = (struct lysc_type_str *)type; struct lyd_value_date_and_time *val; uint32_t i; char c; @@ -102,20 +101,9 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction, there can be only ASCII chars */ - if (type_dat->length) { - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_dat->length, value_len, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - } - - /* date-and-time pattern */ - ret = lyplg_type_validate_patterns(type_dat->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - - /* convert to UNIX time and fractions of second */ - ret = ly_time_str2time(value, &val->time, &val->fractions_s); - if (ret) { - ret = ly_err_new(err, ret, 0, NULL, NULL, "%s", ly_last_logmsg()); + /* convert to UNIX time and fractions of second, function must check for all the possible errors */ + if (ly_time_str2time(value, &val->time, &val->fractions_s)) { + ret = ly_err_new(err, LY_EVALID, 0, NULL, NULL, "%s", ly_last_logmsg()); goto cleanup; } diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c index 0eb01a0..a6ac54b 100644 --- a/src/plugins_types/decimal64.c +++ b/src/plugins_types/decimal64.c @@ -33,8 +33,6 @@ * | 8 | yes | `int64_t *` | little-endian value represented without floating point | */ -static LY_ERR lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err); - /** * @brief Convert decimal64 number to canonical string. * @@ -90,7 +88,7 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ { struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type; LY_ERR ret = LY_SUCCESS; - int64_t num; + int64_t num = 0; char *canon; /* init storage */ @@ -144,8 +142,12 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ if (!(options & LYPLG_TYPE_STORE_ONLY)) { /* validate value */ - ret = lyplg_type_validate_decimal64(ctx, type, NULL, NULL, storage, err); - LY_CHECK_GOTO(ret, cleanup); + if (type_dec->range) { + /* check range of the number */ + ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical, + strlen(storage->_canonical), err); + LY_CHECK_GOTO(ret, cleanup); + } } cleanup: @@ -159,31 +161,6 @@ cleanup: return ret; } -/** - * @brief Implementation of ::lyplg_type_validate_clb for the built-in decimal64 type. - */ -static LY_ERR -lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), - const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err) -{ - LY_ERR ret; - struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type; - int64_t num; - - LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL); - *err = NULL; - num = storage->dec64; - - if (type_dec->range) { - /* check range of the number */ - ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical, - strlen(storage->_canonical), err); - LY_CHECK_RET(ret); - } - - return LY_SUCCESS; -} - LIBYANG_API_DEF LY_ERR lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2) @@ -262,7 +239,7 @@ const struct lyplg_type_record plugins_decimal64[] = { .plugin.id = "libyang 2 - decimal64, version 1", .plugin.store = lyplg_type_store_decimal64, - .plugin.validate = lyplg_type_validate_decimal64, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_decimal64, .plugin.sort = lyplg_type_sort_decimal64, .plugin.print = lyplg_type_print_decimal64, diff --git a/src/plugins_types/hex_string.c b/src/plugins_types/hex_string.c index 9f8d80a..b013cf4 100644 --- a/src/plugins_types/hex_string.c +++ b/src/plugins_types/hex_string.c @@ -55,17 +55,6 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - } - - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* make a copy, it is needed for canonization */ if ((format != LY_VALUE_CANON) && !(options & LYPLG_TYPE_STORE_DYNAMIC)) { value = strndup(value, value_len); @@ -83,12 +72,28 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical); options &= ~LYPLG_TYPE_STORE_DYNAMIC; LY_CHECK_GOTO(ret, cleanup); + + /* value may have been freed */ + value = storage->_canonical; } else { /* store directly */ ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical); LY_CHECK_GOTO(ret, cleanup); } + if (!(options & LYPLG_TYPE_STORE_ONLY)) { + /* validate length restriction of the string */ + if (type_str->length) { + /* value_len is in bytes, but we need number of characters here */ + ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + + /* validate pattern restrictions */ + ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + cleanup: if (options & LYPLG_TYPE_STORE_DYNAMIC) { free((void *)value); diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c index 00ad45a..46bb4ba 100644 --- a/src/plugins_types/instanceid.c +++ b/src/plugins_types/instanceid.c @@ -252,23 +252,14 @@ lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type return LY_SUCCESS; } -LIBYANG_API_DEF LY_ERR -lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) -{ - return lyplg_type_compare_simple(ctx, val1, val2); -} - -LIBYANG_API_DEF int -lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) -{ - return lyplg_type_sort_simple(ctx, val1, val2); -} - LIBYANG_API_DEF const void * -lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format, +lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len) { - char *ret; + char *ret = NULL; + struct ly_path *p = NULL; + const struct ly_path *target; + struct ly_err_item *err; if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) { if (dynamic) { @@ -280,14 +271,34 @@ lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_v return value->_canonical; } + if (!value->target) { + /* schema default value, compile it first */ + if (lyplg_type_lypath_new(ctx, value->_canonical, strlen(value->_canonical), 0, LY_VALUE_JSON, NULL, NULL, + NULL, &p, &err)) { + if (err) { + ly_err_print(ctx, err); + ly_err_free(err); + } + goto cleanup; + } + + target = p; + } else { + target = value->target; + } + /* print the value in the specific format */ - if (instanceid_path2str(value->target, format, prefix_data, &ret)) { - return NULL; + if (instanceid_path2str(target, format, prefix_data, &ret)) { + goto cleanup; } + *dynamic = 1; if (value_len) { *value_len = strlen(ret); } + +cleanup: + ly_path_free(p); return ret; } @@ -295,6 +306,7 @@ LIBYANG_API_DEF LY_ERR lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup) { LY_ERR ret; + struct ly_err_item *err; memset(dup, 0, sizeof *dup); @@ -302,9 +314,21 @@ lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *orig ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical); LY_CHECK_GOTO(ret, error); - /* copy path */ - ret = ly_path_dup(ctx, original->target, &dup->target); - LY_CHECK_GOTO(ret, error); + if (!original->target) { + /* schema default value, needs to be compiled */ + if (lyplg_type_lypath_new(ctx, original->_canonical, strlen(original->_canonical), 0, LY_VALUE_JSON, NULL, NULL, + NULL, &dup->target, &err)) { + if (err) { + ly_err_print(ctx, err); + ly_err_free(err); + } + goto error; + } + } else { + /* copy path */ + ret = ly_path_dup(ctx, original->target, &dup->target); + LY_CHECK_GOTO(ret, error); + } dup->realtype = original->realtype; return LY_SUCCESS; @@ -319,7 +343,7 @@ lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value) { lydict_remove(ctx, value->_canonical); value->_canonical = NULL; - ly_path_free(ctx, value->target); + ly_path_free(value->target); } /** @@ -338,8 +362,8 @@ const struct lyplg_type_record plugins_instanceid[] = { .plugin.id = "libyang 2 - instance-identifier, version 1", .plugin.store = lyplg_type_store_instanceid, .plugin.validate = lyplg_type_validate_instanceid, - .plugin.compare = lyplg_type_compare_instanceid, - .plugin.sort = lyplg_type_sort_instanceid, + .plugin.compare = lyplg_type_compare_simple, + .plugin.sort = lyplg_type_sort_simple, .plugin.print = lyplg_type_print_instanceid, .plugin.duplicate = lyplg_type_dup_instanceid, .plugin.free = lyplg_type_free_instanceid, diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c index eb66499..ac165ac 100644 --- a/src/plugins_types/integer.c +++ b/src/plugins_types/integer.c @@ -36,9 +36,6 @@ * | 1/2/4/8 | yes | pointer to the specific integer type | little-endian integer value | */ -static LY_ERR lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err); -static LY_ERR lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err); - /** * @brief LYB value size of each integer type. */ @@ -53,6 +50,7 @@ lyplg_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, con const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err) { + struct lysc_type_num *type_num = (struct lysc_type_num *)type; LY_ERR ret = LY_SUCCESS; int64_t num = 0; int base = 1; @@ -157,9 +155,12 @@ lyplg_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, con } if (!(options & LYPLG_TYPE_STORE_ONLY)) { - /* validate value */ - ret = lyplg_type_validate_int(ctx, type, NULL, NULL, storage, err); - LY_CHECK_GOTO(ret, cleanup); + /* validate range of the number */ + if (type_num->range) { + ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical, + strlen(storage->_canonical), err); + LY_CHECK_GOTO(ret, cleanup); + } } cleanup: @@ -173,48 +174,6 @@ cleanup: return ret; } -/** - * @brief Implementation of ::lyplg_type_validate_clb for the signed interger types. - */ -static LY_ERR -lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), - const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err) -{ - LY_ERR ret; - struct lysc_type_num *type_num = (struct lysc_type_num *)type; - int64_t num; - - LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL); - *err = NULL; - - /* set the value (matters for big-endian) and get the correct int64 number */ - switch (type->basetype) { - case LY_TYPE_INT8: - num = storage->int8; - break; - case LY_TYPE_INT16: - num = storage->int16; - break; - case LY_TYPE_INT32: - num = storage->int32; - break; - case LY_TYPE_INT64: - num = storage->int64; - break; - default: - return LY_EINVAL; - } - - /* validate range of the number */ - if (type_num->range) { - ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical, - strlen(storage->_canonical), err); - LY_CHECK_RET(ret); - } - - return LY_SUCCESS; -} - LIBYANG_API_DEF LY_ERR lyplg_type_compare_int(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2) { @@ -357,6 +316,7 @@ lyplg_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, co const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err) { + struct lysc_type_num *type_num = (struct lysc_type_num *)type; LY_ERR ret = LY_SUCCESS; uint64_t num = 0; int base = 0; @@ -441,9 +401,12 @@ lyplg_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, co } if (!(options & LYPLG_TYPE_STORE_ONLY)) { - /* validate value */ - ret = lyplg_type_validate_uint(ctx, type, NULL, NULL, storage, err); - LY_CHECK_GOTO(ret, cleanup); + /* validate range of the number */ + if (type_num->range) { + ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical, + strlen(storage->_canonical), err); + LY_CHECK_GOTO(ret, cleanup); + } } cleanup: @@ -457,48 +420,6 @@ cleanup: return ret; } -/** - * @brief Implementation of ::lyplg_type_validate_clb for the unsigned interger types. - */ -static LY_ERR -lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), - const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err) -{ - LY_ERR ret; - struct lysc_type_num *type_num = (struct lysc_type_num *)type; - uint64_t num; - - LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL); - *err = NULL; - - /* set the value (matters for big-endian) and get the correct int64 number */ - switch (type->basetype) { - case LY_TYPE_UINT8: - num = storage->uint8; - break; - case LY_TYPE_UINT16: - num = storage->uint16; - break; - case LY_TYPE_UINT32: - num = storage->uint32; - break; - case LY_TYPE_UINT64: - num = storage->uint64; - break; - default: - return LY_EINVAL; - } - - /* validate range of the number */ - if (type_num->range) { - ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical, - strlen(storage->_canonical), err); - LY_CHECK_RET(ret); - } - - return LY_SUCCESS; -} - LIBYANG_API_DEF LY_ERR lyplg_type_compare_uint(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2) { @@ -646,7 +567,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_uint, - .plugin.validate = lyplg_type_validate_uint, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, .plugin.sort = lyplg_type_sort_uint, .plugin.print = lyplg_type_print_uint, @@ -660,7 +581,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_uint, - .plugin.validate = lyplg_type_validate_uint, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, .plugin.sort = lyplg_type_sort_uint, .plugin.print = lyplg_type_print_uint, @@ -674,7 +595,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_uint, - .plugin.validate = lyplg_type_validate_uint, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, .plugin.sort = lyplg_type_sort_uint, .plugin.print = lyplg_type_print_uint, @@ -688,7 +609,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_uint, - .plugin.validate = lyplg_type_validate_uint, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, .plugin.sort = lyplg_type_sort_uint, .plugin.print = lyplg_type_print_uint, @@ -702,7 +623,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_int, - .plugin.validate = lyplg_type_validate_int, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, .plugin.sort = lyplg_type_sort_int, .plugin.print = lyplg_type_print_int, @@ -716,7 +637,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_int, - .plugin.validate = lyplg_type_validate_int, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, .plugin.sort = lyplg_type_sort_int, .plugin.print = lyplg_type_print_int, @@ -730,7 +651,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_int, - .plugin.validate = lyplg_type_validate_int, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, .plugin.sort = lyplg_type_sort_int, .plugin.print = lyplg_type_print_int, @@ -744,7 +665,7 @@ const struct lyplg_type_record plugins_integer[] = { .plugin.id = "libyang 2 - integers, version 1", .plugin.store = lyplg_type_store_int, - .plugin.validate = lyplg_type_validate_int, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, .plugin.sort = lyplg_type_sort_int, .plugin.print = lyplg_type_print_int, diff --git a/src/plugins_types/ipv4_address.c b/src/plugins_types/ipv4_address.c index 022689b..0ed6d36 100644 --- a/src/plugins_types/ipv4_address.c +++ b/src/plugins_types/ipv4_address.c @@ -171,17 +171,19 @@ lyplg_type_store_ipv4_address(const struct ly_ctx *ctx, const struct lysc_type * ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + if (!(options & LYPLG_TYPE_STORE_ONLY)) { + /* length restriction of the string */ + if (type_str->length) { + /* value_len is in bytes, but we need number of characters here */ + ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + + /* pattern restrictions */ + ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* get the network-byte order address */ ret = ipv4address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err); LY_CHECK_GOTO(ret, cleanup); diff --git a/src/plugins_types/ipv4_address_no_zone.c b/src/plugins_types/ipv4_address_no_zone.c index 4438306..5a0f009 100644 --- a/src/plugins_types/ipv4_address_no_zone.c +++ b/src/plugins_types/ipv4_address_no_zone.c @@ -57,7 +57,6 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys struct ly_err_item **err) { LY_ERR ret = LY_SUCCESS; - struct lysc_type_str *type_str = (struct lysc_type_str *)type; struct lyd_value_ipv4_address_no_zone *val; /* init storage */ @@ -85,17 +84,6 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - } - - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* we always need a dynamic value */ if (!(options & LYPLG_TYPE_STORE_DYNAMIC)) { value = strndup(value, value_len); @@ -104,7 +92,7 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys options |= LYPLG_TYPE_STORE_DYNAMIC; } - /* get the network-byte order address */ + /* get the network-byte order address, validates the value */ if (!inet_pton(AF_INET, value, &val->addr)) { ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Failed to convert IPv4 address \"%s\".", (char *)value); goto cleanup; diff --git a/src/plugins_types/ipv4_prefix.c b/src/plugins_types/ipv4_prefix.c index 2a86f36..4d1916e 100644 --- a/src/plugins_types/ipv4_prefix.c +++ b/src/plugins_types/ipv4_prefix.c @@ -156,17 +156,19 @@ lyplg_type_store_ipv4_prefix(const struct ly_ctx *ctx, const struct lysc_type *t ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + if (!(options & LYPLG_TYPE_STORE_ONLY)) { + /* length restriction of the string */ + if (type_str->length) { + /* value_len is in bytes, but we need number of characters here */ + ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + + /* pattern restrictions */ + ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* get the mask in network-byte order */ ret = ipv4prefix_str2ip(value, value_len, &val->addr, &val->prefix, err); LY_CHECK_GOTO(ret, cleanup); diff --git a/src/plugins_types/ipv6_address.c b/src/plugins_types/ipv6_address.c index 8ddcd18..147df3e 100644 --- a/src/plugins_types/ipv6_address.c +++ b/src/plugins_types/ipv6_address.c @@ -172,17 +172,19 @@ lyplg_type_store_ipv6_address(const struct ly_ctx *ctx, const struct lysc_type * ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + if (!(options & LYPLG_TYPE_STORE_ONLY)) { + /* length restriction of the string */ + if (type_str->length) { + /* value_len is in bytes, but we need number of characters here */ + ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + + /* pattern restrictions */ + ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* get the network-byte order address */ ret = ipv6address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err); LY_CHECK_GOTO(ret, cleanup); diff --git a/src/plugins_types/ipv6_address_no_zone.c b/src/plugins_types/ipv6_address_no_zone.c index caa2c8f..76d47ae 100644 --- a/src/plugins_types/ipv6_address_no_zone.c +++ b/src/plugins_types/ipv6_address_no_zone.c @@ -96,7 +96,6 @@ lyplg_type_store_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lys struct ly_err_item **err) { LY_ERR ret = LY_SUCCESS; - struct lysc_type_str *type_str = (struct lysc_type_str *)type; struct lyd_value_ipv6_address_no_zone *val; /* init storage */ @@ -136,18 +135,7 @@ lyplg_type_store_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lys ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - } - - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - - /* get the network-byte order address */ + /* get the network-byte order address, validates the value */ ret = ipv6addressnozone_str2ip(value, value_len, options, &val->addr, err); LY_CHECK_GOTO(ret, cleanup); diff --git a/src/plugins_types/ipv6_prefix.c b/src/plugins_types/ipv6_prefix.c index 05b1be7..4643e85 100644 --- a/src/plugins_types/ipv6_prefix.c +++ b/src/plugins_types/ipv6_prefix.c @@ -170,17 +170,19 @@ lyplg_type_store_ipv6_prefix(const struct ly_ctx *ctx, const struct lysc_type *t ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + if (!(options & LYPLG_TYPE_STORE_ONLY)) { + /* length restriction of the string */ + if (type_str->length) { + /* value_len is in bytes, but we need number of characters here */ + ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + + /* pattern restrictions */ + ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* get the mask in network-byte order */ ret = ipv6prefix_str2ip(value, value_len, &val->addr, &val->prefix, err); LY_CHECK_GOTO(ret, cleanup); diff --git a/src/plugins_types/leafref.c b/src/plugins_types/leafref.c index fee2ef9..5863895 100644 --- a/src/plugins_types/leafref.c +++ b/src/plugins_types/leafref.c @@ -41,19 +41,19 @@ lyplg_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err) { - LY_ERR ret = LY_SUCCESS; + LY_ERR rc = LY_SUCCESS; struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type; assert(type_lr->realtype); /* store the value as the real type of the leafref target */ - ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data, + rc = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data, hints, ctx_node, storage, unres, err); - if (ret == LY_EINCOMPLETE) { + if (rc == LY_EINCOMPLETE) { /* it is irrelevant whether the target type needs some resolving */ - ret = LY_SUCCESS; + rc = LY_SUCCESS; } - LY_CHECK_RET(ret); + LY_CHECK_RET(rc); if (type_lr->require_instance) { /* needs to be resolved */ @@ -67,7 +67,7 @@ LIBYANG_API_DEF LY_ERR lyplg_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err) { - LY_ERR ret; + LY_ERR rc = LY_SUCCESS; struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type; char *errmsg = NULL, *path; struct ly_set *targets = NULL; @@ -80,24 +80,25 @@ lyplg_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *ty return LY_SUCCESS; } - ret = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree, (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg); - if (ret != LY_SUCCESS) { + rc = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree, + (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg); + if (rc) { path = lyd_path(ctx_node, LYD_PATH_STD, NULL, 0); - ret = ly_err_new(err, LY_EVALID, LYVE_DATA, path, strdup("instance-required"), "%s", errmsg); + rc = ly_err_new(err, LY_EVALID, LYVE_DATA, path, strdup("instance-required"), "%s", errmsg); free(errmsg); goto cleanup; } if (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) { for (i = 0; i < targets->count; ++i) { - ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node); - LY_CHECK_GOTO(ret, cleanup); + rc = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node); + LY_CHECK_GOTO(rc, cleanup); } } cleanup: ly_set_free(targets, NULL); - return ret; + return rc; } LIBYANG_API_DEF LY_ERR diff --git a/src/plugins_types/node_instanceid.c b/src/plugins_types/node_instanceid.c index 21448e3..7c80e30 100644 --- a/src/plugins_types/node_instanceid.c +++ b/src/plugins_types/node_instanceid.c @@ -312,8 +312,8 @@ const struct lyplg_type_record plugins_node_instanceid[] = { .plugin.id = "libyang 2 - node-instance-identifier, version 1", .plugin.store = lyplg_type_store_node_instanceid, .plugin.validate = NULL, - .plugin.compare = lyplg_type_compare_instanceid, - .plugin.sort = lyplg_type_sort_instanceid, + .plugin.compare = lyplg_type_compare_simple, + .plugin.sort = lyplg_type_sort_simple, .plugin.print = lyplg_type_print_node_instanceid, .plugin.duplicate = lyplg_type_dup_instanceid, .plugin.free = lyplg_type_free_instanceid, @@ -327,8 +327,8 @@ const struct lyplg_type_record plugins_node_instanceid[] = { .plugin.id = "libyang 2 - node-instance-identifier, version 1", .plugin.store = lyplg_type_store_node_instanceid, .plugin.validate = NULL, - .plugin.compare = lyplg_type_compare_instanceid, - .plugin.sort = lyplg_type_sort_instanceid, + .plugin.compare = lyplg_type_compare_simple, + .plugin.sort = lyplg_type_sort_simple, .plugin.print = lyplg_type_print_node_instanceid, .plugin.duplicate = lyplg_type_dup_instanceid, .plugin.free = lyplg_type_free_instanceid, diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c index 2ad0035..d1888f3 100644 --- a/src/plugins_types/string.c +++ b/src/plugins_types/string.c @@ -34,8 +34,6 @@ * | string length | yes | `char *` | string itself | */ -static LY_ERR lyplg_type_validate_string(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err); - /** * @brief Check string value for invalid characters. * @@ -65,6 +63,7 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err) { + struct lysc_type_str *type_str = (struct lysc_type_str *)type; LY_ERR ret = LY_SUCCESS; /* init storage */ @@ -86,14 +85,24 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type, ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical); options &= ~LYPLG_TYPE_STORE_DYNAMIC; LY_CHECK_GOTO(ret, cleanup); + + /* value may have been freed */ + value = storage->_canonical; } else { ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical); LY_CHECK_GOTO(ret, cleanup); } if (!(options & LYPLG_TYPE_STORE_ONLY)) { - /* validate value */ - ret = lyplg_type_validate_string(ctx, type, NULL, NULL, storage, err); + /* length restriction of the string */ + if (type_str->length) { + /* value_len is in bytes, but we need number of characters here */ + ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); + LY_CHECK_GOTO(ret, cleanup); + } + + /* pattern restrictions */ + ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -109,37 +118,6 @@ cleanup: } /** - * @brief Implementation of ::lyplg_type_validate_clb for the string type. - */ -static LY_ERR -lyplg_type_validate_string(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), - const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err) -{ - LY_ERR ret; - struct lysc_type_str *type_str = (struct lysc_type_str *)type; - const void *value; - size_t value_len; - - LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL); - value = lyd_value_get_canonical(ctx, storage); - value_len = strlen(value); - *err = NULL; - - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); - LY_CHECK_RET(ret); - } - - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_RET(ret); - - return LY_SUCCESS; -} - -/** * @brief Plugin information for string type implementation. * * Note that external plugins are supposed to use: @@ -154,7 +132,7 @@ const struct lyplg_type_record plugins_string[] = { .plugin.id = "libyang 2 - string, version 1", .plugin.store = lyplg_type_store_string, - .plugin.validate = lyplg_type_validate_string, + .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, .plugin.sort = lyplg_type_sort_simple, .plugin.print = lyplg_type_print_simple, diff --git a/src/plugins_types/time_period.c b/src/plugins_types/time_period.c new file mode 100644 index 0000000..e2fbcd6 --- /dev/null +++ b/src/plugins_types/time_period.c @@ -0,0 +1,100 @@ +/** + * @file time_period.c + * @author Roman Janota <janota@cesnet.cz> + * @brief libnetconf2-netconf-server time-period type plugin. + * + * Copyright (c) 2024 CESNET, z.s.p.o. + * + * This source code is licensed under BSD 3-Clause License (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + */ + +#include "plugins_types.h" + +#include <stdlib.h> +#include <string.h> + +#include "libyang.h" + +#include "compat.h" +#include "ly_common.h" +#include "plugins_internal.h" /* LY_TYPE_*_STR */ + +/** + * @page howtoDataLYB LYB Binary Format + * @subsection howtoDataLYBTypesTimePeriod time-period (libnetconf2-netconf-server) + * + * | Size (B) | Mandatory | Type | Meaning | + * | :------ | :-------: | :--: | :-----: | + * | string length | yes | `char *` | time in either months, weeks, days, or hours | + */ + +/** + * @brief Implementation of ::lyplg_type_sort_clb for libnetconf2-netconf-server time-period type. + * + * The values are sorted in descending order, i.e. the longest expiration time comes first. + */ +static int +lyplg_type_sort_time_period(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) +{ + const char *value1, *value2; + char unit1, unit2; + long v1, v2; + + value1 = lyd_value_get_canonical(ctx, val1); + value2 = lyd_value_get_canonical(ctx, val2); + + /* get the units (last character) and the values (all characters except the last one) */ + unit1 = value1[strlen(value1) - 1]; + unit2 = value2[strlen(value2) - 1]; + v1 = strtol(value1, NULL, 10); + v2 = strtol(value2, NULL, 10); + + /* descending order */ + if (unit1 == unit2) { + if (v1 > v2) { + return -1; + } else if (v1 == v2) { + return 0; + } else { + return 1; + } + } else if (unit1 == 'm') { + return -1; + } else if ((unit1 == 'w') && (unit2 != 'm')) { + return -1; + } else if ((unit1 == 'd') && (unit2 == 'h')) { + return -1; + } else { + return 1; + } +} + +/** + * @brief Plugin information for time-period type implementation. + * + * Note that external plugins are supposed to use: + * + * LYPLG_TYPES = { + */ +const struct lyplg_type_record plugins_time_period[] = { + { + .module = "libnetconf2-netconf-server", + .revision = "2024-07-09", + .name = "time-period", + + .plugin.id = "libyang 2 - time-period, version 1", + .plugin.store = lyplg_type_store_string, + .plugin.validate = NULL, + .plugin.compare = lyplg_type_compare_simple, + .plugin.sort = lyplg_type_sort_time_period, + .plugin.print = lyplg_type_print_simple, + .plugin.duplicate = lyplg_type_dup_simple, + .plugin.free = lyplg_type_free_simple, + .plugin.lyb_data_len = -1, + }, + {0} +}; diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index b494c95..51cca6c 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -493,7 +493,7 @@ lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, LIBYANG_API_DEF int lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) { - int ret; + int rc = LY_SUCCESS; LY_ARRAY_COUNT_TYPE u; struct lysc_type **types; @@ -502,20 +502,19 @@ lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, co } /* compare according to the order of types */ - ret = 0; types = ((struct lysc_type_union *)val1->realtype)->types; LY_ARRAY_FOR(types, u) { if (types[u] == val1->subvalue->value.realtype) { - ret = 1; + rc = 1; break; } else if (types[u] == val2->subvalue->value.realtype) { - ret = -1; + rc = -1; break; } } - assert(ret != 0); + assert(rc != 0); - return ret; + return rc; } /** diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c index 9376351..0c5dfce 100644 --- a/src/plugins_types/xpath1.0.c +++ b/src/plugins_types/xpath1.0.c @@ -248,7 +248,6 @@ lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type, struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err) { LY_ERR ret = LY_SUCCESS; - struct lysc_type_str *type_str = (struct lysc_type_str *)type; struct lyd_value_xpath10 *val; char *canon; @@ -262,17 +261,6 @@ lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type, ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err); LY_CHECK_GOTO(ret, cleanup); - /* length restriction of the string */ - if (type_str->length) { - /* value_len is in bytes, but we need number of characters here */ - ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - } - - /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); - LY_CHECK_GOTO(ret, cleanup); - /* parse */ ret = lyxp_expr_parse(ctx, value_len ? value : "", value_len, 1, &val->exp); LY_CHECK_GOTO(ret, cleanup); diff --git a/src/printer_yang.c b/src/printer_yang.c index 6dc06a8..3adcc2a 100644 --- a/src/printer_yang.c +++ b/src/printer_yang.c @@ -1162,7 +1162,7 @@ yprp_inout(struct lys_ypr_ctx *pctx, const struct lysp_node_action_inout *inout, ly_print_(pctx->out, "%*s%s {\n", INDENT, inout->name); LEVEL++; - yprp_extension_instances(pctx, LY_STMT_MUST, 0, inout->exts, NULL); + yprp_extension_instances(pctx, lyplg_ext_nodetype2stmt(inout->nodetype), 0, inout->exts, NULL); LY_ARRAY_FOR(inout->musts, u) { yprp_restr(pctx, &inout->musts[u], LY_STMT_MUST, NULL); } @@ -2563,7 +2563,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc break; } - LY_LIST_FOR(*VOIDPTR2_C(ext->substmts[u].storage), node) { + LY_LIST_FOR(*ext->substmts[u].storage_p, node) { ypr_open(pctx->out, flag); if (ext->substmts[u].stmt == LY_STMT_NOTIFICATION) { yprc_notification(pctx, (struct lysc_node_notif *)node); @@ -2592,32 +2592,32 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc case LY_STMT_PRESENCE: case LY_STMT_REFERENCE: case LY_STMT_UNITS: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { + if (*ext->substmts[u].storage_p) { ypr_open(pctx->out, flag); - ypr_substmt(pctx, ext->substmts[u].stmt, 0, *VOIDPTR2_C(ext->substmts[u].storage), 0, ext->exts); + ypr_substmt(pctx, ext->substmts[u].stmt, 0, *ext->substmts[u].storage_p, 0, ext->exts); } break; case LY_STMT_BIT: case LY_STMT_ENUM: { - const struct lysc_type_bitenum_item *items = *VOIDPTR2_C(ext->substmts[u].storage); + const struct lysc_type_bitenum_item *items = *ext->substmts[u].storage_p; yprc_bits_enum(pctx, items, ext->substmts[u].stmt == LY_STMT_BIT ? LY_TYPE_BITS : LY_TYPE_ENUM, flag); break; } case LY_STMT_CONFIG: - ypr_config(pctx, *(uint16_t *)VOIDPTR2_C(ext->substmts[u].storage), ext->exts, flag); + ypr_config(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag); break; case LY_STMT_EXTENSION_INSTANCE: - yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, *VOIDPTR2_C(ext->substmts[u].storage), flag); + yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, *ext->substmts[u].storage_p, flag); break; case LY_STMT_FRACTION_DIGITS: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { + if (*ext->substmts[u].storage_p) { ypr_unsigned(pctx, LY_STMT_FRACTION_DIGITS, 0, ext->exts, - (long unsigned int)*VOIDPTR2_C(ext->substmts[u].storage), flag); + (long unsigned int)*ext->substmts[u].storage_p, flag); } break; case LY_STMT_IDENTITY: { - const struct lysc_ident *idents = *VOIDPTR2_C(ext->substmts[u].storage); + const struct lysc_ident *idents = *ext->substmts[u].storage_p; LY_ARRAY_FOR(idents, v) { yprc_identity(pctx, &idents[v]); @@ -2625,15 +2625,15 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc break; } case LY_STMT_LENGTH: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { - yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_STRING, flag); + if (*ext->substmts[u].storage_p) { + yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_STRING, flag); } break; case LY_STMT_MANDATORY: - ypr_mandatory(pctx, *(uint16_t *)VOIDPTR_C(ext->substmts[u].storage), ext->exts, flag); + ypr_mandatory(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag); break; case LY_STMT_MAX_ELEMENTS: { - uint32_t max = *(uint32_t *)VOIDPTR_C(ext->substmts[u].storage); + uint32_t max = *(uint32_t *)ext->substmts[u].storage_p; if (max) { ypr_unsigned(pctx, LY_STMT_MAX_ELEMENTS, 0, ext->exts, max, flag); @@ -2644,15 +2644,15 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc break; } case LY_STMT_MIN_ELEMENTS: - ypr_unsigned(pctx, LY_STMT_MIN_ELEMENTS, 0, ext->exts, *(uint32_t *)VOIDPTR_C(ext->substmts[u].storage), flag); + ypr_unsigned(pctx, LY_STMT_MIN_ELEMENTS, 0, ext->exts, *(uint32_t *)ext->substmts[u].storage_p, flag); break; case LY_STMT_ORDERED_BY: ypr_open(pctx->out, flag); ypr_substmt(pctx, LY_STMT_ORDERED_BY, 0, - ((*(uint16_t *)VOIDPTR_C(ext->substmts[u].storage)) & LYS_ORDBY_USER) ? "user" : "system", 0, ext->exts); + ((*(uint16_t *)ext->substmts[u].storage_p) & LYS_ORDBY_USER) ? "user" : "system", 0, ext->exts); break; case LY_STMT_MUST: { - const struct lysc_must *musts = *VOIDPTR2_C(ext->substmts[u].storage); + const struct lysc_must *musts = *ext->substmts[u].storage_p; LY_ARRAY_FOR(musts, v) { yprc_must(pctx, &musts[v], flag); @@ -2660,7 +2660,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc break; } case LY_STMT_PATTERN: { - const struct lysc_pattern *patterns = *VOIDPTR2_C(ext->substmts[u].storage); + const struct lysc_pattern *patterns = *ext->substmts[u].storage_p; LY_ARRAY_FOR(patterns, v) { yprc_pattern(pctx, &patterns[v], flag); @@ -2668,36 +2668,36 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc break; } case LY_STMT_POSITION: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { - ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag); + if (*ext->substmts[u].storage_p) { + ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag); } break; case LY_STMT_VALUE: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { - ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag); + if (*ext->substmts[u].storage_p) { + ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag); } break; case LY_STMT_RANGE: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { - yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_UINT64, flag); + if (*ext->substmts[u].storage_p) { + yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_UINT64, flag); } break; case LY_STMT_REQUIRE_INSTANCE: ypr_open(pctx->out, flag); - ypr_substmt(pctx, LY_STMT_REQUIRE_INSTANCE, 0, *(uint8_t *)VOIDPTR_C(ext->substmts[u].storage) ? "true" : "false", + ypr_substmt(pctx, LY_STMT_REQUIRE_INSTANCE, 0, *(uint8_t *)ext->substmts[u].storage_p ? "true" : "false", 0, ext->exts); break; case LY_STMT_STATUS: - ypr_status(pctx, *(uint16_t *)VOIDPTR_C(ext->substmts[u].storage), ext->exts, flag); + ypr_status(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag); break; case LY_STMT_TYPE: - if (*VOIDPTR2_C(ext->substmts[u].storage)) { + if (*ext->substmts[u].storage_p) { ypr_open(pctx->out, flag); - yprc_type(pctx, *VOIDPTR2_C(ext->substmts[u].storage)); + yprc_type(pctx, *ext->substmts[u].storage_p); } break; case LY_STMT_WHEN: - yprc_when(pctx, *VOIDPTR2_C(ext->substmts[u].storage), flag); + yprc_when(pctx, *ext->substmts[u].storage_p, flag); break; case LY_STMT_AUGMENT: case LY_STMT_BASE: diff --git a/src/schema_compile.c b/src/schema_compile.c index aa9a3d0..d21f0dc 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -4,7 +4,7 @@ * @author Michal Vasko <mvasko@cesnet.cz> * @brief Schema compilation. * - * Copyright (c) 2015 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2015 - 2024 CESNET, z.s.p.o. * * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. @@ -172,7 +172,10 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys /* compile extension if not already */ LY_CHECK_GOTO(ret = lys_compile_extension(ctx, extp, &ext->def), cleanup); - /* compile */ + /* compile nested extensions */ + COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup); + + /* compile this extension */ if (ext->def->plugin && ext->def->plugin->compile) { if (ext->argument) { lysc_update_path(ctx, ext->module, ext->argument); @@ -218,7 +221,7 @@ lys_identity_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lysp const struct lysp_ident *identities_p, struct lysc_ident **identities) { LY_ARRAY_COUNT_TYPE u; - struct lysc_ctx cctx; + struct lysc_ctx cctx = {0}; struct lysc_ident *ident; LY_ERR ret = LY_SUCCESS; @@ -863,7 +866,7 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st /* get the target node */ target = p[LY_ARRAY_COUNT(p) - 1].node; - ly_path_free(node->module->ctx, p); + ly_path_free(p); if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) { LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.", @@ -960,6 +963,12 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc } LY_ATOMIC_INC_BARRIER(((struct lysc_type *)storage->realtype)->refcount); + if (storage->realtype->basetype == LY_TYPE_INST) { + /* ly_path includes references to other nodes, in case they are in foreign modules, the context would + * need to be freed in specific order to avoid accessing freed memory, so just avoid storing it */ + ly_path_free(storage->target); + storage->target = NULL; + } return LY_SUCCESS; } @@ -1453,7 +1462,7 @@ resolve_all: ret = ly_path_compile_leafref(cctx.ctx, l->node, cctx.ext, lref->path, (l->node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path); - ly_path_free(l->node->module->ctx, path); + ly_path_free(path); assert(ret != LY_ERECOMPILE); if (ret) { @@ -1468,7 +1477,7 @@ resolve_all: } cleanup: - lysf_ctx_erase(&cctx.free_ctx); + assert(!cctx.free_ctx.ext_set.count); return ret; } @@ -1548,8 +1557,8 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob } cleanup: + assert(!fctx.ext_set.count); lys_compile_unres_depset_erase(ctx, unres); - lysf_ctx_erase(&fctx); return ret; } @@ -1693,7 +1702,7 @@ lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error) LY_ERR lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) { - struct lysc_ctx ctx; + struct lysc_ctx ctx = {0}; struct lysc_module *mod_c = NULL; struct lysp_module *sp; struct lysp_submodule *submod; @@ -1814,7 +1823,7 @@ LY_ERR lys_compile_identities(struct lys_module *mod) { LY_ERR rc = LY_SUCCESS; - struct lysc_ctx ctx; + struct lysc_ctx ctx = {0}; struct lysp_submodule *submod; LY_ARRAY_COUNT_TYPE u; diff --git a/src/schema_compile.h b/src/schema_compile.h index d45156e..8f67ce3 100644 --- a/src/schema_compile.h +++ b/src/schema_compile.h @@ -67,7 +67,6 @@ struct lysc_ctx { * @param[in] CTX libyang context. */ #define LYSC_CTX_INIT_CTX(CCTX, CTX) \ - memset(&(CCTX), 0, sizeof (CCTX)); \ (CCTX).ctx = (CTX); \ (CCTX).path_len = 1; \ (CCTX).path[0] = '/'; \ @@ -81,7 +80,6 @@ struct lysc_ctx { * @param[in] EXT Ancestor extension instance. */ #define LYSC_CTX_INIT_PMOD(CCTX, PMOD, EXT) \ - memset(&(CCTX), 0, sizeof (CCTX)); \ (CCTX).ctx = (PMOD)->mod->ctx; \ (CCTX).cur_mod = (PMOD)->mod; \ (CCTX).pmod = (PMOD); \ @@ -164,9 +162,9 @@ struct lysc_unres_dflt { * @param[out] DUP Where to store the result. * @param[out] RET Where to store the return code. */ -#define DUP_STRING(CTX, ORIG, DUP, RET) RET = lydict_insert(CTX, ORIG, 0, &(DUP)) -#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_insert(CTX, ORIG, 0, &(DUP))) -#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lydict_insert(CTX, ORIG, 0, &(DUP)), GOTO) +#define DUP_STRING(CTX, ORIG, DUP, RET) RET = lydict_dup(CTX, ORIG, &(DUP)) +#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_dup(CTX, ORIG, &(DUP))) +#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lydict_dup(CTX, ORIG, &(DUP)), GOTO) #define DUP_ARRAY(CTX, ORIG_ARRAY, NEW_ARRAY, DUP_FUNC) \ if (ORIG_ARRAY) { \ diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index 4eac4ec..6179220 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -2218,7 +2218,7 @@ lys_precompile_own_augments_mod(struct lysc_ctx *ctx, const struct lysp_module * aug_p = NULL; LY_ARRAY_FOR(pmod->exts[u].substmts, v) { if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) { - aug_p = *VOIDPTR2_C(pmod->exts[u].substmts[v].storage); + aug_p = *(pmod->exts[u].substmts[v].storage_p); break; } } @@ -2443,7 +2443,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set * { LY_ERR ret = LY_SUCCESS; LY_ARRAY_COUNT_TYPE u, v; - struct lysc_ctx ctx; + struct lysc_ctx ctx = {0}; struct lys_module *m; struct lysp_node_augment *aug; struct ly_set set = {0}; @@ -2488,7 +2488,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set * aug = NULL; LY_ARRAY_FOR(pmod->exts[u].substmts, v) { if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) { - aug = *VOIDPTR2_C(pmod->exts[u].substmts[v].storage); + aug = *(pmod->exts[u].substmts[v].storage_p); break; } } diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index a627799..d57d8a7 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1390,7 +1390,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) { (*pattern)->inverted = 1; } - DUP_STRING_GOTO(ctx->ctx, &patterns_p[u].arg.str[1], (*pattern)->expr, ret, done); + LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, &patterns_p[u].arg.str[1], 0, &(*pattern)->expr), done); DUP_STRING_GOTO(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag, ret, done); DUP_STRING_GOTO(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg, ret, done); DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, ret, done); @@ -2582,10 +2582,10 @@ lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct } } else { /* top-level element */ - struct lysc_node **list; + struct lysc_node **list = NULL; if (ctx->ext) { - lyplg_ext_get_storage_p(ctx->ext, LY_STMT_DATA_NODE_MASK, (uint64_t *)&list); + lyplg_ext_get_storage_p(ctx->ext, LY_STMT_DATA_NODE_MASK, (void ***)&list); } else if (node->nodetype == LYS_RPC) { list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs; } else if (node->nodetype == LYS_NOTIF) { @@ -2794,7 +2794,6 @@ lys_compile_node_action_inout(struct lysc_ctx *ctx, struct lysp_node *pnode, str struct lysc_node_action_inout *inout = (struct lysc_node_action_inout *)node; COMPILE_ARRAY_GOTO(ctx, inout_p->musts, inout->musts, lys_compile_must, ret, done); - COMPILE_EXTS_GOTO(ctx, inout_p->exts, inout->exts, inout, ret, done); ctx->compile_opts |= (inout_p->nodetype == LYS_INPUT) ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT; LY_LIST_FOR(inout_p->child, child_p) { diff --git a/src/schema_features.c b/src/schema_features.c index 9f6c368..5552267 100644 --- a/src/schema_features.c +++ b/src/schema_features.c @@ -105,7 +105,7 @@ lys_identity_iffeature_value(const struct lysc_ident *ident) const struct lysp_ident *idents_p, *found_ident = NULL; struct lysp_include *includes; - assert(ident); + LY_CHECK_ARG_RET(NULL, ident, ident->module->parsed, LY_EINVAL); /* Search parsed identity in the module. */ idents_p = ident->module->parsed->identities; @@ -146,6 +146,8 @@ lysp_feature_next(const struct lysp_feature *last, const struct lysp_module *pmo { struct lysp_feature *features; + LY_CHECK_ARG_RET(NULL, pmod, NULL); + if (!*idx) { /* module features */ features = pmod->features; diff --git a/src/tree_data.c b/src/tree_data.c index dede407..a8c42bf 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -1078,7 +1078,7 @@ lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_n { struct lyd_node *first_sibling; - LY_CHECK_ARG_RET(NULL, node, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, node, sibling != node, LY_EINVAL); if (sibling) { LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema)); @@ -2148,6 +2148,11 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_ struct lyd_node *child; if (options & LYD_DUP_RECURSIVE) { + /* create a hash table with the size of the previous hash table (duplicate) */ + if (orig->children_ht) { + ((struct lyd_node_inner *)dup)->children_ht = lyht_new(orig->children_ht->size, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1); + } + /* duplicate all the children */ LY_LIST_FOR(orig->child, child) { LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error); @@ -2179,58 +2184,6 @@ error: } /** - * @brief Duplicate a (leaf-)list and connect it into @p parent (if present) or last of @p first siblings. - * - * @param[in] orig Node to duplicate. - * @param[in] trg_ctx Target context for duplicated nodes. - * @param[in] parent Parent to insert into, NULL for top-level sibling. - * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set. - * @param[in] options Bitmask of options flags, see @ref dupoptions. - * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first). - * @return LY_ERR value. - */ -static LY_ERR -lyd_dup_list(const struct lyd_node **orig, const struct ly_ctx *trg_ctx, struct lyd_node *parent, - struct lyd_node **first, uint32_t options, struct lyd_node **dup_p) -{ - LY_ERR rc; - struct lyd_node *start, *leader, *dup; - const struct lysc_node *schema; - uint32_t insert_order; - - /* duplicate leader */ - start = (*orig)->next; - schema = (*orig)->schema; - rc = lyd_dup_r(*orig, trg_ctx, parent, LYD_INSERT_NODE_DEFAULT, first, options, &leader); - LY_CHECK_RET(rc); - - if (!start || !start->schema || !LYD_NODE_IS_ALONE(leader)) { - /* no other instances */ - if (dup_p) { - *dup_p = leader; - } - return LY_SUCCESS; - } - - /* duplicate the rest of the nodes in the (leaf-)list */ - insert_order = leader->next ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_LAST; - LY_LIST_FOR(start, *orig) { - if (schema != (*orig)->schema) { - break; - } - rc = lyd_dup_r(*orig, trg_ctx, parent, insert_order, first, options, &dup); - LY_CHECK_GOTO(rc, cleanup); - } - -cleanup: - if (dup_p) { - *dup_p = leader; - } - - return rc; -} - -/** * @brief Get a parent node to connect duplicated subtree to. * * @param[in] node Node (subtree) to duplicate. @@ -2311,12 +2264,14 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no ly_bool nosiblings, struct lyd_node **dup_p) { LY_ERR rc; - const struct lyd_node *orig; /* original node to be duplicated */ - struct lyd_node *first_dup = NULL; /* the first duplicated node, this is returned */ - struct lyd_node *top = NULL; /* the most higher created node */ - struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */ - struct lyd_node *dup = NULL; /* duplicate node */ - struct lyd_node *first_sibling = NULL; /* first sibling node */ + const struct lyd_node *orig; /* original node to be duplicated */ + struct lyd_node *first_dup = NULL; /* the first duplicated node, this is returned */ + struct lyd_node *top = NULL; /* the most higher created node */ + struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */ + struct lyd_node *dup = NULL; /* duplicate node */ + struct lyd_node *first_sibling = NULL; /* first sibling node */ + const struct lyd_node *first_llist = NULL; /* first duplicated (leaf-)list node, if any */ + uint32_t insert_order; assert(node && trg_ctx); @@ -2339,19 +2294,35 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first_sibling, options, &dup); LY_CHECK_GOTO(rc, error); } - } else if (!nosiblings && orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) { - /* duplicate the whole (leaf-)list */ - rc = lyd_dup_list(&orig, trg_ctx, local_parent, &first_sibling, options, &dup); - LY_CHECK_GOTO(rc, error); } else { - rc = lyd_dup_r(orig, trg_ctx, local_parent, - options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT, - &first_sibling, options, &dup); + /* decide insert order */ + insert_order = (options & LYD_DUP_NO_LYDS) ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT; + if (first_llist) { + if (orig->schema != first_llist->schema) { + /* all the (leaf-)list instances duplicated */ + first_llist = NULL; + } else { + /* duplicating all the instances of a (leaf-)list, no need to change their order */ + insert_order = LYD_INSERT_NODE_LAST; + } + } else if (orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) { + /* duplicating the first (leaf-)list instance, duplicate the rest more efficiently */ + first_llist = orig; + } + + /* duplicate the node */ + rc = lyd_dup_r(orig, trg_ctx, local_parent, insert_order, &first_sibling, options, &dup); LY_CHECK_GOTO(rc, error); + + if (first_llist && dup->next) { + /* orig was not the last node (because we are inserting into a parent with some previous instances), + * we must check find the order */ + first_llist = NULL; + } } first_dup = first_dup ? first_dup : dup; - if (nosiblings || !orig) { + if (nosiblings) { break; } } @@ -3624,7 +3595,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output, cleanup: lyxp_expr_free(LYD_CTX(ctx_node), expr); - ly_path_free(LYD_CTX(ctx_node), lypath); + ly_path_free(lypath); return ret; } diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 05cab2a..f480a5a 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -1656,10 +1656,11 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s) struct tm tm = {0}; uint32_t i, frac_len; const char *frac; + char *ptr; int64_t shift, shift_m; time_t t; - LY_CHECK_ARG_RET(NULL, value, time, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, value, strlen(value) > 17, time, LY_EINVAL); tm.tm_year = atoi(&value[0]) - 1900; tm.tm_mon = atoi(&value[5]) - 1; @@ -1698,6 +1699,10 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s) ++i; frac = &value[i]; for (frac_len = 0; isdigit(frac[frac_len]); ++frac_len) {} + if (!frac_len) { + LOGERR(NULL, LY_EINVAL, "Missing date-and-time fractions after '.'."); + return LY_EINVAL; + } i += frac_len; } else { @@ -1709,15 +1714,20 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s) /* zero shift */ shift = 0; } else { - shift = strtol(&value[i], NULL, 10); + value += i; + shift = strtol(value, &ptr, 10); if (shift > 23) { LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%" PRIi64 "\".", shift); return LY_EINVAL; + } else if (ptr[0] != ':') { + LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%s\".", value); + return LY_EINVAL; } shift = shift * 60 * 60; /* convert from hours to seconds */ - shift_m = strtol(&value[i + 4], NULL, 10); - if (shift_m > 59) { + value = ptr + 1; + shift_m = strtol(value, NULL, 10); + if ((shift_m < 0) || (shift_m > 59)) { LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone minutes \"%" PRIi64 "\".", shift_m); return LY_EINVAL; } diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c index ce237b1..9be655c 100644 --- a/src/tree_data_hash.c +++ b/src/tree_data_hash.c @@ -84,7 +84,7 @@ lyd_hash(struct lyd_node *node) * * Implementation of ::lyht_value_equal_cb. */ -static ly_bool +ly_bool lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_data)) { struct lyd_node *val1, *val2; diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h index 2bfa66d..b3a027c 100644 --- a/src/tree_data_internal.h +++ b/src/tree_data_internal.h @@ -16,6 +16,7 @@ #ifndef LY_TREE_DATA_INTERNAL_H_ #define LY_TREE_DATA_INTERNAL_H_ +#include "compat.h" #include "log.h" #include "plugins_types.h" #include "tree_data.h" @@ -601,6 +602,13 @@ LY_ERR ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, LY_ERR lyd_hash(struct lyd_node *node); /** + * @brief Compare callback for values in hash table. + * + * Implementation of ::lyht_value_equal_cb. + */ +ly_bool lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *cb_data); + +/** * @brief Insert hash of the node into the hash table of its parent. * * @param[in] node Data node which hash will be inserted into the ::lyd_node_inner.children_ht hash table of its parent. diff --git a/src/tree_data_new.c b/src/tree_data_new.c index f3bd9e7..7b26508 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -885,7 +885,7 @@ lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const cha return _lyd_new_term(parent, module, name, value, value ? strlen(value) : 0, options, node); } -LIBYANG_API_DECL LY_ERR +LIBYANG_API_DEF LY_ERR lyd_new_term_bin(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value, size_t value_len, uint32_t options, struct lyd_node **node) { @@ -1089,6 +1089,7 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name const char *prefix, const char *module_name, struct lyd_node **node) { struct lyd_node *ret = NULL; + uint32_t hints = 0; LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, !prefix || !strcmp(prefix, module_name), LY_EINVAL); LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL); @@ -1098,10 +1099,12 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name } if (!value) { value = ""; + } else if (!strcmp(value, "[null]")) { + hints |= LYD_VALHINT_EMPTY; } LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), prefix, prefix ? strlen(prefix) : 0, module_name, - strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, 0, &ret)); + strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, hints, &ret)); if (parent) { lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_LAST); } @@ -1626,6 +1629,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0; LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0; LY_VALUE_FORMAT format; + uint32_t hints; assert(parent || ctx); assert(path && ((path[0] == '/') || parent)); @@ -1728,9 +1732,13 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly } if (r && (r != LY_EINCOMPLETE)) { /* creating opaque leaf-list */ + hints = LYD_NODEHINT_LEAFLIST; + if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) { + hints |= LYD_VALHINT_EMPTY; + } LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, - LYD_NODEHINT_LEAFLIST, &node), cleanup); + hints, &node), cleanup); break; } } @@ -1765,8 +1773,12 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly } if (r && (r != LY_EINCOMPLETE)) { /* creating opaque leaf */ + hints = 0; + if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) { + hints |= LYD_VALHINT_EMPTY; + } LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, - schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, 0, &node), + schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, hints, &node), cleanup); break; } @@ -1811,7 +1823,7 @@ cleanup: LY_ARRAY_INCREMENT(p); } } - ly_path_free(ctx, p); + ly_path_free(p); if (!ret) { /* set out params only on success */ if (new_parent) { diff --git a/src/tree_schema.c b/src/tree_schema.c index d7ac8d8..21e2413 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -644,7 +644,7 @@ lys_find_path_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, ret = lys_find_lypath_atoms(p, set); cleanup: - ly_path_free(ctx, p); + ly_path_free(p); lyxp_expr_free(ctx, expr); return ret; } @@ -679,7 +679,7 @@ lys_find_path(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const snode = p[LY_ARRAY_COUNT(p) - 1].node; cleanup: - ly_path_free(ctx, p); + ly_path_free(p); lyxp_expr_free(ctx, expr); return snode; } @@ -1179,7 +1179,7 @@ lys_set_implemented(struct lys_module *mod, const char **features) LY_ERR ret = LY_SUCCESS; struct lys_glob_unres *unres = &mod->ctx->unres; - LY_CHECK_ARG_RET(NULL, mod, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, mod, mod->parsed, LY_EINVAL); /* implement */ ret = _lys_set_implemented(mod, features, unres); diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index 803009a..0faaa3c 100644 --- a/src/tree_schema_common.c +++ b/src/tree_schema_common.c @@ -768,7 +768,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision, { struct ly_in *in; char *filepath = NULL; - LYS_INFORMAT format; + LYS_INFORMAT format = 0; void *mod = NULL; LY_ERR ret = LY_SUCCESS; struct lysp_load_module_check_data check_data = {0}; @@ -1829,7 +1829,7 @@ lysc_node_lref_target(const struct lysc_node *node) /* get the target node */ target = p[LY_ARRAY_COUNT(p) - 1].node; - ly_path_free(node->module->ctx, p); + ly_path_free(p); return target; } diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 91ba72b..040872b 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -80,6 +80,8 @@ lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext) LY_LIST_FOR_SAFE(ext->child, next, stmt) { lysp_stmt_free(ctx->ctx, stmt); } + + FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free); } /** @@ -1360,7 +1362,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext ly_bool node_free; LY_ARRAY_FOR(substmts, u) { - if (!substmts[u].storage) { + if (!substmts[u].storage_p) { continue; } @@ -1383,75 +1385,75 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext case LY_STMT_USES: { struct lysp_node *child, *child_next; - LY_LIST_FOR_SAFE(*VOIDPTR2_C(substmts[u].storage), child_next, child) { + LY_LIST_FOR_SAFE(*substmts[u].storage_p, child_next, child) { node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0; lysp_node_free(&fctx, child); if (node_free) { free(child); } } - *VOIDPTR2_C(substmts[u].storage) = NULL; + *substmts[u].storage_p = NULL; break; } case LY_STMT_BASE: /* multiple strings */ - FREE_ARRAY(ctx, **(const char ***)VOIDPTR2_C(substmts[u].storage), lydict_remove); + FREE_ARRAY(ctx, **(const char ***)substmts[u].storage_p, lydict_remove); break; case LY_STMT_BIT: case LY_STMT_ENUM: /* single enum */ - lysp_type_enum_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); + lysp_type_enum_free(&fctx, *substmts[u].storage_p); break; case LY_STMT_DEVIATE: /* single deviate */ - lysp_deviate_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); + lysp_deviate_free(&fctx, *substmts[u].storage_p); break; case LY_STMT_DEVIATION: /* single deviation */ - lysp_deviation_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); + lysp_deviation_free(&fctx, *substmts[u].storage_p); break; case LY_STMT_EXTENSION: /* single extension */ - lysp_ext_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); + lysp_ext_free(&fctx, *substmts[u].storage_p); break; case LY_STMT_EXTENSION_INSTANCE: /* multiple extension instances */ - FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)VOIDPTR2_C(substmts[u].storage), lysp_ext_instance_free); + FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)substmts[u].storage_p, lysp_ext_instance_free); break; case LY_STMT_FEATURE: /* multiple features */ - FREE_ARRAY(&fctx, *(struct lysp_feature **)VOIDPTR2_C(substmts[u].storage), lysp_feature_free); + FREE_ARRAY(&fctx, *(struct lysp_feature **)substmts[u].storage_p, lysp_feature_free); break; case LY_STMT_IDENTITY: /* multiple identities */ - FREE_ARRAY(&fctx, *(struct lysp_ident **)VOIDPTR2_C(substmts[u].storage), lysp_ident_free); + FREE_ARRAY(&fctx, *(struct lysp_ident **)substmts[u].storage_p, lysp_ident_free); break; case LY_STMT_IMPORT: /* multiple imports */ - FREE_ARRAY(&fctx, *(struct lysp_import **)VOIDPTR2_C(substmts[u].storage), lysp_import_free); + FREE_ARRAY(&fctx, *(struct lysp_import **)substmts[u].storage_p, lysp_import_free); break; case LY_STMT_INCLUDE: /* multiple includes */ - FREE_ARRAY(&fctx, *(struct lysp_include **)VOIDPTR2_C(substmts[u].storage), lysp_include_free); + FREE_ARRAY(&fctx, *(struct lysp_include **)substmts[u].storage_p, lysp_include_free); break; case LY_STMT_REFINE: /* multiple refines */ - FREE_ARRAY(&fctx, *(struct lysp_refine **)VOIDPTR2_C(substmts[u].storage), lysp_refine_free); + FREE_ARRAY(&fctx, *(struct lysp_refine **)substmts[u].storage_p, lysp_refine_free); break; case LY_STMT_REVISION: /* multiple revisions */ - FREE_ARRAY(&fctx, *(struct lysp_revision **)VOIDPTR2_C(substmts[u].storage), lysp_revision_free); + FREE_ARRAY(&fctx, *(struct lysp_revision **)substmts[u].storage_p, lysp_revision_free); break; case LY_STMT_CONFIG: @@ -1485,7 +1487,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext case LY_STMT_REVISION_DATE: case LY_STMT_UNITS: /* single string */ - lydict_remove(ctx, *VOIDPTR2_C(substmts[u].storage)); + lydict_remove(ctx, *substmts[u].storage_p); break; case LY_STMT_LENGTH: @@ -1493,34 +1495,34 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext case LY_STMT_PATTERN: case LY_STMT_RANGE: /* multiple restrictions */ - FREE_ARRAY(&fctx, *(struct lysp_restr **)VOIDPTR2_C(substmts[u].storage), lysp_restr_free); + FREE_ARRAY(&fctx, *(struct lysp_restr **)substmts[u].storage_p, lysp_restr_free); break; case LY_STMT_WHEN: /* multiple whens */ - FREE_ARRAY(&fctx, *(struct lysp_when **)VOIDPTR2_C(substmts[u].storage), lysp_when_free); + FREE_ARRAY(&fctx, *(struct lysp_when **)substmts[u].storage_p, lysp_when_free); break; case LY_STMT_PATH: /* single expression */ - lyxp_expr_free(ctx, *VOIDPTR2_C(substmts[u].storage)); + lyxp_expr_free(ctx, *substmts[u].storage_p); break; case LY_STMT_DEFAULT: case LY_STMT_IF_FEATURE: case LY_STMT_UNIQUE: /* multiple qnames */ - FREE_ARRAY(ctx, *(struct lysp_qname **)VOIDPTR2_C(substmts[u].storage), lysp_qname_free); + FREE_ARRAY(ctx, *(struct lysp_qname **)substmts[u].storage_p, lysp_qname_free); break; case LY_STMT_TYPEDEF: /* multiple typedefs */ - FREE_ARRAY(&fctx, *(struct lysp_tpdf **)VOIDPTR2_C(substmts[u].storage), lysp_tpdf_free); + FREE_ARRAY(&fctx, *(struct lysp_tpdf **)substmts[u].storage_p, lysp_tpdf_free); break; case LY_STMT_TYPE: { /* single type */ - struct lysp_type **type_p = VOIDPTR_C(substmts[u].storage); + struct lysp_type **type_p = (struct lysp_type **)substmts[u].storage_p; lysp_type_free(&fctx, *type_p); free(*type_p); @@ -1529,7 +1531,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext case LY_STMT_MODULE: case LY_STMT_SUBMODULE: /* single (sub)module */ - lysp_module_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); + lysp_module_free(&fctx, *substmts[u].storage_p); break; default: @@ -1548,7 +1550,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext ly_bool node_free; LY_ARRAY_FOR(substmts, u) { - if (!substmts[u].storage) { + if (!substmts[u].storage_p) { continue; } @@ -1568,14 +1570,14 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext case LY_STMT_LIST: { struct lysc_node *child, *child_next; - LY_LIST_FOR_SAFE(*VOIDPTR2_C(substmts[u].storage), child_next, child) { + LY_LIST_FOR_SAFE(*substmts[u].storage_p, child_next, child) { node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0; lysc_node_free_(&fctx, child); if (node_free) { free(child); } } - *VOIDPTR2_C(substmts[u].storage) = NULL; + *substmts[u].storage_p = NULL; break; } case LY_STMT_USES: @@ -1605,7 +1607,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext case LY_STMT_REFERENCE: case LY_STMT_UNITS: { /* single item */ - const char *str = *VOIDPTR2_C(substmts[u].storage); + const char *str = *substmts[u].storage_p; lydict_remove(ctx, str); break; @@ -1613,7 +1615,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext case LY_STMT_BIT: case LY_STMT_ENUM: { /* sized array */ - struct lysc_type_bitenum_item *items = *VOIDPTR2_C(substmts[u].storage); + struct lysc_type_bitenum_item *items = *substmts[u].storage_p; FREE_ARRAY(&fctx, items, lysc_enum_item_free); break; @@ -1621,47 +1623,47 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext case LY_STMT_LENGTH: case LY_STMT_RANGE: { /* single item */ - struct lysc_range *range = *VOIDPTR2_C(substmts[u].storage); + struct lysc_range *range = *substmts[u].storage_p; lysc_range_free(&fctx, range); break; } case LY_STMT_MUST: { /* sized array */ - struct lysc_must *musts = *VOIDPTR2_C(substmts[u].storage); + struct lysc_must *musts = *substmts[u].storage_p; FREE_ARRAY(&fctx, musts, lysc_must_free); break; } case LY_STMT_WHEN: /* single item, expects a pointer */ - lysc_when_free(&fctx, VOIDPTR_C(substmts[u].storage)); + lysc_when_free(&fctx, (struct lysc_when **)substmts[u].storage_p); break; case LY_STMT_PATTERN: { /* sized array of pointers */ - struct lysc_pattern **patterns = *VOIDPTR2_C(substmts[u].storage); + struct lysc_pattern **patterns = *substmts[u].storage_p; FREE_ARRAY(&fctx, patterns, lysc_pattern_free); break; } case LY_STMT_TYPE: { /* single item */ - struct lysc_type *type = *VOIDPTR2_C(substmts[u].storage); + struct lysc_type *type = *substmts[u].storage_p; lysc_type_free(&fctx, type); break; } case LY_STMT_IDENTITY: { /* sized array */ - struct lysc_ident *idents = *VOIDPTR2_C(substmts[u].storage); + struct lysc_ident *idents = *substmts[u].storage_p; FREE_ARRAY(&fctx, idents, lysc_ident_free); break; } case LY_STMT_EXTENSION_INSTANCE: { /* sized array */ - struct lysc_ext_instance *exts = *VOIDPTR2_C(substmts[u].storage); + struct lysc_ext_instance *exts = *substmts[u].storage_p; FREE_ARRAY(&fctx, exts, lysc_ext_instance_free); break; diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h index d3e399c..ee40f58 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -726,11 +726,11 @@ uint8_t lys_stmt_flags(enum ly_stmt stmt); * @param[in] ext Compiled ext instance. * @param[in] stmt Compiled statement. Can be a mask when the first match is returned, it is expected the storage is * the same for all the masked statements. - * @param[out] storage_p Pointer to a compiled ext instance substatement storage, NULL if was not compiled. + * @param[out] storage_pp Pointer to a compiled ext instance substatement storage, NULL if was not compiled. * @return LY_SUCCESS on success. * @return LY_ENOT if the substatement is not supported. */ -LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t *storage_p); +LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp); /** * @brief Warning if the filename does not match the expected module name and version diff --git a/src/validation.c b/src/validation.c index 501dd69..a950c54 100644 --- a/src/validation.c +++ b/src/validation.c @@ -197,13 +197,14 @@ lyd_validate_node_when(const struct lyd_node *tree, const struct lyd_node *node, * @param[in] np_cont_diff Whether to put NP container into diff or only its children. * @param[in,out] node Optional current iteration node, update it if it is deleted. * @param[in,out] node_when Optional set with nodes with "when" conditions, may be removed from. + * @param[in,out] node_types Optional set with unresolved type nodes, may be removed from. * @param[in,out] diff Validation diff. * @return 1 if @p node auto-deleted and updated to its next sibling. * @return 0 if @p node was not auto-deleted. */ static ly_bool lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, const struct lys_module *mod, - int np_cont_diff, struct lyd_node **node, struct ly_set *node_types, struct lyd_node **diff) + int np_cont_diff, struct lyd_node **node, struct ly_set *node_when, struct ly_set *node_types, struct lyd_node **diff) { struct lyd_node *iter; ly_bool node_autodel = 0; @@ -228,6 +229,16 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con } } + if (node_when && node_when->count) { + /* remove nested from node_when set */ + LYD_TREE_DFS_BEGIN(del, iter) { + if ((del != iter) && ly_set_contains(node_when, iter, &idx)) { + ly_set_rm_index(node_when, idx, NULL); + } + LYD_TREE_DFS_END(del, iter); + } + } + if (node_types && node_types->count) { /* remove from node_types set */ LYD_TREE_DFS_BEGIN(del, iter) { @@ -264,7 +275,7 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st uint32_t xpath_options, struct ly_set *node_types, struct lyd_node **diff) { LY_ERR rc = LY_SUCCESS, r; - uint32_t i; + uint32_t i, count; const struct lysc_when *disabled; struct lyd_node *node = NULL; @@ -285,7 +296,12 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st /* when false */ if (node->flags & LYD_WHEN_TRUE) { /* autodelete */ - lyd_validate_autodel_node_del(tree, node, mod, 1, NULL, node_types, diff); + count = node_when->count; + lyd_validate_autodel_node_del(tree, node, mod, 1, NULL, node_when, node_types, diff); + if (count > node_when->count) { + /* nested nodes removed, we lost the index */ + ly_set_contains(node_when, node, &i); + } } else if (val_opts & LYD_VALIDATE_OPERATIONAL) { /* only a warning */ LOGWRN(LYD_CTX(node), "When condition \"%s\" not satisfied.", disabled->cond->expr); @@ -640,7 +656,7 @@ lyd_validate_autodel_leaflist_dflt(struct lyd_node **first, struct lyd_node **no LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) { if (iter->flags & LYD_DEFAULT) { /* default instance found, remove it */ - if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) { + if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) { node_autodel = 1; } } @@ -685,7 +701,7 @@ lyd_validate_autodel_cont_leaf_dflt(struct lyd_node **first, struct lyd_node **n LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) { if (iter->flags & LYD_DEFAULT) { /* default instance, remove it */ - if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) { + if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) { node_autodel = 1; } } @@ -695,7 +711,7 @@ lyd_validate_autodel_cont_leaf_dflt(struct lyd_node **first, struct lyd_node **n LYD_LIST_FOR_INST(*first, schema, iter) { if ((iter->flags & LYD_DEFAULT) && !(iter->flags & LYD_NEW)) { /* old default instance, remove it */ - if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) { + if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) { node_autodel = 1; } break; @@ -753,7 +769,7 @@ lyd_validate_autodel_case_dflt(struct lyd_node **first, struct lyd_node **node, if (!iter) { /* there are only default nodes of the case meaning it does not exist and neither should any default nodes * of the case, remove this one default node */ - if (lyd_validate_autodel_node_del(first, *node, mod, 0, node, NULL, diff)) { + if (lyd_validate_autodel_node_del(first, *node, mod, 0, node, NULL, NULL, diff)) { node_autodel = 1; } } diff --git a/src/version.h.in b/src/version.h.in index 1ed86c1..021cd05 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -16,6 +16,8 @@ #ifndef LY_VERSION_H_ #define LY_VERSION_H_ +#include "ly_config.h" + #ifdef __cplusplus extern "C" { #endif @@ -30,22 +32,61 @@ extern "C" { #define LY_PROJ_VERSION_MICRO @LIBYANG_MICRO_VERSION@ /**< project micro version number */ #define LY_PROJ_VERSION "@LIBYANG_VERSION@" /**< project version string */ -struct ly_version { - uint32_t major; /**< Major version number */ - uint32_t minor; /**< Minor version number */ - uint32_t micro; /**< Micro version number */ - const char *str; /**< Version string */ -}; +/** + * @brief Get libyang major SO version. + * + * @return LY version. + */ +LIBYANG_API_DECL uint32_t ly_version_so_major(void); + +/** + * @brief Get libyang minor SO version. + * + * @return LY version. + */ +LIBYANG_API_DECL uint32_t ly_version_so_minor(void); + +/** + * @brief Get libyang micro SO version. + * + * @return LY version. + */ +LIBYANG_API_DECL uint32_t ly_version_so_micro(void); + +/** + * @brief Get libyang string SO version. + * + * @return LY version. + */ +LIBYANG_API_DECL const char *ly_version_so_str(void); /** - * @brief libyang SO version. + * @brief Get libyang major project version. + * + * @return LY version. */ -LIBYANG_API_DECL extern struct ly_version ly_version_so; +LIBYANG_API_DECL uint32_t ly_version_proj_major(void); /** - * @brief libyang project version. + * @brief Get libyang minor project version. + * + * @return LY version. + */ +LIBYANG_API_DECL uint32_t ly_version_proj_minor(void); + +/** + * @brief Get libyang micro project version. + * + * @return LY version. + */ +LIBYANG_API_DECL uint32_t ly_version_proj_micro(void); + +/** + * @brief Get libyang string project version. + * + * @return LY version. */ -LIBYANG_API_DECL extern struct ly_version ly_version_proj; +LIBYANG_API_DECL const char *ly_version_proj_str(void); #ifdef __cplusplus } diff --git a/src/xpath.c b/src/xpath.c index 8e9bf02..2251eab 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -330,7 +330,7 @@ print_set_debug(struct lyxp_set *set) (lyd_child(item->node)->schema->nodetype == LYS_LEAF)) { LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (1st child val: %s)", i + 1, item->pos, item->node->schema->name, lyd_get_value(lyd_child(item->node))); - } else if ((!item->node->schema && !lyd_child(item->node)) || (item->node->schema->nodetype == LYS_LEAFLIST)) { + } else if (lyd_get_value(item->node)) { LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (val: %s)", i + 1, item->pos, LYD_NAME(item->node), lyd_get_value(item->node)); } else { @@ -4042,7 +4042,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set if (!r) { /* get the target node */ target = p[LY_ARRAY_COUNT(p) - 1].node; - ly_path_free(set->ctx, p); + ly_path_free(p); LY_CHECK_RET(lyxp_set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL)); } /* else the target was found before but is disabled so it was removed */ @@ -8272,7 +8272,9 @@ cleanup: options &= ~LYXP_SKIP_EXPR; } lydict_remove(set->ctx, ncname_dict); - ly_path_predicates_free(set->ctx, predicates); + if (predicates) { + ly_path_predicates_free(scnode->module->ctx, predicates); + } return rc; } diff --git a/tests/modules/yang/notifications@2008-07-14.yang b/tests/modules/yang/notifications@2008-07-14.yang index b696f39..8a723b2 100644 --- a/tests/modules/yang/notifications@2008-07-14.yang +++ b/tests/modules/yang/notifications@2008-07-14.yang @@ -80,7 +80,7 @@ module notifications { } } - /*container notification { + container notification { description "internal struct to start a notification"; config false; @@ -90,6 +90,6 @@ module notifications { } // eventType and any data content goes here - }*/ + } } diff --git a/tests/perf/perf.c b/tests/perf/perf.c index da1eb93..37591cb 100644 --- a/tests/perf/perf.c +++ b/tests/perf/perf.c @@ -580,6 +580,9 @@ test_dup_siblings_to_empty(struct test_state *state, struct timespec *ts_start, TEST_END(ts_end); + /* need to remove the duplicated nodes if the test is repeated */ + lyd_free_siblings(lyd_child(state->data1)); + return LY_SUCCESS; } diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c index 7feb65f..476fd81 100644 --- a/tests/utests/basic/test_context.c +++ b/tests/utests/basic/test_context.c @@ -831,8 +831,8 @@ check_ext_instance_priv_parsed_is_set(struct lysc_ext_instance *ext) LY_ARRAY_FOR(ext, u) { substmts = ext[u].substmts; LY_ARRAY_FOR(substmts, v) { - if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) { - cnode = *(struct lysc_node **)substmts[v].storage; + if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) { + cnode = *(struct lysc_node **)substmts[v].storage_p; iter = check; assert_int_equal(LY_SUCCESS, lysc_tree_dfs_full(cnode, check_node_priv_parsed_is_set, &iter)); } @@ -850,8 +850,8 @@ check_ext_instance_priv_parsed_not_set(struct lysc_ext_instance *ext) LY_ARRAY_FOR(ext, u) { substmts = ext[u].substmts; LY_ARRAY_FOR(substmts, v) { - if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) { - cnode = *(struct lysc_node **)substmts[v].storage; + if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) { + cnode = *(struct lysc_node **)substmts[v].storage_p; if (cnode) { CHECK_POINTER((struct lysp_node *)cnode->priv, 0); } diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c index d5336c0..d7203fa 100644 --- a/tests/utests/data/test_parser_xml.c +++ b/tests/utests/data/test_parser_xml.c @@ -193,6 +193,18 @@ test_anyxml(void **state) free(str); CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected); lyd_free_all(tree); + + data = "<anyx xmlns=\"urn:tests:a\"><x>1</x><x>0</x><x>-1</x><x>4294967295</x><x>4294967296</x><x>-2147483648</x><x>-2147483649</x></anyx>"; + CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree); + assert_non_null(tree); + tree = tree->next; + assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree, LYD_XML, LYD_PRINT_SHRINK)); + CHECK_STRING(str, data); + free(str); + assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree, LYD_JSON, LYD_PRINT_SHRINK)); + CHECK_STRING(str, "{\"a:anyx\":{\"x\":[1,0,-1,4294967295,\"4294967296\",-2147483648,\"-2147483649\"]}}"); + free(str); + lyd_free_all(tree); } static void @@ -349,7 +361,7 @@ test_opaq(void **state) " <c xmld:id=\"D\">1</c>\n" "</a>\n", LYD_XML, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree)); - CHECK_LOG_CTX("Unknown XML prefix \"xmld\".", "/a", 3); + CHECK_LOG_CTX("Unknown XML prefix \"xmld\" at attribute \"id\".", "/a", 3); } static void diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c index fabd170..b3dde5a 100644 --- a/tests/utests/data/test_tree_data.c +++ b/tests/utests/data/test_tree_data.c @@ -409,7 +409,7 @@ test_target(void **state) assert_string_equal(lyd_get_value(term->prev), "b"); lyd_free_all(tree); - ly_path_free(UTEST_LYCTX, path); + ly_path_free(path); lyxp_expr_free(UTEST_LYCTX, exp); } diff --git a/tests/utests/data/test_tree_data_sorted.c b/tests/utests/data/test_tree_data_sorted.c index 0e812e7..bb6e4d6 100644 --- a/tests/utests/data/test_tree_data_sorted.c +++ b/tests/utests/data/test_tree_data_sorted.c @@ -131,6 +131,57 @@ test_insert_cont_leaflist(void **state) } static void +test_dup_sort(void **state) +{ + const char *schema; + struct lys_module *mod; + struct lyd_node *cont, *cont2; + char *str; + + schema = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;revision 2014-05-08;" + "container cn { list lst {key \"k\"; leaf k {type uint32;}}}}"; + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + + assert_int_equal(lyd_new_inner(NULL, mod, "cn", 0, &cont), LY_SUCCESS); + assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "2"), LY_SUCCESS); + assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "5"), LY_SUCCESS); + assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "9"), LY_SUCCESS); + + assert_int_equal(lyd_new_inner(NULL, mod, "cn", 0, &cont2), LY_SUCCESS); + assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "1"), LY_SUCCESS); + assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "3"), LY_SUCCESS); + assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "8"), LY_SUCCESS); + + assert_int_equal(lyd_dup_siblings(lyd_child(cont2), (struct lyd_node_inner *)cont, 0, NULL), LY_SUCCESS); + lyd_print_mem(&str, cont, LYD_XML, 0); + assert_string_equal(str, + "<cn xmlns=\"urn:tests:a\">\n" + " <lst>\n" + " <k>1</k>\n" + " </lst>\n" + " <lst>\n" + " <k>2</k>\n" + " </lst>\n" + " <lst>\n" + " <k>3</k>\n" + " </lst>\n" + " <lst>\n" + " <k>5</k>\n" + " </lst>\n" + " <lst>\n" + " <k>8</k>\n" + " </lst>\n" + " <lst>\n" + " <k>9</k>\n" + " </lst>\n" + "</cn>\n"); + free(str); + + lyd_free_all(cont); + lyd_free_all(cont2); +} + +static void test_try_user_order_func(void **state) { const char *schema; @@ -1599,6 +1650,7 @@ main(void) UTEST(test_insert_top_level_leaflist), UTEST(test_insert_cont_list), UTEST(test_insert_cont_leaflist), + UTEST(test_dup_sort), UTEST(test_try_user_order_func), UTEST(test_ordered_by_user), UTEST(test_remove), diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 953aad8..cba2b2d 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -1712,7 +1712,7 @@ test_extension_compile(void **state) LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_p.substmts, substmtp, rc, cleanup); substmtp->stmt = LY_STMT_ERROR_MESSAGE; - substmtp->storage = (uintptr_t)(void *)&ext_p.parsed; + substmtp->storage_p = &ext_p.parsed; /* fake parse */ lydict_insert(UTEST_LYCTX, "my error", 0, (const char **)&ext_p.parsed); @@ -1721,7 +1721,7 @@ test_extension_compile(void **state) LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_c.substmts, substmt, rc, cleanup); substmt->stmt = LY_STMT_ERROR_MESSAGE; - substmt->storage = (uintptr_t)(void *)&ext_c.compiled; + substmt->storage_p = &ext_c.compiled; /* * error-message diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c index 3d4fbf7..04c30db 100644 --- a/tests/utests/schema/test_tree_schema_compile.c +++ b/tests/utests/schema/test_tree_schema_compile.c @@ -1233,6 +1233,7 @@ test_type_instanceid(void **state) { struct lys_module *mod; struct lysc_type *type; + char *str; assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;typedef mytype {type instance-identifier {require-instance false;}}" "leaf l1 {type instance-identifier {require-instance true;}}" @@ -1252,12 +1253,22 @@ test_type_instanceid(void **state) assert_int_equal(LY_TYPE_INST, type->basetype); assert_int_equal(1, ((struct lysc_type_instanceid *)type)->require_instance); + /* default value */ + str = "module b1 {namespace urn:b1;prefix b1;" + "leaf l1 {type string;}}"; + ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, str); + ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED); + assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b2 {namespace urn:b2;prefix b2;" + "import b1 {prefix b1;}" + "leaf l1 {type instance-identifier; default \"/b1:l1\";}}", LYS_IN_YANG, NULL)); + ly_ctx_set_options(UTEST_LYCTX, 0); + /* invalid cases */ - assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, &mod)); + assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, NULL)); CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL, 0); CHECK_LOG_CTX("Invalid value \"yes\" of \"require-instance\".", NULL, 1); - assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, &mod)); + assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, NULL)); CHECK_LOG_CTX("Invalid type restrictions for instance-identifier type.", "/aa:l", 0); } diff --git a/tests/utests/schema/test_yang.c b/tests/utests/schema/test_yang.c index 67f9747..034f95d 100644 --- a/tests/utests/schema/test_yang.c +++ b/tests/utests/schema/test_yang.c @@ -284,8 +284,6 @@ test_arg(void **state) TEST_GET_ARGUMENT_SUCCESS("hello ", YCTX, Y_STR_ARG, "hello ", 5, " ", 1); - TEST_GET_ARGUMENT_SUCCESS("hello/*comment*/\n", YCTX, Y_STR_ARG, "hello/*comment*/\n", 5, "\n", 1); - TEST_GET_ARGUMENT_SUCCESS("\"hello\\n\\t\\\"\\\\\";", YCTX, Y_STR_ARG, "hello\n\t\"\\", 9, ";", 1); free(buf); diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c index f79238e..07c5e16 100644 --- a/tests/utests/types/yang_types.c +++ b/tests/utests/types/yang_types.c @@ -112,14 +112,13 @@ test_data_xml(void **state) TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00"); TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00", LY_EVALID); - CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to " - "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".", + CHECK_LOG_CTX("Missing date-and-time fractions after '.'.", "/a:l", 1); - TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EINVAL); + TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EVALID); CHECK_LOG_CTX("Invalid date-and-time month \"15\".", "/a:l", 1); - TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EINVAL); + TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EVALID); CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "/a:l", 1); /* hex-string */ diff --git a/tests/yanglint/interactive/debug.test b/tests/yanglint/interactive/debug.test deleted file mode 100644 index 8a64c92..0000000 --- a/tests/yanglint/interactive/debug.test +++ /dev/null @@ -1,33 +0,0 @@ -source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}] - -set mdir $::env(YANG_MODULES_DIR) - -test debug_dict {Check debug message DICT} { --setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body { - ly_cmd "verb debug" - ly_cmd "debug dict" - ly_cmd "load modleaf" "DICT" -}} - -test debug_xpath {Check debug message XPATH} { --setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body { - ly_cmd "verb debug" - ly_cmd "debug xpath" - ly_cmd "load modmust" "XPATH" -}} - -test debug_dep_sets {Check debug message DEPSETS} { --setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body { - ly_cmd "verb debug" - ly_cmd "debug dep-sets" - ly_cmd "load modleaf" "DEPSETS" -}} - -test debug_depsets_xpath {Check debug message DEPSETS and XPATH} { --setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body { - ly_cmd "verb debug" - ly_cmd "debug dep-sets xpath" - ly_cmd "load modmust" "DEPSETS.*XPATH" -}} - -cleanupTests diff --git a/tests/yanglint/interactive/ly.tcl b/tests/yanglint/interactive/ly.tcl index 4c56be4..efa57f2 100644 --- a/tests/yanglint/interactive/ly.tcl +++ b/tests/yanglint/interactive/ly.tcl @@ -65,17 +65,3 @@ proc ly_exit {} { send "exit\r" expect eof } - -# Check if yanglint is configured as DEBUG. -# Return 1 on success. -proc yanglint_debug {} { - global TUT - # Call non-interactive yanglint with --help. - set output [exec -- $TUT "-h"] - # Find option --debug. - if { [regexp -- "--debug=GROUPS" $output] } { - return 1 - } else { - return 0 - } -} diff --git a/tools/lint/completion.c b/tools/lint/completion.c index 59207ca..3c7503e 100644 --- a/tools/lint/completion.c +++ b/tools/lint/completion.c @@ -224,7 +224,7 @@ get_schema_completion(const char *hint, char ***matches, unsigned int *match_cou uint32_t idx; const char *start; char *end, *module_name = NULL, *path = NULL; - const struct lysc_node *parent, *last_node; + const struct lysc_node *parent, *last_node = NULL; int rc = 0; size_t len; |