Skip to content

Commit

Permalink
parser BUGFIX any content parsing
Browse files Browse the repository at this point in the history
Any data whatsoever must be possible
to parse.
  • Loading branch information
michalvasko committed Jul 15, 2021
1 parent 3a70862 commit 02ed9d8
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 39 deletions.
5 changes: 5 additions & 0 deletions src/in.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)

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;
Expand Down
5 changes: 3 additions & 2 deletions src/parser_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ typedef void (*lyd_ctx_free_clb)(struct lyd_ctx *ctx);
#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.
Expand Down
9 changes: 6 additions & 3 deletions src/parser_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ lydjson_parse_instance(struct lyd_json_ctx *lydctx, struct lyd_node_inner *paren
{
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);
Expand Down Expand Up @@ -1187,9 +1187,11 @@ lydjson_parse_instance(struct lyd_json_ctx *lydctx, struct lyd_node_inner *paren

/* 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) {
Expand All @@ -1199,7 +1201,8 @@ lydjson_parse_instance(struct lyd_json_ctx *lydctx, struct lyd_node_inner *paren
}

/* 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);
Expand Down
111 changes: 79 additions & 32 deletions src/parser_lyb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -703,6 +707,44 @@ lyb_skip_subtree(struct lylyb_ctx *lybctx)
} while (LYB_LAST_SUBTREE(lybctx).written);
}

/**
* @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.
*
Expand All @@ -726,7 +768,7 @@ lyb_parse_subtree_r(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct
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 */
Expand Down Expand Up @@ -855,19 +897,13 @@ lyb_parse_subtree_r(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct
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 */
Expand Down Expand Up @@ -1036,14 +1072,13 @@ lyb_parse_header(struct lylyb_ctx *lybctx)
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));
Expand All @@ -1057,27 +1092,8 @@ lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, str
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 */
Expand Down Expand Up @@ -1132,6 +1148,37 @@ lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, str
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)
{
Expand Down
2 changes: 1 addition & 1 deletion src/parser_xml.c
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ lydxml_subtree_r(struct lyd_xml_ctx *lydctx, struct lyd_node *parent, struct lyd
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;
Expand Down
4 changes: 3 additions & 1 deletion tests/utests/data/test_lyb.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ test_statements(void **state)
" }\n"
" }\n"
"\n"
" notification notif;\n"
"\n"
" augment \"/random\" {\n"
" leaf aug-leaf {\n"
" type string;\n"
Expand All @@ -325,7 +327,7 @@ test_statements(void **state)
"<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"
Expand Down

0 comments on commit 02ed9d8

Please sign in to comment.