data types BUGFIX several tests and bugfixes for parsing binary values from XML
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 86ae99a..389a8db 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -200,6 +200,13 @@
}
cur->schema = snode;
cur->parent = parent;
+ if (parent) {
+ parent->child->prev = cur;
+ } else if (prev) {
+ struct lyd_node *iter;
+ for (iter = prev; iter->prev->next; iter = iter->prev);
+ iter->prev = cur;
+ }
if (prev) {
cur->prev = prev;
prev->next = cur;
@@ -223,9 +230,14 @@
LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_SYNTAX, "Child element inside terminal node \"%s\" found.", cur->schema->name);
goto cleanup;
}
- lyd_value_validate((struct lyd_node_term*)cur, value, value_len,
- LY_TYPE_VALIDATE_CANONIZE | (dynamic ? LY_TYPE_VALIDATE_DYNAMIC : 0));
+ } else {
+ /* no content - validate empty value */
+ value = "";
+ value_len = 0;
}
+ ret = lyd_value_validate((struct lyd_node_term*)cur, value, value_len,
+ LY_TYPE_VALIDATE_CANONIZE | (dynamic ? LY_TYPE_VALIDATE_DYNAMIC : 0));
+ LY_CHECK_GOTO(ret, cleanup);
} else if (snode->nodetype & LYD_NODE_INNER) {
int dynamic = 0;
char *buffer = NULL, *value;
@@ -240,6 +252,7 @@
}
if (ctx->status == LYXML_ELEMENT) {
ret = lydxml_nodes(ctx, (struct lyd_node_inner*)cur, data, lyd_node_children_p(cur));
+ LY_CHECK_GOTO(ret, cleanup);
}
}
/* TODO anyxml/anydata */
@@ -261,6 +274,10 @@
xmlctx.line = 1;
ret = lydxml_nodes(&xmlctx, NULL, &data, result);
+ if (ret) {
+ lyd_free_all(*result);
+ *result = NULL;
+ }
lyxml_context_clear((struct lyxml_context*)&xmlctx);
return ret;
}
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 7938d15..c8ea09f 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -103,7 +103,7 @@
*err = NULL;
/* validate characters and remember the number of octets for length validation */
- if (value) {
+ if (value && value_len) {
/* silently skip leading/trailing whitespaces */
for (start = 0; (start < value_len) && isspace(value[start]); start++);
for (stop = value_len - 1; stop > start && isspace(value[stop]); stop--);
@@ -127,6 +127,8 @@
/* padding */
if (u == stop - 1 && value[stop] == '=') {
termination = 2;
+ count++;
+ u++;
} else if (u == stop){
termination = 1;
}
@@ -154,13 +156,13 @@
}
if (options & LY_TYPE_VALIDATE_CANONIZE) {
- if (start != 0 || stop != value_len - 1) {
+ if (start != 0 || stop != value_len) {
*canonized = lydict_insert_zc(ctx, strndup(&value[start], stop + 1 - start));
} else if (options & LY_TYPE_VALIDATE_DYNAMIC) {
*canonized = lydict_insert_zc(ctx, (char*)value);
value = NULL;
} else {
- *canonized = lydict_insert(ctx, value, value_len);
+ *canonized = lydict_insert(ctx, value_len ? value : "", value_len);
}
}
if (options & LY_TYPE_VALIDATE_DYNAMIC) {
diff --git a/src/tree_data.c b/src/tree_data.c
index a972d4c..86d183b 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -90,10 +90,11 @@
static struct lyd_node *
lyd_parse_mem_(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, va_list ap)
{
- LY_ERR ret = LY_SUCCESS;
struct lyd_node *result = NULL;
const struct lyd_node *rpc_act = NULL, *data_tree = NULL, *iter;
+#if 0
const char *yang_data_name = NULL;
+#endif
if (lyd_parse_check_options(ctx, options, __func__)) {
return NULL;
@@ -133,9 +134,11 @@
}
}
}
+#if 0
if (options & LYD_OPT_DATA_TEMPLATE) {
yang_data_name = va_arg(ap, const char *);
}
+#endif
if (!format) {
/* TODO try to detect format from the content */
@@ -143,14 +146,14 @@
switch (format) {
case LYD_XML:
- ret = lyd_parse_xml(ctx, data, options, &result);
+ lyd_parse_xml(ctx, data, options, &result);
break;
#if 0
case LYD_JSON:
- ret = lyd_parse_json(ctx, data, options, rpc_act, data_tree, yang_data_name);
+ lyd_parse_json(ctx, data, options, rpc_act, data_tree, yang_data_name);
break;
case LYD_LYB:
- ret = lyd_parse_lyb(ctx, data, options, data_tree, yang_data_name, NULL);
+ lyd_parse_lyb(ctx, data, options, data_tree, yang_data_name, NULL);
break;
#endif
case LYD_UNKNOWN:
@@ -158,11 +161,6 @@
break;
}
- if (ret) {
- lyd_free_all(result);
- result = NULL;
- }
-
return result;
}
diff --git a/src/xml.c b/src/xml.c
index a318420..8ae6221 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -330,7 +330,8 @@
return rc;
} else {
/* whitespace-only content */
- len = offset - 1;
+ len = offset;
+ context->status++;
goto success;
}
}
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index 6eb7b8e..1f1119a 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -57,7 +57,7 @@
{
struct state_s *s;
const char *schema_a = "module types {namespace urn:tests:types;prefix t;yang-version 1.1;"
- "leaf binary {type binary {length 5;}}"
+ "leaf binary {type binary {length 5 {error-message \"This bas64 value must be of length 5.\";}}}"
"leaf binary-norestr {type binary;}}";
s = calloc(1, sizeof *s);
@@ -113,14 +113,20 @@
struct lyd_node *tree;
struct lyd_node_term *leaf;
- const char *data = "<binary xmlns=\"urn:tests:types\">\n aGVsbG8= \t\n </binary>";
+ const char *data = "<binary xmlns=\"urn:tests:types\">\n aGVs\nbG8= \t\n </binary>"
+ "<binary-norestr xmlns=\"urn:tests:types\">TQ==</binary-norestr>";
/* valid data (hello) */
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
assert_int_equal(LYS_LEAF, tree->schema->nodetype);
assert_string_equal("binary", tree->schema->name);
leaf = (struct lyd_node_term*)tree;
- assert_string_equal("aGVsbG8=", leaf->value.canonized);
+ assert_string_equal("aGVs\nbG8=", leaf->value.canonized);
+ assert_non_null(tree = tree->next);
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("binary-norestr", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("TQ==", leaf->value.canonized);
lyd_free_all(tree);
/* no data */
@@ -131,6 +137,41 @@
leaf = (struct lyd_node_term*)tree;
assert_string_equal("", leaf->value.canonized);
lyd_free_all(tree);
+ data = "<binary-norestr xmlns=\"urn:tests:types\"></binary-norestr>";
+ assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("binary-norestr", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("", leaf->value.canonized);
+ lyd_free_all(tree);
+ data = "<binary-norestr xmlns=\"urn:tests:types\"/>";
+ assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("binary-norestr", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("", leaf->value.canonized);
+ lyd_free_all(tree);
+
+ /* invalid base64 character */
+ data = "<binary-norestr xmlns=\"urn:tests:types\">a@bcd=</binary-norestr>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Invalid Base64 character (@). /");
+
+ /* missing data */
+ data = "<binary-norestr xmlns=\"urn:tests:types\">aGVsbG8</binary-norestr>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Base64 encoded value length must be divisible by 4. /");
+ data = "<binary-norestr xmlns=\"urn:tests:types\">VsbG8=</binary-norestr>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Base64 encoded value length must be divisible by 4. /");
+
+ /* invalid binary length */
+ data = "<binary xmlns=\"urn:tests:types\">aGVsbG93b3JsZA==</binary>"; /* helloworld */
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("This bas64 value must be of length 5. /");
+ data = "<binary xmlns=\"urn:tests:types\">TQ==</binary>"; /* M */
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("This bas64 value must be of length 5. /");
s->func = NULL;
}