Skip to content

Commit b7ba2c9

Browse files
committed
xpath BUGFIX proper not-found support in unions
1 parent 0a0716d commit b7ba2c9

File tree

2 files changed

+83
-33
lines changed

2 files changed

+83
-33
lines changed

src/xpath.c

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -899,18 +899,21 @@ static void
899899
set_init(struct lyxp_set *new, const struct lyxp_set *set)
900900
{
901901
memset(new, 0, sizeof *new);
902-
if (set) {
903-
new->non_child_axis = set->non_child_axis;
904-
new->ctx = set->ctx;
905-
new->cur_node = set->cur_node;
906-
new->root_type = set->root_type;
907-
new->context_op = set->context_op;
908-
new->tree = set->tree;
909-
new->cur_mod = set->cur_mod;
910-
new->format = set->format;
911-
new->prefix_data = set->prefix_data;
912-
new->vars = set->vars;
902+
if (!set) {
903+
return;
913904
}
905+
906+
new->non_child_axis = set->non_child_axis;
907+
new->not_found = set->not_found;
908+
new->ctx = set->ctx;
909+
new->cur_node = set->cur_node;
910+
new->root_type = set->root_type;
911+
new->context_op = set->context_op;
912+
new->tree = set->tree;
913+
new->cur_mod = set->cur_mod;
914+
new->format = set->format;
915+
new->prefix_data = set->prefix_data;
916+
new->vars = set->vars;
914917
}
915918

916919
/**
@@ -7522,7 +7525,11 @@ eval_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_set *
75227525
*tok_idx = orig_exp;
75237526

75247527
rc = eval_expr_select(exp, tok_idx, 0, &set2, options);
7525-
if (rc != LY_SUCCESS) {
7528+
if (!rc && set2.not_found) {
7529+
set->not_found = 1;
7530+
break;
7531+
}
7532+
if (rc) {
75267533
lyxp_set_free_content(&set2);
75277534
return rc;
75287535
}
@@ -7571,6 +7578,9 @@ eval_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_set *
75717578
*tok_idx = orig_exp;
75727579

75737580
rc = eval_expr_select(exp, tok_idx, 0, set, options);
7581+
if (!rc && set->not_found) {
7582+
break;
7583+
}
75747584
LY_CHECK_RET(rc);
75757585

75767586
set->val.scnodes[i].in_ctx = pred_in_ctx;
@@ -7590,7 +7600,7 @@ eval_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_set *
75907600
set_fill_set(&set2, set);
75917601

75927602
rc = eval_expr_select(exp, tok_idx, 0, &set2, options);
7593-
if (rc != LY_SUCCESS) {
7603+
if (rc) {
75947604
lyxp_set_free_content(&set2);
75957605
return rc;
75967606
}
@@ -8205,8 +8215,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en
82058215

82068216
if (options & LYXP_SCNODE_ERROR) {
82078217
/* error */
8208-
rc = LY_ENOTFOUND;
8209-
goto cleanup;
8218+
set->not_found = 1;
82108219
}
82118220

82128221
/* skip the predicates and the rest of this path to not generate invalid warnings */
@@ -8248,10 +8257,8 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en
82488257
/* restore options */
82498258
options &= ~LYXP_SKIP_EXPR;
82508259
}
8251-
if (!(options & LYXP_SKIP_EXPR)) {
8252-
lydict_remove(set->ctx, ncname_dict);
8253-
ly_path_predicates_free(set->ctx, predicates);
8254-
}
8260+
lydict_remove(set->ctx, ncname_dict);
8261+
ly_path_predicates_free(set->ctx, predicates);
82558262
return rc;
82568263
}
82578264

@@ -8423,8 +8430,9 @@ eval_relative_location_path(const struct lyxp_expr *exp, uint32_t *tok_idx, ly_b
84238430
rc = eval_name_test_with_predicate(exp, tok_idx, axis, all_desc, set, options);
84248431
if (rc == LY_ENOT) {
84258432
assert(options & LYXP_SCNODE_ALL);
8426-
/* skip the rest of this path */
84278433
rc = LY_SUCCESS;
8434+
8435+
/* skip the rest of this path */
84288436
scnode_skip_path = 1;
84298437
options |= LYXP_SKIP_EXPR;
84308438
}
@@ -8673,8 +8681,9 @@ eval_function_call(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_s
86738681

86748682
rc = eval_expr_select(exp, tok_idx, 0, args[0], options);
86758683
LY_CHECK_GOTO(rc, cleanup);
8684+
set->not_found = args[0]->not_found;
86768685
} else {
8677-
rc = eval_expr_select(exp, tok_idx, 0, set, options | LYXP_SKIP_EXPR);
8686+
rc = eval_expr_select(exp, tok_idx, 0, set, options);
86788687
LY_CHECK_GOTO(rc, cleanup);
86798688
}
86808689
}
@@ -8696,8 +8705,11 @@ eval_function_call(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_s
86968705

86978706
rc = eval_expr_select(exp, tok_idx, 0, args[arg_count - 1], options);
86988707
LY_CHECK_GOTO(rc, cleanup);
8708+
if (args[arg_count - 1]->not_found) {
8709+
set->not_found = 1;
8710+
}
86998711
} else {
8700-
rc = eval_expr_select(exp, tok_idx, 0, set, options | LYXP_SKIP_EXPR);
8712+
rc = eval_expr_select(exp, tok_idx, 0, set, options);
87018713
LY_CHECK_GOTO(rc, cleanup);
87028714
}
87038715
}
@@ -8990,8 +9002,9 @@ static LY_ERR
89909002
eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
89919003
{
89929004
LY_ERR rc = LY_SUCCESS;
8993-
struct lyxp_set orig_set, set2;
89949005
uint32_t i;
9006+
struct lyxp_set orig_set, set2;
9007+
ly_bool found = 0;
89959008

89969009
assert(repeat);
89979010

@@ -9002,6 +9015,11 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat,
90029015

90039016
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_UNION, set, options);
90049017
LY_CHECK_GOTO(rc, cleanup);
9018+
if (set->not_found) {
9019+
set->not_found = 0;
9020+
} else {
9021+
found = 1;
9022+
}
90059023

90069024
/* ('|' PathExpr)* */
90079025
for (i = 0; i < repeat; ++i) {
@@ -9019,6 +9037,9 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat,
90199037
set_fill_set(&set2, &orig_set);
90209038
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_UNION, &set2, options);
90219039
LY_CHECK_GOTO(rc, cleanup);
9040+
if (!set2.not_found) {
9041+
found = 1;
9042+
}
90229043

90239044
/* eval */
90249045
if (options & LYXP_SCNODE_ALL) {
@@ -9032,6 +9053,9 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat,
90329053
cleanup:
90339054
lyxp_set_free_content(&orig_set);
90349055
lyxp_set_free_content(&set2);
9056+
if (!found) {
9057+
set->not_found = 1;
9058+
}
90359059
return rc;
90369060
}
90379061

@@ -9099,7 +9123,7 @@ static LY_ERR
90999123
eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set,
91009124
uint32_t options)
91019125
{
9102-
LY_ERR rc;
9126+
LY_ERR rc = LY_SUCCESS;
91039127
uint32_t i, this_op;
91049128
struct lyxp_set orig_set, set2;
91059129

@@ -9131,6 +9155,9 @@ eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_
91319155
set_fill_set(&set2, &orig_set);
91329156
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_MULTIPLICATIVE, &set2, options);
91339157
LY_CHECK_GOTO(rc, cleanup);
9158+
if (set2.not_found) {
9159+
set->not_found = 1;
9160+
}
91349161

91359162
/* eval */
91369163
if (options & LYXP_SCNODE_ALL) {
@@ -9166,7 +9193,7 @@ eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_
91669193
static LY_ERR
91679194
eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
91689195
{
9169-
LY_ERR rc;
9196+
LY_ERR rc = LY_SUCCESS;
91709197
uint32_t i, this_op;
91719198
struct lyxp_set orig_set, set2;
91729199

@@ -9198,6 +9225,9 @@ eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe
91989225
set_fill_set(&set2, &orig_set);
91999226
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_ADDITIVE, &set2, options);
92009227
LY_CHECK_GOTO(rc, cleanup);
9228+
if (set2.not_found) {
9229+
set->not_found = 1;
9230+
}
92019231

92029232
/* eval */
92039233
if (options & LYXP_SCNODE_ALL) {
@@ -9235,7 +9265,7 @@ eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe
92359265
static LY_ERR
92369266
eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
92379267
{
9238-
LY_ERR rc;
9268+
LY_ERR rc = LY_SUCCESS;
92399269
uint32_t i, this_op;
92409270
struct lyxp_set orig_set, set2;
92419271

@@ -9267,6 +9297,9 @@ eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t re
92679297
set_fill_set(&set2, &orig_set);
92689298
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_RELATIONAL, &set2, options);
92699299
LY_CHECK_GOTO(rc, cleanup);
9300+
if (set2.not_found) {
9301+
set->not_found = 1;
9302+
}
92709303

92719304
/* eval */
92729305
if (options & LYXP_SCNODE_ALL) {
@@ -9304,7 +9337,7 @@ eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t re
93049337
static LY_ERR
93059338
eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
93069339
{
9307-
LY_ERR rc;
9340+
LY_ERR rc = LY_SUCCESS;
93089341
uint32_t i, this_op;
93099342
struct lyxp_set orig_set, set2;
93109343

@@ -9336,6 +9369,9 @@ eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe
93369369
set_fill_set(&set2, &orig_set);
93379370
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_EQUALITY, &set2, options);
93389371
LY_CHECK_GOTO(rc, cleanup);
9372+
if (set2.not_found) {
9373+
set->not_found = 1;
9374+
}
93399375

93409376
/* eval */
93419377
if (options & LYXP_SCNODE_ALL) {
@@ -9374,7 +9410,7 @@ eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe
93749410
static LY_ERR
93759411
eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
93769412
{
9377-
LY_ERR rc;
9413+
LY_ERR rc = LY_SUCCESS;
93789414
struct lyxp_set orig_set, set2;
93799415
uint32_t i;
93809416

@@ -9414,6 +9450,9 @@ eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, s
94149450
set_fill_set(&set2, &orig_set);
94159451
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_AND, &set2, options);
94169452
LY_CHECK_GOTO(rc, cleanup);
9453+
if (set2.not_found) {
9454+
set->not_found = 1;
9455+
}
94179456

94189457
/* eval - just get boolean value actually */
94199458
if (set->type == LYXP_SET_SCNODE_SET) {
@@ -9446,7 +9485,7 @@ eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, s
94469485
static LY_ERR
94479486
eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
94489487
{
9449-
LY_ERR rc;
9488+
LY_ERR rc = LY_SUCCESS;
94509489
struct lyxp_set orig_set, set2;
94519490
uint32_t i;
94529491

@@ -9488,6 +9527,9 @@ eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, st
94889527
* but it does not matter */
94899528
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_OR, &set2, options);
94909529
LY_CHECK_GOTO(rc, cleanup);
9530+
if (set2.not_found) {
9531+
set->not_found = 1;
9532+
}
94919533

94929534
/* eval - just get boolean value actually */
94939535
if (set->type == LYXP_SET_SCNODE_SET) {
@@ -9674,7 +9716,10 @@ lyxp_eval(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct ly
96749716

96759717
/* evaluate */
96769718
rc = eval_expr_select(exp, &tok_idx, 0, set, options);
9677-
if (rc != LY_SUCCESS) {
9719+
if (!rc && set->not_found) {
9720+
rc = LY_ENOTFOUND;
9721+
}
9722+
if (rc) {
96789723
lyxp_set_free_content(set);
96799724
}
96809725

@@ -9915,7 +9960,7 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct
99159960
LY_VALUE_FORMAT format, void *prefix_data, const struct lysc_node *cur_scnode,
99169961
const struct lysc_node *ctx_scnode, struct lyxp_set *set, uint32_t options)
99179962
{
9918-
LY_ERR ret;
9963+
LY_ERR rc;
99199964
uint32_t tok_idx = 0;
99209965

99219966
LY_CHECK_ARG_RET(ctx, ctx, exp, set, LY_EINVAL);
@@ -9943,10 +9988,13 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct
99439988
LOG_LOCSET(set->cur_scnode, NULL, NULL, NULL);
99449989

99459990
/* evaluate */
9946-
ret = eval_expr_select(exp, &tok_idx, 0, set, options);
9991+
rc = eval_expr_select(exp, &tok_idx, 0, set, options);
9992+
if (!rc && set->not_found) {
9993+
rc = LY_ENOTFOUND;
9994+
}
99479995

99489996
LOG_LOCBACK(set->cur_scnode ? 1 : 0, 0, 0, 0);
9949-
return ret;
9997+
return rc;
99509998
}
99519999

995210000
LIBYANG_API_DEF const char *

src/xpath.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ struct lyxp_set {
298298
uint32_t ctx_size; /**< Position of the last node at the time the node was examined. */
299299
ly_bool non_child_axis; /**< Whether any node change was performed on a non-child axis. */
300300

301+
ly_bool not_found; /**< Set if a node is not found and it is considered an error. */
302+
301303
/* general context */
302304
struct ly_ctx *ctx; /**< General context for logging. */
303305

0 commit comments

Comments
 (0)