parser BUGFIX any content parsing
Any data whatsoever must be possible
to parse.
diff --git a/src/in.c b/src/in.c
index 359e407..278b77a 100644
--- a/src/in.c
+++ b/src/in.c
@@ -443,6 +443,11 @@
LOG_LOCSET(snode, NULL, NULL, NULL);
+ if (lydctx->int_opts & LYD_INTOPT_ANY) {
+ /* nothing to check, everything is allowed */
+ goto cleanup;
+ }
+
if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
rc = LY_EVALID;
diff --git a/src/parser_internal.h b/src/parser_internal.h
index 4681b13..b81a6ff 100644
--- a/src/parser_internal.h
+++ b/src/parser_internal.h
@@ -36,8 +36,9 @@
#define LYD_INTOPT_ACTION 0x02 /**< Action request is being parsed. */
#define LYD_INTOPT_REPLY 0x04 /**< RPC/action reply is being parsed. */
#define LYD_INTOPT_NOTIF 0x08 /**< Notification is being parsed. */
-#define LYD_INTOPT_WITH_SIBLINGS 0x10 /**< Parse the whole input with any siblings. */
-#define LYD_INTOPT_NO_SIBLINGS 0x20 /**< If there are any siblings, return an error. */
+#define LYD_INTOPT_ANY 0x10 /**< Anydata/anyxml content is being parsed, there can be anything. */
+#define LYD_INTOPT_WITH_SIBLINGS 0x20 /**< Parse the whole input with any siblings. */
+#define LYD_INTOPT_NO_SIBLINGS 0x40 /**< If there are any siblings, return an error. */
/**
* @brief Internal (common) context for YANG data parsers.
diff --git a/src/parser_json.c b/src/parser_json.c
index c47b47f..ca11b31 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1123,7 +1123,7 @@
{
LY_ERR ret;
uint32_t type_hints = 0;
- uint32_t prev_opts;
+ uint32_t prev_parse_opts, prev_int_opts;
struct lyd_node *tree = NULL;
ret = lydjson_data_check_opaq(lydctx, snode, &type_hints);
@@ -1187,9 +1187,11 @@
/* parse any data tree with correct options */
/* first backup the current options and then make the parser to process data as opaq nodes */
- prev_opts = lydctx->parse_opts;
+ prev_parse_opts = lydctx->parse_opts;
lydctx->parse_opts &= ~LYD_PARSE_STRICT;
lydctx->parse_opts |= LYD_PARSE_OPAQ;
+ prev_int_opts = lydctx->int_opts;
+ lydctx->int_opts |= LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS;
/* process the anydata content */
while (*status != LYJSON_OBJECT_CLOSED && *status != LYJSON_OBJECT_EMPTY) {
@@ -1199,7 +1201,8 @@
}
/* restore parser options */
- lydctx->parse_opts = prev_opts;
+ lydctx->parse_opts = prev_parse_opts;
+ lydctx->int_opts = prev_int_opts;
/* finish linking metadata */
ret = lydjson_metadata_finish(lydctx, &tree);
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index d569f6c..36c8f43 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -39,6 +39,10 @@
#include "validation.h"
#include "xml.h"
+static LY_ERR _lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+ struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
+ struct ly_set *parsed, struct lyd_ctx **lydctx_p);
+
void
lylyb_ctx_free(struct lylyb_ctx *ctx)
{
@@ -704,6 +708,44 @@
}
/**
+ * @brief Parse the context of anydata/anyxml node.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] data LYB data to parse.
+ * @param[out] tree Parsed tree.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
+{
+ LY_ERR ret;
+ uint32_t prev_lo;
+ struct ly_in *in;
+ struct lyd_ctx *lydctx = NULL;
+
+ *tree = NULL;
+
+ LY_CHECK_RET(ly_in_new_memory(data, &in));
+
+ /* turn logging off */
+ prev_lo = ly_log_options(0);
+
+ ret = _lyd_parse_lyb(ctx, NULL, NULL, tree, in, LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0,
+ LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
+
+ /* turn logging on again */
+ ly_log_options(prev_lo);
+
+ ly_in_free(in, 0);
+ lydctx->free(lydctx);
+ if (ret) {
+ lyd_free_siblings(*tree);
+ *tree = NULL;
+ }
+ return ret;
+}
+
+/**
* @brief Parse LYB subtree.
*
* @param[in] lybctx LYB context.
@@ -726,7 +768,7 @@
ly_bool dynamic = 0;
LY_VALUE_FORMAT format = 0;
void *val_prefix_data = NULL;
- uint32_t prev_lo, flags;
+ uint32_t flags;
const struct ly_ctx *ctx = lybctx->lybctx->ctx;
/* register a new subtree */
@@ -855,19 +897,13 @@
dynamic = 1;
if (value_type == LYD_ANYDATA_LYB) {
- /* turn logging off */
- prev_lo = ly_log_options(0);
-
/* try to parse LYB into a data tree */
- if (lyd_parse_data_mem(ctx, value, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0, &tree) == LY_SUCCESS) {
+ if (!lyb_parse_any_content(ctx, value, &tree)) {
/* successfully parsed */
free(value);
value = (char *)tree;
value_type = LYD_ANYDATA_DATATREE;
}
-
- /* turn logging on again */
- ly_log_options(prev_lo);
}
/* create the node */
@@ -1036,14 +1072,13 @@
return LY_SUCCESS;
}
-LY_ERR
-lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
- struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
+static LY_ERR
+_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+ struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
struct ly_set *parsed, struct lyd_ctx **lydctx_p)
{
LY_ERR rc = LY_SUCCESS;
struct lyd_lyb_ctx *lybctx;
- uint32_t int_opts;
assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
@@ -1057,27 +1092,8 @@
lybctx->lybctx->ctx = ctx;
lybctx->parse_opts = parse_opts;
lybctx->val_opts = val_opts;
- lybctx->free = lyd_lyb_ctx_free;
-
- switch (data_type) {
- case LYD_TYPE_DATA_YANG:
- int_opts = LYD_INTOPT_WITH_SIBLINGS;
- break;
- case LYD_TYPE_RPC_YANG:
- int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
- break;
- case LYD_TYPE_NOTIF_YANG:
- int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
- break;
- case LYD_TYPE_REPLY_YANG:
- int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
- break;
- default:
- LOGINT(ctx);
- rc = LY_EINT;
- goto cleanup;
- }
lybctx->int_opts = int_opts;
+ lybctx->free = lyd_lyb_ctx_free;
lybctx->ext = ext;
/* find the operation node if it exists already */
@@ -1132,6 +1148,37 @@
return rc;
}
+LY_ERR
+lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
+ struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
+ struct ly_set *parsed, struct lyd_ctx **lydctx_p)
+{
+ uint32_t int_opts;
+
+ assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
+ assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
+
+ switch (data_type) {
+ case LYD_TYPE_DATA_YANG:
+ int_opts = LYD_INTOPT_WITH_SIBLINGS;
+ break;
+ case LYD_TYPE_RPC_YANG:
+ int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
+ break;
+ case LYD_TYPE_NOTIF_YANG:
+ int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
+ break;
+ case LYD_TYPE_REPLY_YANG:
+ int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
+ break;
+ default:
+ LOGINT(ctx);
+ return LY_EINT;
+ }
+
+ return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
+}
+
API int
lyd_lyb_data_length(const char *data)
{
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 38fb07a..3e46ad4 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -655,7 +655,7 @@
lydctx->parse_opts &= ~LYD_PARSE_STRICT;
lydctx->parse_opts |= LYD_PARSE_OPAQ;
prev_int_opts = lydctx->int_opts;
- lydctx->int_opts |= LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF;
+ lydctx->int_opts |= LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS;
/* parse any data tree */
anchor = NULL;
diff --git a/tests/utests/data/test_lyb.c b/tests/utests/data/test_lyb.c
index 10470a2..7bce80e 100644
--- a/tests/utests/data/test_lyb.c
+++ b/tests/utests/data/test_lyb.c
@@ -299,6 +299,8 @@
" }\n"
" }\n"
"\n"
+ " notification notif;\n"
+ "\n"
" augment \"/random\" {\n"
" leaf aug-leaf {\n"
" type string;\n"
@@ -325,7 +327,7 @@
"<random xmlns=\"urn:module\">\n"
" <aleaf>string</aleaf>\n"
" <xml-data><anyxml>data</anyxml></xml-data>\n"
- " <any-data><data>any data</data></any-data>\n"
+ " <any-data><notif/></any-data>\n"
" <leaflist>l0</leaflist>\n"
" <leaflist>l1</leaflist>\n"
" <leaflist>l2</leaflist>\n"