Skip to content

Commit

Permalink
xpath BUGFIX support for unprefixed identities
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvasko committed Oct 22, 2024
1 parent 8a8fde0 commit 4b88556
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 5 deletions.
51 changes: 46 additions & 5 deletions src/xpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -4098,6 +4098,51 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set
return ret;
}

/**
* @brief Get the module of an identity used in derived-from(-or-self)() functions.
*
* @param[in,out] qname Qualified node name. If includes prefix, it is skipped.
* @param[in,out] qname_len Length of @p qname, is updated accordingly.
* @param[in] set Set with general XPath context.
* @param[out] mod Module of the identity.
* @return LY_ERR
*/
static LY_ERR
xpath_derived_ident_module(const char **qname, uint32_t *qname_len, const struct lyxp_set *set,
const struct lys_module **mod)
{
LY_CHECK_RET(moveto_resolve_model(qname, qname_len, set, mod));
if (*mod) {
/* prefixed identity */
return LY_SUCCESS;
}

switch (set->format) {
case LY_VALUE_SCHEMA:
case LY_VALUE_SCHEMA_RESOLVED:
/* current module */
*mod = set->cur_mod;
break;
case LY_VALUE_CANON:
case LY_VALUE_JSON:
case LY_VALUE_LYB:
case LY_VALUE_STR_NS:
/* inherit parent (context node) module */
if (set->cur_scnode) {
*mod = set->cur_scnode->module;
} else {
*mod = set->cur_mod;
}
break;
case LY_VALUE_XML:
/* all identifiers need to be prefixed */
LOGVAL(set->ctx, LYVE_DATA, "Non-prefixed identity \"%.*s\" in XML xpath found.", (int)*qname_len, *qname);
return LY_EVALID;
}

return LY_SUCCESS;
}

static LY_ERR
xpath_derived_(struct lyxp_set **args, struct lyxp_set *set, uint32_t options, ly_bool self_match, const char *func)
{
Expand Down Expand Up @@ -4147,12 +4192,8 @@ xpath_derived_(struct lyxp_set **args, struct lyxp_set *set, uint32_t options, l
/* parse the identity */
id_name = args[1]->val.str;
id_len = strlen(id_name);
rc = moveto_resolve_model(&id_name, &id_len, set, &mod);
rc = xpath_derived_ident_module(&id_name, &id_len, set, &mod);
LY_CHECK_RET(rc);
if (!mod) {
LOGVAL(set->ctx, LYVE_XPATH, "Identity \"%.*s\" without a prefix.", (int)id_len, id_name);
return LY_EVALID;
}

/* find the identity */
found = 0;
Expand Down
32 changes: 32 additions & 0 deletions tests/utests/data/test_validation.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,37 @@ test_type_incomplete_when(void **state)
lyd_free_all(tree);
}

static void
test_unprefixed_ident(void **state)
{
struct lyd_node *tree;
const char *schema =
"module a {\n"
" namespace urn:tests:a;\n"
" prefix a;\n"
" yang-version 1.1;\n"
"\n"
" identity d3 {base d2;}\n"
" identity d2 {base d1;}\n"
" identity d1;\n"
"\n"
" leaf a {type identityref {base d1;}}\n"
" leaf b {type string; must \"derived-from-or-self(/a, 'd2')\";}\n"
" leaf c {type string; when \"derived-from(/a, 'd2')\";}\n"
"}";

UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);

CHECK_PARSE_LYD_PARAM("<b xmlns=\"urn:tests:a\">hey</b>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
CHECK_LOG_CTX("Must condition \"derived-from-or-self(/a, 'd2')\" not satisfied.", "/a:b", 0);

CHECK_PARSE_LYD_PARAM("<c xmlns=\"urn:tests:a\">hey</c>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
CHECK_LOG_CTX("When condition \"derived-from(/a, 'd2')\" not satisfied.", "/a:c", 0);

LYD_TREE_CREATE("<a xmlns=\"urn:tests:a\">d3</a><b xmlns=\"urn:tests:a\">b-val</b><c xmlns=\"urn:tests:a\">c-val</c>", tree);
lyd_free_all(tree);
}

static void
test_mandatory(void **state)
{
Expand Down Expand Up @@ -1523,6 +1554,7 @@ main(void)
UTEST(test_mandatory),
UTEST(test_mandatory_when),
UTEST(test_type_incomplete_when),
UTEST(test_unprefixed_ident),
UTEST(test_minmax),
UTEST(test_unique),
UTEST(test_unique_nested),
Expand Down

0 comments on commit 4b88556

Please sign in to comment.