Fix XER decoder of INTEGER, Issue #344.

    In some cases an INTEGER overflow during parsing is not detected
    and incorrect value is returned to the decoder instead of an error.
    Reported by Nika Pona <npona@digamma.ai>.
    (Severity: low; Seuciry impact: medium).
diff --git a/tests/tests-skeletons/check-INTEGER.c b/tests/tests-skeletons/check-INTEGER.c
index 5beff7d..705b165 100644
--- a/tests/tests-skeletons/check-INTEGER.c
+++ b/tests/tests-skeletons/check-INTEGER.c
@@ -178,6 +178,129 @@
 	ASN_STRUCT_FREE(asn_DEF_INTEGER, st);
 }
 
+static void
+check_strtoimax() {
+    const intmax_t intmax_max = ((~(uintmax_t)0) >> 1);
+    const intmax_t intmax_min = -((intmax_t)intmax_max) - 1;
+    char positive_max[32];
+    char negative_min[32];
+    const int len_pmax = snprintf(positive_max, sizeof(positive_max),
+        "+%" ASN_PRIdMAX, intmax_max);
+    const int len_nmin = snprintf(negative_min, sizeof(negative_min),
+        "%" ASN_PRIdMAX, intmax_min);
+    assert(len_pmax < (int)sizeof(positive_max));
+    assert(len_nmin < (int)sizeof(negative_min));
+
+    enum asn_strtox_result_e result;
+    intmax_t value;
+
+    /*
+     * Test edge values first.
+     */
+    // Positive.
+    const char *last_pmax = &positive_max[len_pmax];
+    result = asn_strtoimax_lim(positive_max, &last_pmax, &value);
+    assert(result == ASN_STRTOX_OK);
+    assert(last_pmax == &positive_max[len_pmax]);
+    assert(value == intmax_max);
+    // Negative.
+    const char *last_nmin = &negative_min[len_nmin];
+    result = asn_strtoimax_lim(negative_min, &last_nmin, &value);
+    assert(result == ASN_STRTOX_OK);
+    assert(last_nmin == &negative_min[len_nmin]);
+    assert(value == intmax_min);
+
+    /*
+     * Test one smaller than edge evalues.
+     */
+    positive_max[len_pmax - 1]--;
+    negative_min[len_nmin - 1]--;
+    // Positive.
+    result = asn_strtoimax_lim(positive_max, &last_pmax, &value);
+    assert(result == ASN_STRTOX_OK);
+    assert(last_pmax == &positive_max[len_pmax]);
+    assert(value == intmax_max - 1);
+    // Negative.
+    result = asn_strtoimax_lim(negative_min, &last_nmin, &value);
+    assert(result == ASN_STRTOX_OK);
+    assert(last_nmin == &negative_min[len_nmin]);
+    assert(value == intmax_min + 1);
+
+    /*
+     * Test one bigger than edge evalues.
+     */
+    positive_max[len_pmax - 1] += 2;
+    negative_min[len_nmin - 1] += 2;
+    // Positive.
+    value = 42;
+    result = asn_strtoimax_lim(positive_max, &last_pmax, &value);
+    assert(result == ASN_STRTOX_ERROR_RANGE);
+    assert(last_pmax == &positive_max[len_pmax - 1]);
+    assert(value == 42);
+    // Negative.
+    value = 42;
+    result = asn_strtoimax_lim(negative_min, &last_nmin, &value);
+    assert(result == ASN_STRTOX_ERROR_RANGE);
+    assert(last_nmin == &negative_min[len_nmin - 1]);
+    assert(value == 42);
+
+    /*
+     * Get back to the edge.
+     * Append an extra digit at the end.
+     */
+    positive_max[len_pmax - 1]--;
+    negative_min[len_nmin - 1]--;
+    assert(len_pmax < (int)sizeof(positive_max) - 1);
+    assert(len_nmin < (int)sizeof(negative_min) - 1);
+    strcat(positive_max, "0");
+    strcat(negative_min, "0");
+    last_pmax++;
+    last_nmin++;
+    value = 42;
+    result = asn_strtoimax_lim(positive_max, &last_pmax, &value);
+    assert(result == ASN_STRTOX_OK);
+    assert(value == intmax_max);
+    result = asn_strtoimax_lim(negative_min, &last_nmin, &value);
+    assert(result == ASN_STRTOX_OK);
+    assert(value == intmax_min);
+}
+
+/*
+ * Check that asn_strtoimax_lim() always reaches the end of the numeric
+ * sequence, even if it can't fit into the range.
+ */
+static void
+check_strtoimax_span() {
+    const intmax_t intmax_max = ((~(uintmax_t)0) >> 1);
+    const intmax_t almost_min = -((intmax_t)(intmax_max - 10));
+    char buf[64];
+    intmax_t value = 42;
+    enum asn_strtox_result_e result;
+
+    // Check a particular way to integer overflow.
+    // Check that we scan until the very end.
+    int len = snprintf(buf, sizeof(buf), "%" PRIdMAX "0</end>", almost_min);
+    assert(len < (int)sizeof(buf));
+    const char *nmlast = &buf[len];
+    result = asn_strtoimax_lim(buf, &nmlast, &value);
+    assert(*nmlast == '0');
+    assert((ptrdiff_t)(nmlast - buf) == (ptrdiff_t)(len - strlen("0</end>")));
+    assert(result == ASN_STRTOX_ERROR_RANGE);
+    assert(value == 42);
+
+    // Check a particular way to integer overflow.
+    // Check that we scan until the very end.
+    len = snprintf(buf, sizeof(buf), "%" PRIdMAX "</end>", almost_min);
+    assert(len < (int)sizeof(buf));
+    nmlast = &buf[len];
+    result = asn_strtoimax_lim(buf, &nmlast, &value);
+    assert(*nmlast == '<');
+    assert((ptrdiff_t)(nmlast - buf) == (ptrdiff_t)(len - strlen("</end>")));
+    assert(result == ASN_STRTOX_EXTRA_DATA);
+    assert(value == almost_min);
+
+}
+
 int
 main() {
 	uint8_t buf1[] = { 1 };
@@ -298,5 +421,8 @@
         }
 #endif
 
+    check_strtoimax();
+    check_strtoimax_span();
+
 	return 0;
 }