]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
crypto/bio/bio_print.c: avoid integer overflow when reading width/precision
authorEugene Syromiatnikov <esyr@openssl.org>
Tue, 5 Aug 2025 12:51:22 +0000 (14:51 +0200)
committerNeil Horman <nhorman@openssl.org>
Fri, 29 Aug 2025 16:18:30 +0000 (12:18 -0400)
Both width and precision are "decimal digit strings" of unspecified size,
but we can realistically cap it at INT_MAX.

Signed-off-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28177)

crypto/bio/bio_print.c

index dc66603aad3903a3a00e35cafc8cf5e8e2c247cc..82aecf82acf7dad01aab2a03010767f9aec474f2 100644 (file)
@@ -158,9 +158,17 @@ _dopr(char **sbuffer,
                 break;
             }
             break;
-        case DP_S_MIN:
+        case DP_S_MIN: /* width */
             if (ossl_isdigit(ch)) {
-                min = 10 * min + char_to_int(ch);
+                /*
+                 * Most implementations cap the possible explicitly specified
+                 * width by (INT_MAX / 10) * 10 - 1 or so (the standard gives
+                 * no clear limit on this), we can do the same.
+                 */
+                if (min < INT_MAX / 10)
+                    min = 10 * min + char_to_int(ch);
+                else
+                    goto out;
                 ch = *format++;
             } else if (ch == '*') {
                 min = va_arg(args, int);
@@ -180,11 +188,19 @@ _dopr(char **sbuffer,
             } else
                 state = DP_S_MOD;
             break;
-        case DP_S_MAX:
+        case DP_S_MAX: /* precision */
             if (ossl_isdigit(ch)) {
                 if (max < 0)
                     max = 0;
-                max = 10 * max + char_to_int(ch);
+                /*
+                 * Most implementations cap the possible explicitly specified
+                 * width by (INT_MAX / 10) * 10 - 1 or so (the standard gives
+                 * no clear limit on this), we can do the same.
+                 */
+                if (max < INT_MAX / 10)
+                    max = 10 * max + char_to_int(ch);
+                else
+                    goto out;
                 ch = *format++;
             } else if (ch == '*') {
                 max = va_arg(args, int);