]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add overflow checks to parse_number/parse_hex/parse_oct
authorNeil Horman <nhorman@openssl.org>
Tue, 28 Nov 2023 18:54:37 +0000 (13:54 -0500)
committerNeil Horman <nhorman@openssl.org>
Thu, 7 Dec 2023 17:21:52 +0000 (12:21 -0500)
Test the next arithmetic operation to safely determine if adding the
next digit in the passed property string will overflow

Also, noted a bug in the parse_hex code.  When parsing non-digit
characters (i.e. a-f and A-F), we do a tolower conversion (which is
fine), and then subtract 'a' to get the hex value from the ascii (which
is definately wrong).  We should subtract 'W' to convert tolower
converted hex digits in the range a-f to their hex value counterparts

Add tests to test_property_parse_error to ensure overflow checks work

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
(Merged from https://github.com/openssl/openssl/pull/22874)

(cherry picked from commit 986c48c4eb26861f25bc68ea252d8f2aad592735)

crypto/property/property_parse.c
test/property_test.c

index 8ba42a0dcb8adea72409841e9d49760c9208ec9d..f94d0d3d41db41b41c65ac52e30a9ad1e56f2ad3 100644 (file)
@@ -97,9 +97,18 @@ static int parse_number(const char *t[], OSSL_PROPERTY_DEFINITION *res)
     const char *s = *t;
     int64_t v = 0;
 
-    if (!ossl_isdigit(*s))
-        return 0;
     do {
+        if (!ossl_isdigit(*s)) {
+            ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
+                           "HERE-->%s", *t);
+            return 0;
+        }
+        /* overflow check */
+        if (v > ((INT64_MAX - (*s - '0')) / 10)) {
+            ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+                           "Property %s overflows", *t);
+            return 0;
+        }
         v = v * 10 + (*s++ - '0');
     } while (ossl_isdigit(*s));
     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
@@ -117,15 +126,27 @@ static int parse_hex(const char *t[], OSSL_PROPERTY_DEFINITION *res)
 {
     const char *s = *t;
     int64_t v = 0;
+    int sval;
 
-    if (!ossl_isxdigit(*s))
-        return 0;
     do {
+        if (ossl_isdigit(*s)) {
+            sval = *s - '0';
+        } else if (ossl_isxdigit(*s)) {
+            sval = ossl_tolower(*s) - 'a' + 10;
+        } else {
+            ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
+                           "%s", *t);
+            return 0;
+        }
+
+        if (v > ((INT64_MAX - sval) / 16)) {
+            ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+                           "Property %s overflows", *t);
+            return 0;
+        }
+
         v <<= 4;
-        if (ossl_isdigit(*s))
-            v += *s - '0';
-        else
-            v += ossl_tolower(*s) - 'a';
+        v += sval;
     } while (ossl_isxdigit(*++s));
     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
         ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
@@ -143,9 +164,18 @@ static int parse_oct(const char *t[], OSSL_PROPERTY_DEFINITION *res)
     const char *s = *t;
     int64_t v = 0;
 
-    if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
-        return 0;
     do {
+        if (*s == '9' || *s == '8' || !ossl_isdigit(*s)) {
+            ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
+                           "HERE-->%s", *t);
+            return 0;
+        }
+        if (v > ((INT64_MAX - (*s - '0')) / 8)) {
+            ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+                           "Property %s overflows", *t);
+            return 0;
+        }
+
         v = (v << 3) + (*s - '0');
     } while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
index bba96fac0a0191613a181805a6c1dfafacb0a7a6..18f8cc8740e0d3d2236a33d8579ac9e55a64e0b7 100644 (file)
@@ -136,6 +136,10 @@ static const struct {
     { "n=0x3", "n=3", 1 },
     { "n=0x3", "n=-3", -1 },
     { "n=0x33", "n=51", 1 },
+    { "n=0x123456789abcdef", "n=0x123456789abcdef", 1 },
+    { "n=0x7fffffffffffffff", "n=0x7fffffffffffffff", 1 },   /* INT64_MAX */
+    { "n=9223372036854775807", "n=9223372036854775807", 1 }, /* INT64_MAX */
+    { "n=0777777777777777777777", "n=0777777777777777777777", 1 }, /* INT64_MAX */
     { "n=033", "n=27", 1 },
     { "n=0", "n=00", 1 },
     { "n=0x0", "n=0", 1 },
@@ -198,6 +202,9 @@ static const struct {
     { 1, "a=2, n=012345678" },  /* Bad octal digit */
     { 0, "n=0x28FG, a=3" },     /* Bad hex digit */
     { 0, "n=145d, a=2" },       /* Bad decimal digit */
+    { 0, "n=0x8000000000000000, a=3" },     /* Hex overflow */
+    { 0, "n=922337203000000000d, a=2" },    /* Decimal overflow */
+    { 0, "a=2, n=1000000000000000000000" }, /* Octal overflow */
     { 1, "@='hello'" },         /* Invalid name */
     { 1, "n0123456789012345678901234567890123456789"
          "0123456789012345678901234567890123456789"