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;
 }