From 2a4de52e56dd11755b9b58f76af2a774d7088c1f Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 23 Feb 2021 15:24:39 +0100 Subject: [PATCH] * Added support for the following XPATH functions: * `false`, `true` * Fixed: [Negation operator in 'must' statement makes backend segmentation fault](https://github.com/clicon/clixon/issues/179) --- CHANGELOG.md | 3 ++ lib/src/clixon_xpath_eval.c | 10 +++++ lib/src/clixon_xpath_function.c | 80 +++++++++++++++++++++++++++------ lib/src/clixon_xpath_function.h | 10 +++-- lib/src/clixon_xpath_parse.y | 4 +- 5 files changed, 88 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f57359ad..f471a0e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,8 @@ Developers may need to change their code ### Minor changes +* Added support for the following XPATH functions: + * `false`, `true` * Augment target node check strict, instead of printing a warning, it will terminate with error. * Implemented: [Simplifying error messages for regex validations. #174](https://github.com/clicon/clixon/issues/174) * Add ca_reset plugin also when backend starts as `-s none` @@ -117,6 +119,7 @@ Developers may need to change their code ### Corrected Bugs +* Fixed: [Negation operator in 'must' statement makes backend segmentation fault](https://github.com/clicon/clixon/issues/179) * Fixed extension/unknown problem shown in latest openconfig where other than a single space was used between the unknown identifier and string * Fixed: [Augment that reference a submodule as target node fails #178](https://github.com/clicon/clixon/issues/178) * Fixed a memory error that was reported in slack by Pawel Maslanka diff --git a/lib/src/clixon_xpath_eval.c b/lib/src/clixon_xpath_eval.c index 3dd43c96..6bee001e 100644 --- a/lib/src/clixon_xpath_eval.c +++ b/lib/src/clixon_xpath_eval.c @@ -1040,6 +1040,16 @@ xp_eval(xp_ctx *xc, goto done; goto ok; break; + case XPATHFN_TRUE: + if (xp_function_true(xc, xs->xs_c0, nsc, localonly, xrp) < 0) + goto done; + goto ok; + break; + case XPATHFN_FALSE: + if (xp_function_false(xc, xs->xs_c0, nsc, localonly, xrp) < 0) + goto done; + goto ok; + break; default: clicon_err(OE_XML, EFAULT, "XPATH function not implemented: %s", xs->xs_s0); goto done; diff --git a/lib/src/clixon_xpath_function.c b/lib/src/clixon_xpath_function.c index 7dc19fc7..81b8ac54 100644 --- a/lib/src/clixon_xpath_function.c +++ b/lib/src/clixon_xpath_function.c @@ -74,6 +74,9 @@ #include "clixon_xpath_eval.h" #include "clixon_xpath_function.h" +/*! xpath function translation table + * @see enum clixon_xpath_function + */ static const map_str2int xpath_fnname_map[] = { /* alphabetic order */ {"bit-is-set", XPATHFN_BIT_IS_SET}, {"boolean", XPATHFN_BOOLEAN}, @@ -379,7 +382,7 @@ xp_function_derived_from(xp_ctx *xc, /*! Return a number equal to the context position from the expression evaluation context. * * Signature: number position(node-set) - * @param[in] xc0 Incoming context + * @param[in] xc Incoming context * @param[in] xs XPATH node tree * @param[in] nsc XML Namespace context * @param[in] localonly Skip prefix and namespace tests (non-standard) @@ -388,7 +391,7 @@ xp_function_derived_from(xp_ctx *xc, * @retval -1 Error */ int -xp_function_position(xp_ctx *xc0, +xp_function_position(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, @@ -402,9 +405,9 @@ xp_function_position(xp_ctx *xc0, goto done; } memset(xr, 0, sizeof(*xr)); - xr->xc_initial = xc0->xc_initial; + xr->xc_initial = xc->xc_initial; xr->xc_type = XT_NUMBER; - xr->xc_number = xc0->xc_position; + xr->xc_number = xc->xc_position; *xrp = xr; retval = 0; done: @@ -416,14 +419,13 @@ xp_function_position(xp_ctx *xc0, * Signature: number count(node-set) */ int -xp_function_count(xp_ctx *xc0, +xp_function_count(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp) { int retval = -1; - xp_ctx *xc = NULL; xp_ctx *xr = NULL; xp_ctx *xr0 = NULL; @@ -440,7 +442,7 @@ xp_function_count(xp_ctx *xc0, memset(xr, 0, sizeof(*xr)); xr->xc_type = XT_NUMBER; xr->xc_number = xr0->xc_number; - *xrp = xc; + *xrp = xr; retval = 0; done: if (xr0) @@ -456,14 +458,13 @@ xp_function_count(xp_ctx *xc0, * XXX: should return expanded-name, should namespace be included? */ int -xp_function_name(xp_ctx *xc0, +xp_function_name(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp) { int retval = -1; - xp_ctx *xc = NULL; xp_ctx *xr = NULL; xp_ctx *xr0 = NULL; char *s0 = NULL; @@ -491,7 +492,7 @@ xp_function_name(xp_ctx *xc0, } break; } - *xrp = xc; + *xrp = xr; retval = 0; done: if (xr0) @@ -565,14 +566,13 @@ xp_function_contains(xp_ctx *xc, * Signature: boolean not(boolean) */ int -xp_function_not(xp_ctx *xc0, +xp_function_not(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp) { int retval = -1; - xp_ctx *xc = NULL; xp_ctx *xr = NULL; xp_ctx *xr0 = NULL; int bool; @@ -591,10 +591,64 @@ xp_function_not(xp_ctx *xc0, memset(xr, 0, sizeof(*xr)); xr->xc_type = XT_BOOL; xr->xc_bool = !bool; - *xrp = xc; + *xrp = xr; retval = 0; done: if (xr0) ctx_free(xr0); return retval; } + +/*! The true function returns true. + * + * Signature: boolean true() + */ +int +xp_function_true(xp_ctx *xc, + struct xpath_tree *xs, + cvec *nsc, + int localonly, + xp_ctx **xrp) +{ + int retval = -1; + xp_ctx *xr = NULL; + + if ((xr = malloc(sizeof(*xr))) == NULL){ + clicon_err(OE_UNIX, errno, "malloc"); + goto done; + } + memset(xr, 0, sizeof(*xr)); + xr->xc_type = XT_BOOL; + xr->xc_bool = 1; + *xrp = xr; + retval = 0; + done: + return retval; +} + +/*! The false function returns false. + * + * Signature: boolean false() + */ +int +xp_function_false(xp_ctx *xc, + struct xpath_tree *xs, + cvec *nsc, + int localonly, + xp_ctx **xrp) +{ + int retval = -1; + xp_ctx *xr = NULL; + + if ((xr = malloc(sizeof(*xr))) == NULL){ + clicon_err(OE_UNIX, errno, "malloc"); + goto done; + } + memset(xr, 0, sizeof(*xr)); + xr->xc_type = XT_BOOL; + xr->xc_bool = 0; + *xrp = xr; + retval = 0; + done: + return retval; +} diff --git a/lib/src/clixon_xpath_function.h b/lib/src/clixon_xpath_function.h index f625d27c..a8f377bd 100644 --- a/lib/src/clixon_xpath_function.h +++ b/lib/src/clixon_xpath_function.h @@ -43,8 +43,8 @@ */ /* * XPath functions from Xpath 1.0 spec or YANG - * @see xp_checkfn where they are parsed and checked - * @see clixon_xpath_function.c for implementations + * @see xp_eval,xp_primary_function where they are parsed and checked + * @see clixon_xpath_function.ch] for implementation */ enum clixon_xpath_function{ XPATHFN_CURRENT, /* RFC 7950 10.1.1 */ @@ -73,8 +73,8 @@ enum clixon_xpath_function{ XPATHFN_TRANSLATE, /* XPATH 1.0 4.2 NYI */ XPATHFN_BOOLEAN, /* XPATH 1.0 4.3 NYI */ XPATHFN_NOT, /* XPATH 1.0 4.3 */ - XPATHFN_TRUE, /* XPATH 1.0 4.3 NYI */ - XPATHFN_FALSE, /* XPATH 1.0 4.3 NYI */ + XPATHFN_TRUE, /* XPATH 1.0 4.3 */ + XPATHFN_FALSE, /* XPATH 1.0 4.3 */ XPATHFN_LANG, /* XPATH 1.0 4.3 NYI */ XPATHFN_NUMBER, /* XPATH 1.0 4.4 NYI */ XPATHFN_SUM, /* XPATH 1.0 4.4 NYI */ @@ -101,5 +101,7 @@ int xp_function_count(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonl int xp_function_name(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp); int xp_function_contains(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp); int xp_function_not(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp); +int xp_function_true(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp); +int xp_function_false(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp); #endif /* _CLIXON_XPATH_FUNCTION_H */ diff --git a/lib/src/clixon_xpath_parse.y b/lib/src/clixon_xpath_parse.y index bb74dac1..cfb45267 100644 --- a/lib/src/clixon_xpath_parse.y +++ b/lib/src/clixon_xpath_parse.y @@ -248,8 +248,6 @@ xp_primary_function(clixon_xpath_yacc *xpy, case XPATHFN_NORMALIZE_SPACE: case XPATHFN_TRANSLATE: case XPATHFN_BOOLEAN: - case XPATHFN_TRUE: - case XPATHFN_FALSE: case XPATHFN_LANG: case XPATHFN_NUMBER: case XPATHFN_SUM: @@ -273,6 +271,8 @@ xp_primary_function(clixon_xpath_yacc *xpy, case XPATHFN_NAME: case XPATHFN_CONTAINS: case XPATHFN_NOT: + case XPATHFN_TRUE: + case XPATHFN_FALSE: break; default: if ((cb = cbuf_new()) == NULL){