tree CHANGE invalid xpath is accepted with a warning
diff --git a/src/log.c b/src/log.c
index 59f2767..4a57c66 100644
--- a/src/log.c
+++ b/src/log.c
@@ -108,10 +108,7 @@
}
}
- if (hide == 0xff && level == LY_LLERR && (LY_LLWRN <= ly_log_level)) {
- /* change error to warning */
- level = LY_LLWRN;
- } else if (hide || (level > ly_log_level)) {
+ if (hide || (level > ly_log_level)) {
/* do not print the message */
goto clean;
}
@@ -139,7 +136,7 @@
va_list ap;
va_start(ap, format);
- log_vprintf(level, 0, format, NULL, ap);
+ log_vprintf(level, (*ly_vlog_hide_location()), format, NULL, ap);
va_end(ap);
}
diff --git a/src/resolve.c b/src/resolve.c
index a90725d..6427ff7 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -4173,12 +4173,12 @@
}
int
-lys_check_xpath(struct lys_node *node, int check_place)
+lys_check_xpath(struct lys_node *node, int check_place, int warn_on_fwd_ref)
{
struct lys_node *parent, *elem;
struct lyxp_set set;
uint32_t i;
- int rc;
+ int ret;
if (check_place) {
parent = node;
@@ -4206,9 +4206,9 @@
}
}
- rc = lyxp_node_atomize(node, &set);
- if (rc) {
- return rc;
+ ret = lyxp_node_atomize(node, &set, warn_on_fwd_ref);
+ if (ret == -1) {
+ return -1;
}
for (parent = node; parent && !(parent->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); parent = lys_parent(parent));
@@ -4234,7 +4234,7 @@
}
free(set.val.snodes);
- return EXIT_SUCCESS;
+ return ret;
}
static int
@@ -6026,12 +6026,13 @@
* @param[in] type Type of the unresolved item.
* @param[in] str_snode String, a schema node, or NULL.
* @param[in] unres Unres schema structure to use.
+ * @param[in] final_fail Whether we are just printing errors of the failed unres items.
*
* @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
*/
static int
resolve_unres_schema_item(struct lys_module *mod, void *item, enum UNRES_ITEM type, void *str_snode,
- struct unres_schema *unres)
+ struct unres_schema *unres, int final_fail)
{
/* has_str - whether the str_snode is a string in a dictionary that needs to be freed */
int rc = -1, has_str = 0, tpdf_flag = 0, i, k;
@@ -6250,7 +6251,7 @@
break;
case UNRES_XPATH:
node = (struct lys_node *)item;
- rc = lys_check_xpath(node, 1);
+ rc = lys_check_xpath(node, 1, final_fail);
break;
default:
LOGINT;
@@ -6378,7 +6379,7 @@
* UNRES_AUGMENT, UNRES_CHOICE_DFLT and UNRES_IDENT */
++unres_count;
- rc = resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
+ rc = resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, 0);
if (!rc) {
unres->type[i] = UNRES_RESOLVED;
++resolved;
@@ -6386,7 +6387,7 @@
} else if (rc == -1) {
ly_vlog_hide(0);
/* print the error */
- resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
+ resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, 1);
return -1;
} else {
/* forward reference, erase ly_errno */
@@ -6403,7 +6404,7 @@
if (unres->type[i] > UNRES_IDENT) {
continue;
}
- resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
+ resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, 1);
}
return -1;
}
@@ -6414,7 +6415,7 @@
continue;
}
- rc = resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
+ rc = resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, 0);
if (rc == 0) {
if (unres->type[i] == UNRES_LIST_UNIQ) {
/* free the allocated structure */
@@ -6425,7 +6426,7 @@
} else if (rc == -1) {
ly_vlog_hide(0);
/* print the error */
- resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
+ resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, 1);
return -1;
}
}
@@ -6440,17 +6441,11 @@
if (unres->type[i] == UNRES_RESOLVED) {
continue;
}
+ resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres, 1);
if (unres->type[i] == UNRES_XPATH) {
- /* unresolvable XPaths are actually supposed to be warnings - they may be
- * unresolved due to the not implemented target module so it shouldn't avoid
- * parsing the module, but we still want to announce some issue here */
- ly_vlog_hide(0xff);
- }
- resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
- if (unres->type[i] == UNRES_XPATH && *ly_vlog_hide_location() == 0xff) {
+ /* XPath referencing an unknown node is actually supposed to be just a warning */
unres->type[i] = UNRES_RESOLVED;
resolved++;
- ly_vlog_hide(0);
}
}
if (resolved < unres->count) {
@@ -6528,7 +6523,7 @@
log_hidden = 0;
ly_vlog_hide(1);
}
- rc = resolve_unres_schema_item(mod, item, type, snode, unres);
+ rc = resolve_unres_schema_item(mod, item, type, snode, unres, 0);
if (!log_hidden) {
ly_vlog_hide(0);
}
@@ -6543,7 +6538,7 @@
} else if (rc == -1 && type == UNRES_IFFEAT) {
/* free the allocated resources */
free(*((char **)item));
- }
+ }
return rc;
} else {
/* erase info about validation errors */
diff --git a/src/tree_internal.h b/src/tree_internal.h
index c87f0fa..4045f6a 100644
--- a/src/tree_internal.h
+++ b/src/tree_internal.h
@@ -181,9 +181,10 @@
*
* @param[in] node Node to examine.
* @param[in] check_place Check where the node is placed to get know if the check is supposed to be performed
+ * @param[in] warn_on_fwd_ref Whether to not print errors and only warn on forward references.
* @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
*/
-int lys_check_xpath(struct lys_node *node, int check_place);
+int lys_check_xpath(struct lys_node *node, int check_place, int warn_on_fwd_ref);
/**
* @brief Get know if the node contains must or when with XPath expression
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 0ba99f1..33df466 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -3378,7 +3378,7 @@
goto next_iter;
}
- if (lyxp_node_atomize(elem, &set)) {
+ if (lyxp_node_atomize(elem, &set, 0)) {
ly_set_free(ret_set);
free(set.val.snodes);
return NULL;
diff --git a/src/xpath.c b/src/xpath.c
index e52fc45..4af4b21 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -4574,13 +4574,6 @@
set->val.snodes[i].in_ctx = 1;
}
}
- } else if (orig_used == (int)set->used && !moveto_mod) {
- /* no new node inserted into set (all are invalid now) and we were searching
- * in the same schema as the previous node, so this is definitely a bug in expression,
- * avoid changing it to just a warning */
- if (*ly_vlog_hide_location() == 0xff) {
- ly_vlog_hide(0);
- }
}
return EXIT_SUCCESS;
@@ -7659,17 +7652,19 @@
}
int
-lyxp_node_atomize(const struct lys_node *node, struct lyxp_set *set)
+lyxp_node_atomize(const struct lys_node *node, struct lyxp_set *set, int warn_on_fwd_ref)
{
struct lys_node *ctx_snode;
enum lyxp_node_type ctx_snode_type;
struct lyxp_set tmp_set;
uint8_t must_size = 0;
uint32_t i;
- int opts;
+ int opts, ret = EXIT_SUCCESS;
struct lys_when *when = NULL;
struct lys_restr *must = NULL;
+ assert(!warn_on_fwd_ref || !*ly_vlog_hide_location());
+
memset(&tmp_set, 0, sizeof tmp_set);
memset(set, 0, sizeof *set);
@@ -7733,39 +7728,71 @@
break;
}
+ if (warn_on_fwd_ref) {
+ /* hide errors, we can print only warnings */
+ ly_vlog_hide(1);
+ }
+
/* check "when" */
if (when) {
resolve_when_ctx_snode(node, &ctx_snode, &ctx_snode_type);
if (lyxp_atomize(when->cond, ctx_snode, ctx_snode_type, &tmp_set, LYXP_SNODE_WHEN | opts)) {
free(tmp_set.val.snodes);
- LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving when condition \"%s\" failed.", when->cond);
- if ((ly_errno == LY_EVALID) && (ly_vecode == LYVE_XPATH_INSNODE)) {
- return EXIT_FAILURE;
- } else {
- return -1;
+ if ((ly_errno != LY_EVALID) || (ly_vecode != LYVE_XPATH_INSNODE)) {
+ LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Invalid when condition \"%s\".", when->cond);
+ ret = -1;
+ goto finish;
+ } else if (!warn_on_fwd_ref) {
+ LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Invalid when condition \"%s\".", when->cond);
+ ret = EXIT_FAILURE;
+ goto finish;
}
- }
+ ly_vlog_hide(0);
+ LOGWRN(ly_errmsg());
+ LOGWRN("Invalid when condition \"%s\".", when->cond);
+ ly_vlog_hide(1);
- set_snode_merge(set, &tmp_set);
- memset(&tmp_set, 0, sizeof tmp_set);
+ ret = EXIT_FAILURE;
+ memset(&tmp_set, 0, sizeof tmp_set);
+ } else {
+ set_snode_merge(set, &tmp_set);
+ memset(&tmp_set, 0, sizeof tmp_set);
+ }
}
/* check "must" */
for (i = 0; i < must_size; ++i) {
if (lyxp_atomize(must[i].expr, node, LYXP_NODE_ELEM, &tmp_set, LYXP_SNODE_MUST | opts)) {
free(tmp_set.val.snodes);
- free(set->val.snodes);
- LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving must restriction \"%s\" failed.", must[i].expr);
- if ((ly_errno == LY_EVALID) && (ly_vecode == LYVE_XPATH_INSNODE)) {
- return EXIT_FAILURE;
- } else {
- return -1;
+ if ((ly_errno != LY_EVALID) || (ly_vecode != LYVE_XPATH_INSNODE)) {
+ LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Invalid must restriction \"%s\".", must[i].expr);
+ ret = -1;
+ goto finish;
+ } else if (!warn_on_fwd_ref) {
+ LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Invalid must restriction \"%s\".", must[i].expr);
+ ret = EXIT_FAILURE;
+ goto finish;
}
- }
+ ly_vlog_hide(0);
+ LOGWRN(ly_errmsg());
+ LOGWRN("Invalid must restriction \"%s\".", must[i].expr);
+ ly_vlog_hide(1);
- set_snode_merge(set, &tmp_set);
- memset(&tmp_set, 0, sizeof tmp_set);
+ ret = EXIT_FAILURE;
+ memset(&tmp_set, 0, sizeof tmp_set);
+ } else {
+ set_snode_merge(set, &tmp_set);
+ memset(&tmp_set, 0, sizeof tmp_set);
+ }
}
- return EXIT_SUCCESS;
+finish:
+ if (warn_on_fwd_ref) {
+ ly_vlog_hide(0);
+ }
+ if (ret) {
+ free(set->val.snodes);
+ memset(set, 0, sizeof *set);
+ }
+ return ret;
}
diff --git a/src/xpath.h b/src/xpath.h
index 865c5f0..89e8f09 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -253,10 +253,12 @@
* @param[in] node Node to examine.
* @param[in,out] set Resulting set of atoms merged from all the expressions.
* Will be cleared before use.
+ * @param[in] warn_on_fwd_ref Setting this flag causes no errors to be printed and
+ * only warning is printed on forward reference paths (addressing a non-existing node).
*
* @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
*/
-int lyxp_node_atomize(const struct lys_node *node, struct lyxp_set *set);
+int lyxp_node_atomize(const struct lys_node *node, struct lyxp_set *set, int warn_on_fwd_ref);
/**
* @brief Cast XPath set to another type.