]> 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:31 +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 e3a4998df11fcb38d556d8c709b556118968619e..19ea39a786eb05d14b5783f3fee8381443fed2c8 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 1005b9952c9a6c0f6db9788295204464b6c157f6..88c5342c538eca7dfa3937fdb1eb06ae91e8f426 100644 (file)
@@ -107,6 +107,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 },
@@ -169,6 +173,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"