date and time UPDATE gross errors check

Fixes #2072
diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c
index dbde52f..f772f97 100644
--- a/src/plugins_types/date_and_time.c
+++ b/src/plugins_types/date_and_time.c
@@ -3,7 +3,7 @@
  * @author Michal Vasko <mvasko@cesnet.cz>
  * @brief ietf-yang-types date-and-time type plugin.
  *
- * Copyright (c) 2019-2021 CESNET, z.s.p.o.
+ * Copyright (c) 2019-2023 CESNET, z.s.p.o.
  *
  * This source code is licensed under BSD 3-Clause License (the "License").
  * You may not use this file except in compliance with the License.
@@ -112,7 +112,10 @@
 
     /* convert to UNIX time and fractions of second */
     ret = ly_time_str2time(value, &val->time, &val->fractions_s);
-    LY_CHECK_GOTO(ret, cleanup);
+    if (ret) {
+        ret = ly_err_new(err, ret, 0, NULL, NULL, ly_last_errmsg());
+        goto cleanup;
+    }
 
     if (!strncmp(((char *)value + value_len) - 6, "-00:00", 6)) {
         /* unknown timezone */
diff --git a/src/tree_data_common.c b/src/tree_data_common.c
index 4602e98..8d1de06 100644
--- a/src/tree_data_common.c
+++ b/src/tree_data_common.c
@@ -1606,6 +1606,28 @@
     tm.tm_min = atoi(&value[14]);
     tm.tm_sec = atoi(&value[17]);
 
+    /* explicit checks for some gross errors */
+    if (tm.tm_mon > 11) {
+        LOGERR(NULL, LY_EINVAL, "Invalid date-and-time month \"%d\".", tm.tm_mon);
+        return LY_EINVAL;
+    }
+    if ((tm.tm_mday < 1) || (tm.tm_mday > 31)) {
+        LOGERR(NULL, LY_EINVAL, "Invalid date-and-time day of month \"%d\".", tm.tm_mday);
+        return LY_EINVAL;
+    }
+    if (tm.tm_hour > 23) {
+        LOGERR(NULL, LY_EINVAL, "Invalid date-and-time hours \"%d\".", tm.tm_hour);
+        return LY_EINVAL;
+    }
+    if (tm.tm_min > 59) {
+        LOGERR(NULL, LY_EINVAL, "Invalid date-and-time minutes \"%d\".", tm.tm_min);
+        return LY_EINVAL;
+    }
+    if (tm.tm_sec > 60) {
+        LOGERR(NULL, LY_EINVAL, "Invalid date-and-time seconds \"%d\".", tm.tm_sec);
+        return LY_EINVAL;
+    }
+
     t = timegm(&tm);
     i = 19;
 
@@ -1626,12 +1648,24 @@
         shift = 0;
     } else {
         shift = strtol(&value[i], NULL, 10);
+        if (shift > 23) {
+            LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%" PRIi64 "\".", shift);
+            return LY_EINVAL;
+        }
         shift = shift * 60 * 60; /* convert from hours to seconds */
-        shift_m = strtol(&value[i + 4], NULL, 10) * 60; /* includes conversion from minutes to seconds */
+
+        shift_m = strtol(&value[i + 4], NULL, 10);
+        if (shift_m > 59) {
+            LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone minutes \"%" PRIi64 "\".", shift_m);
+            return LY_EINVAL;
+        }
+        shift_m *= 60; /* convert from minutes to seconds */
+
         /* correct sign */
         if (shift < 0) {
             shift_m *= -1;
         }
+
         /* connect hours and minutes of the shift */
         shift = shift + shift_m;
     }
diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c
index 60649ef..0f78455 100644
--- a/tests/utests/types/yang_types.c
+++ b/tests/utests/types/yang_types.c
@@ -52,11 +52,11 @@
         lyd_free_all(tree); \
     }
 
-#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
+#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA, RET) \
     {\
         struct lyd_node *tree; \
         const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
-        CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
+        CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \
         assert_null(tree); \
     }
 
@@ -111,11 +111,17 @@
     TEST_SUCCESS_XML("a", "l", "2017-02-01T00:00:00-00:00", STRING, "2017-02-01T00:00:00-00:00");
     TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00");
 
-    TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00");
+    TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00", LY_EVALID);
     CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to "
             "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".",
             "Schema location \"/a:l\", line number 1.");
 
+    TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EINVAL);
+    CHECK_LOG_CTX("Invalid date-and-time month \"15\".", "Schema location \"/a:l\", line number 1.");
+
+    TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EINVAL);
+    CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "Schema location \"/a:l\", line number 1.");
+
     /* hex-string */
     TEST_SUCCESS_XML("a", "l21", "DB:BA:12:54:fa", STRING, "db:ba:12:54:fa");
     TEST_SUCCESS_XML("a", "l22", "f81D4fAE-7dec-11d0-A765-00a0c91E6BF6", STRING, "f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
@@ -131,10 +137,10 @@
             "/a:node1/node2[node3/b:node4]/b:node5 | b:node6 and (b:node7)");
     TEST_SUCCESS_XML("a", "l3", "/l3[. = '4']", STRING, "/l3[.='4']");
 
-    TEST_ERROR_XML("a", "l3", "/a:l3[. = '4']");
+    TEST_ERROR_XML("a", "l3", "/a:l3[. = '4']", LY_EVALID);
     CHECK_LOG_CTX("Failed to resolve prefix \"a\".", "Schema location \"/a:l3\", line number 1.");
     TEST_ERROR_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library", "l3",
-            "/yl:yang-library/yl:datastore/yl::name");
+            "/yl:yang-library/yl:datastore/yl::name", LY_EVALID);
     CHECK_LOG_CTX("Storing value failed.", "Schema location \"/a:l3\", line number 1.");
     CHECK_LOG_CTX("Invalid character 'y'[31] of expression '/yl:yang-library/yl:datastore/yl::name'.",
             "Schema location \"/a:l3\", line number 1.");