Skip to content

Commit

Permalink
xpath BUGFIX inheriting modules for unprefixed nodes
Browse files Browse the repository at this point in the history
Reverts some previous changes and now JSON format
is used for user XPaths when unprefixed nodes
match every module and instance-ids when the
moduloe should be inherited but is not (should
not matter).
  • Loading branch information
michalvasko committed Jan 8, 2025
1 parent 08a2b06 commit 13bdd03
Showing 1 changed file with 52 additions and 51 deletions.
103 changes: 52 additions & 51 deletions src/xpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static LY_ERR reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, u
static LY_ERR eval_expr_select(const struct lyxp_expr *exp, uint32_t *tok_idx, enum lyxp_expr_type etype,
struct lyxp_set *set, uint32_t options);
static LY_ERR moveto_resolve_model(const char **qname, uint32_t *qname_len, const struct lyxp_set *set,
const struct lys_module **moveto_mod);
const struct lysc_node *ctx_scnode, const struct lys_module **moveto_mod);
static LY_ERR moveto_axis_node_next(const struct lyd_node **iter, enum lyxp_node_type *iter_type,
const struct lyd_node *node, enum lyxp_node_type node_type, enum lyxp_axis axis, struct lyxp_set *set);
static LY_ERR moveto_node(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname,
Expand Down Expand Up @@ -4112,33 +4112,11 @@ 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 */
LY_CHECK_RET(moveto_resolve_model(qname, qname_len, set, set->cur_node ? set->cur_node->schema : NULL, mod));
if (!*mod) {
/* unprefixed JSON identity */
assert(set->format == LY_VALUE_JSON);
*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;
Expand Down Expand Up @@ -5673,47 +5651,69 @@ xpath_pi_text(struct lyxp_set *set, enum lyxp_axis axis, uint32_t options)
}

/**
* @brief Skip prefix and return corresponding model if there is a prefix. Logs directly.
* @brief Skip prefix and return corresponding model. Logs directly.
*
* XPath @p set is expected to be a (sc)node set!
*
* @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[in] ctx_scnode Current context schema node (parent).
* @param[out] moveto_mod Expected module of a matching node.
* @return LY_ERR
*/
static LY_ERR
moveto_resolve_model(const char **qname, uint32_t *qname_len, const struct lyxp_set *set,
const struct lys_module **moveto_mod)
const struct lysc_node *ctx_scnode, const struct lys_module **moveto_mod)
{
const struct lys_module *mod = NULL;
const char *ptr;
size_t pref_len;

assert((set->type == LYXP_SET_NODE_SET) || (set->type == LYXP_SET_SCNODE_SET));

*moveto_mod = NULL;
if ((ptr = ly_strnchr(*qname, ':', *qname_len))) {
/* specific module */
pref_len = ptr - *qname;
mod = ly_resolve_prefix(set->ctx, *qname, pref_len, set->format, set->prefix_data);

ptr = ly_strnchr(*qname, ':', *qname_len);
if (!ptr) {
/* no prefix */
return LY_SUCCESS;
}

/* specific module */
pref_len = ptr - *qname;
mod = ly_resolve_prefix(set->ctx, *qname, pref_len, set->format, set->prefix_data);
/* check for errors and non-implemented modules, as they are not valid */
if (!mod || !mod->implemented) {
LOGVAL(set->ctx, LY_VCODE_XP_INMOD, (int)pref_len, *qname);
return LY_EVALID;
}

/* check for errors and non-implemented modules, as they are not valid */
if (!mod || !mod->implemented) {
LOGVAL(set->ctx, LY_VCODE_XP_INMOD, (int)pref_len, *qname);
return LY_EVALID;
*qname += pref_len + 1;
*qname_len -= pref_len + 1;
} else if (((*qname)[0] == '*') && (*qname_len == 1)) {
/* all modules - special case */
mod = NULL;
} else {
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 (ctx_scnode) {
mod = ctx_scnode->module;
} else {
/* JSON XPath is our own format (except for identityref), which supports node names matching all the modules */
mod = NULL;
}
break;
case LY_VALUE_XML:
/* all nodes need to be prefixed */
LOGVAL(set->ctx, LYVE_DATA, "Non-prefixed node \"%.*s\" in XML xpath found.", (int)*qname_len, *qname);
return LY_EVALID;
}
}

*qname += pref_len + 1;
*qname_len -= pref_len + 1;

*moveto_mod = mod;
return LY_SUCCESS;
}
Expand Down Expand Up @@ -7683,20 +7683,21 @@ eval_literal(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_set *se
*
* @param[in] nametest Nametest to check.
* @param[in] len Length of @p nametest.
* @param[in] ctx_scnode Found schema node as the context for the predicate.
* @param[in] set Context set.
* @param[in] key Expected key node.
* @return LY_SUCCESS on success,
* @return LY_ENOT if a predicate could not be compiled.
* @return LY_ERR on any error.
*/
static LY_ERR
eval_name_test_try_compile_predicate_key(const char *nametest, uint32_t len, const struct lyxp_set *set,
const struct lysc_node *key)
eval_name_test_try_compile_predicate_key(const char *nametest, uint32_t len, const struct lysc_node *ctx_scnode,
const struct lyxp_set *set, const struct lysc_node *key)
{
const struct lys_module *mod;

/* prefix (module) */
LY_CHECK_RET(moveto_resolve_model(&nametest, &len, set, &mod));
LY_CHECK_RET(moveto_resolve_model(&nametest, &len, set, ctx_scnode, &mod));
if (mod && (mod != key->module)) {
return LY_ENOT;
}
Expand Down Expand Up @@ -7855,7 +7856,7 @@ eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint32_t *tok

/* check key */
LY_CHECK_GOTO(rc = eval_name_test_try_compile_predicate_key(exp->expr + exp->tok_pos[e_idx],
exp->tok_len[e_idx], set, key), cleanup);
exp->tok_len[e_idx], ctx_scnode, set, key), cleanup);

++e_idx;

Expand Down Expand Up @@ -8155,7 +8156,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en
}

/* parse (and skip) module name */
rc = moveto_resolve_model(&ncname, &ncname_len, set, &moveto_mod);
rc = moveto_resolve_model(&ncname, &ncname_len, set, NULL, &moveto_mod);
LY_CHECK_GOTO(rc, cleanup);

if ((ncname[0] == '*') && (ncname_len == 1)) {
Expand Down

0 comments on commit 13bdd03

Please sign in to comment.