schema compile BUGFIX improve if-feature expression parsing
Fixes #804
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index e872d6e..623dd26 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -444,7 +444,9 @@
}
if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
- if (c[i + r] == '\0') {
+ int sp;
+ for(sp = 0; c[i + r + sp] && isspace(c[i + r + sp]); sp++);
+ if (c[i + r + sp] == '\0') {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
return LY_EVALID;
@@ -461,7 +463,13 @@
last_not = 1;
}
} else { /* and, or */
+ if (f_exp != f_size) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ "Invalid value \"%s\" of if-feature - missing feature/expression before \"%.*s\" operation.", *value, r, &c[i]);
+ return LY_EVALID;
+ }
f_exp++;
+
/* not a not operation */
last_not = 0;
}
@@ -473,19 +481,26 @@
expr_size++;
while (!isspace(c[i])) {
- if (!c[i] || c[i] == ')') {
+ if (!c[i] || c[i] == ')' || c[i] == '(') {
i--;
break;
}
i++;
}
}
- if (j || f_exp != f_size) {
+ if (j) {
/* not matching count of ( and ) */
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
return LY_EVALID;
}
+ if (f_exp != f_size) {
+ /* features do not match the needed arguments for the logical operations */
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ "Invalid value \"%s\" of if-feature - number of features in expression does not match "
+ "the required number of operands for the operations.", *value);
+ return LY_EVALID;
+ }
if (checkversion || expr_size > 1) {
/* check that we have 1.1 module */
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 530f119..f03d2d3 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -354,6 +354,21 @@
assert_null(lys_parse_mem(ctx.ctx, "module ab{namespace urn:ab; prefix ab; feature f1 {if-feature f1;}}", LYS_IN_YANG));
logbuf_assert("Feature \"f1\" is referenced from itself. /ab:{feature='f1'}");
+ assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f {if-feature ();}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"()\" of if-feature - number of features in expression does not match the required number "
+ "of operands for the operations. /bb:{feature='f'}");
+ assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1(';}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"f1(\" of if-feature - non-matching opening and closing parentheses. /bb:{feature='f'}");
+ assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'and f1';}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"and f1\" of if-feature - missing feature/expression before \"and\" operation. /bb:{feature='f'}");
+ assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not ';}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"f1 not \" of if-feature - unexpected end of expression. /bb:{feature='f'}");
+ assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not not ';}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"f1 not not \" of if-feature - unexpected end of expression. /bb:{feature='f'}");
+ assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f2; "
+ "feature f {if-feature 'or f1 f2';}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"or f1 f2\" of if-feature - missing feature/expression before \"or\" operation. /bb:{feature='f'}");
+
/* import reference */
assert_non_null(modp = lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
assert_int_equal(LY_SUCCESS, lys_feature_enable(modp, "f1"));