parser json UPDATE support for opaque nodes with invalid-encoded value
Fixes #2033
diff --git a/src/parser_json.c b/src/parser_json.c
index 9cbd5d8..40eb568 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -338,6 +338,55 @@
}
/**
+ * @brief Get the hint for the data type parsers according to the current JSON parser context.
+ *
+ * @param[in] jsonctx JSON parser context. The context is supposed to be on a value.
+ * @param[in,out] status Pointer to the current context status,
+ * in some circumstances the function manipulates with the context so the status is updated.
+ * @param[out] type_hint_p Pointer to the variable to store the result.
+ * @return LY_SUCCESS in case of success.
+ * @return LY_EINVAL in case of invalid context status not referring to a value.
+ */
+static LY_ERR
+lydjson_value_type_hint(struct lyjson_ctx *jsonctx, enum LYJSON_PARSER_STATUS *status_p, uint32_t *type_hint_p)
+{
+ *type_hint_p = 0;
+
+ if (*status_p == LYJSON_ARRAY) {
+ /* only [null] */
+ LY_CHECK_RET(lyjson_ctx_next(jsonctx, status_p));
+ if (*status_p != LYJSON_NULL) {
+ LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON,
+ "Expected JSON name/value or special name/[null], but input data contains name/[%s].",
+ lyjson_token2str(*status_p));
+ return LY_EINVAL;
+ }
+
+ LY_CHECK_RET(lyjson_ctx_next(jsonctx, NULL));
+ if (lyjson_ctx_status(jsonctx) != LYJSON_ARRAY_CLOSED) {
+ LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON, "Expected array end, but input data contains %s.",
+ lyjson_token2str(*status_p));
+ return LY_EINVAL;
+ }
+
+ *type_hint_p = LYD_VALHINT_EMPTY;
+ } else if (*status_p == LYJSON_STRING) {
+ *type_hint_p = LYD_VALHINT_STRING | LYD_VALHINT_NUM64;
+ } else if (*status_p == LYJSON_NUMBER) {
+ *type_hint_p = LYD_VALHINT_DECNUM;
+ } else if ((*status_p == LYJSON_FALSE) || (*status_p == LYJSON_TRUE)) {
+ *type_hint_p = LYD_VALHINT_BOOLEAN;
+ } else if (*status_p == LYJSON_NULL) {
+ *type_hint_p = 0;
+ } else {
+ LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON, "Unexpected input data %s.", lyjson_token2str(*status_p));
+ return LY_EINVAL;
+ }
+
+ return LY_SUCCESS;
+}
+
+/**
* @brief Check that the input data are parseable as the @p list.
*
* Checks for all the list's keys. Function does not revert the context state.
@@ -354,7 +403,7 @@
enum LYJSON_PARSER_STATUS status = lyjson_ctx_status(jsonctx);
struct ly_set key_set = {0};
const struct lysc_node *snode;
- uint32_t i;
+ uint32_t i, hints;
assert(list && (list->nodetype == LYS_LIST));
@@ -402,7 +451,9 @@
goto cleanup;
}
- rc = lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL);
+ rc = lydjson_value_type_hint(jsonctx, &status, &hints);
+ LY_CHECK_GOTO(rc, cleanup);
+ rc = ly_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL, hints);
LY_CHECK_GOTO(rc, cleanup);
/* key with a valid value, remove from the set */
@@ -430,55 +481,6 @@
}
/**
- * @brief Get the hint for the data type parsers according to the current JSON parser context.
- *
- * @param[in] lydctx JSON data parser context. The context is supposed to be on a value.
- * @param[in,out] status Pointer to the current context status,
- * in some circumstances the function manipulates with the context so the status is updated.
- * @param[out] type_hint_p Pointer to the variable to store the result.
- * @return LY_SUCCESS in case of success.
- * @return LY_EINVAL in case of invalid context status not referring to a value.
- */
-static LY_ERR
-lydjson_value_type_hint(struct lyd_json_ctx *lydctx, enum LYJSON_PARSER_STATUS *status_p, uint32_t *type_hint_p)
-{
- *type_hint_p = 0;
-
- if (*status_p == LYJSON_ARRAY) {
- /* only [null] */
- LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status_p));
- if (*status_p != LYJSON_NULL) {
- LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON,
- "Expected JSON name/value or special name/[null], but input data contains name/[%s].",
- lyjson_token2str(*status_p));
- return LY_EINVAL;
- }
-
- LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, NULL));
- if (lyjson_ctx_status(lydctx->jsonctx) != LYJSON_ARRAY_CLOSED) {
- LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Expected array end, but input data contains %s.",
- lyjson_token2str(*status_p));
- return LY_EINVAL;
- }
-
- *type_hint_p = LYD_VALHINT_EMPTY;
- } else if (*status_p == LYJSON_STRING) {
- *type_hint_p = LYD_VALHINT_STRING | LYD_VALHINT_NUM64;
- } else if (*status_p == LYJSON_NUMBER) {
- *type_hint_p = LYD_VALHINT_DECNUM;
- } else if ((*status_p == LYJSON_FALSE) || (*status_p == LYJSON_TRUE)) {
- *type_hint_p = LYD_VALHINT_BOOLEAN;
- } else if (*status_p == LYJSON_NULL) {
- *type_hint_p = 0;
- } else {
- LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Unexpected input data %s.", lyjson_token2str(*status_p));
- return LY_EINVAL;
- }
-
- return LY_SUCCESS;
-}
-
-/**
* @brief Check in advance if the input data are parsable according to the provided @p snode.
*
* Note that the checks are done only in case the LYD_PARSE_OPAQ is allowed. Otherwise the same checking
@@ -518,12 +520,10 @@
case LYS_LEAFLIST:
case LYS_LEAF:
/* value may not be valid in which case we parse it as an opaque node */
- ret = lydjson_value_type_hint(lydctx, &status, type_hint_p);
- if (ret) {
+ if ((ret = lydjson_value_type_hint(jsonctx, &status, type_hint_p))) {
break;
}
-
- if (lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL)) {
+ if (ly_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL, *type_hint_p)) {
ret = LY_ENOT;
}
break;
@@ -536,7 +536,7 @@
break;
}
} else if (snode->nodetype & LYD_NODE_TERM) {
- ret = lydjson_value_type_hint(lydctx, &status, type_hint_p);
+ ret = lydjson_value_type_hint(jsonctx, &status, type_hint_p);
}
/* restore parser */
@@ -846,7 +846,7 @@
LY_CHECK_GOTO(rc = lyjson_ctx_next(lydctx->jsonctx, &status), cleanup);
/* get value hints */
- LY_CHECK_GOTO(rc = lydjson_value_type_hint(lydctx, &status, &val_hints), cleanup);
+ LY_CHECK_GOTO(rc = lydjson_value_type_hint(lydctx->jsonctx, &status, &val_hints), cleanup);
if (node->schema) {
/* create metadata */
@@ -969,7 +969,7 @@
dynamic = lydctx->jsonctx->dynamic;
lydctx->jsonctx->dynamic = 0;
- LY_CHECK_RET(lydjson_value_type_hint(lydctx, status_inner_p, &type_hint));
+ LY_CHECK_RET(lydjson_value_type_hint(lydctx->jsonctx, status_inner_p, &type_hint));
}
/* get the module name */
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 54e6c8b..054e01a 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -286,7 +286,7 @@
assert(xmlctx->status == LYXML_ELEM_CONTENT);
if (i < key_set.count) {
/* validate the value */
- r = lys_value_validate(NULL, snode, xmlctx->value, xmlctx->value_len, LY_VALUE_XML, &xmlctx->ns);
+ r = ly_value_validate(NULL, snode, xmlctx->value, xmlctx->value_len, LY_VALUE_XML, &xmlctx->ns, LYD_HINT_DATA);
if (!r) {
/* key with a valid value, remove from the set */
ly_set_rm_index(&key_set, i, NULL);
@@ -392,7 +392,7 @@
if ((*snode)->nodetype & LYD_NODE_TERM) {
/* value may not be valid in which case we parse it as an opaque node */
- if (lys_value_validate(NULL, *snode, xmlctx->value, xmlctx->value_len, LY_VALUE_XML, &xmlctx->ns)) {
+ if (ly_value_validate(NULL, *snode, xmlctx->value, xmlctx->value_len, LY_VALUE_XML, &xmlctx->ns, LYD_HINT_DATA)) {
LOGVRB("Parsing opaque term node \"%s\" with invalid value \"%.*s\".", (*snode)->name, xmlctx->value_len,
xmlctx->value);
*snode = NULL;
diff --git a/src/tree_data_common.c b/src/tree_data_common.c
index 69c3851..65784ae 100644
--- a/src/tree_data_common.c
+++ b/src/tree_data_common.c
@@ -499,8 +499,8 @@
}
LY_ERR
-lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
- LY_VALUE_FORMAT format, void *prefix_data)
+ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
+ LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints)
{
LY_ERR rc = LY_SUCCESS;
struct ly_err_item *err = NULL;
@@ -515,8 +515,8 @@
}
type = ((struct lysc_node_leaf *)node)->type;
- rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, 0, format, prefix_data,
- LYD_HINT_SCHEMA, node, &storage, NULL, &err);
+ rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, 0, format, prefix_data, hints, node,
+ &storage, NULL, &err);
if (rc == LY_EINCOMPLETE) {
/* actually success since we do not provide the context tree and call validation with
* LY_TYPE_OPTS_INCOMPLETE_DATA */
@@ -778,8 +778,8 @@
ly_set_rm_index(&key_set, i, NULL);
/* check value */
- ret = lys_value_validate(LYD_CTX(node), key, opaq_k->value, strlen(opaq_k->value), opaq_k->format,
- opaq_k->val_prefix_data);
+ ret = ly_value_validate(LYD_CTX(node), key, opaq_k->value, strlen(opaq_k->value), opaq_k->format,
+ opaq_k->val_prefix_data, opaq_k->hints);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -889,7 +889,7 @@
if (snode->nodetype & LYD_NODE_TERM) {
/* leaf / leaf-list */
- rc = lys_value_validate(ctx, snode, opaq->value, strlen(opaq->value), opaq->format, opaq->val_prefix_data);
+ rc = ly_value_validate(ctx, snode, opaq->value, strlen(opaq->value), opaq->format, opaq->val_prefix_data, opaq->hints);
LY_CHECK_GOTO(rc, cleanup);
} else if (snode->nodetype == LYS_LIST) {
/* list */
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index e87723b..c7449ce 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -506,8 +506,7 @@
const struct lyd_node *ctx_node, const struct lyd_node *tree);
/**
- * @brief Check type restrictions applicable to the particular leaf/leaf-list with the given string @p value coming
- * from a schema.
+ * @brief Check type restrictions applicable to the particular leaf/leaf-list with the given string @p value.
*
* This function check just the type's restriction, if you want to check also the data tree context (e.g. in case of
* require-instance restriction), use ::lyd_value_validate().
@@ -518,11 +517,12 @@
* @param[in] value_len Length of the given @p value (mandatory).
* @param[in] format Value prefix format.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
+ * @param[in] hints Value encoding hints.
* @return LY_SUCCESS on success
* @return LY_ERR value if an error occurred.
*/
-LY_ERR lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
- LY_VALUE_FORMAT format, void *prefix_data);
+LY_ERR ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
+ LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints);
/**
* @defgroup datahash Data nodes hash manipulation