]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
formatString_u() can display numbers > 100
authorYann Collet <cyan@fb.com>
Tue, 6 Aug 2024 18:44:37 +0000 (11:44 -0700)
committerYann Collet <cyan@fb.com>
Tue, 6 Aug 2024 18:44:37 +0000 (11:44 -0700)
fixes #4110

programs/benchzstd.c

index 29ee595c174142bf519e6ef72d0ca50775c761df..075640e82c76e91b3e8ae1d0aa2fef022c07c383 100644 (file)
@@ -139,52 +139,61 @@ static const size_t maxMemory = (sizeof(size_t) == 4)
         return r;                                      \
     }
 
-/* replacement for snprintf(), which is not supported by C89
- * sprintf() would be the supported one, but it's labelled unsafe,
- * so some modern static analyzer will flag it as such, making it unusable.
- * formatString_u() replaces snprintf() for the specific case where there are only %u arguments */
+static size_t uintSize(unsigned value)
+{
+    size_t size = 1;
+    while (value >= 10) {
+        size++;
+        value /= 10;
+    }
+    return size;
+}
+
+// Note: presume @buffer is large enough
+static void writeUint_varLen(char* buffer, size_t capacity, unsigned value)
+{
+    int endPos = (int)uintSize(value) - 1;
+    assert(uintSize(value) >= 1);
+    assert(uintSize(value) < capacity); (void)capacity;
+    while (endPos >= 0) {
+        char c = '0' + (char)(value % 10);
+        buffer[endPos--] = c;
+        value /= 10;
+    }
+}
+
+/* replacement for snprintf(), which is not supported by C89.
+ * sprintf() would be the supported one, but it's labelled unsafe:
+ * modern static analyzer will flag sprintf() as dangerous, making it unusable.
+ * formatString_u() replaces snprintf() for the specific case where there is only one %u argument */
 static int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value)
 {
+    size_t const valueSize = uintSize(value);
     size_t written = 0;
     int i;
-    assert(value <= 100);
 
-    for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; ++i) {
+    for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; i++) {
         if (formatString[i] != '%') {
             buffer[written++] = formatString[i];
             continue;
         }
 
-        if (formatString[++i] == 'u') {
-            /* Handle single digit */
-            if (value < 10) {
-                buffer[written++] = '0' + (char)value;
-            } else if (value < 100) {
-                /* Handle two digits */
-                if (written >= buffer_size - 2) {
-                    return -1; /* buffer overflow */
-                }
-                buffer[written++] = '0' + (char)(value / 10);
-                buffer[written++] = '0' + (char)(value % 10);
-            } else { /* 100 */
-                if (written >= buffer_size - 3) {
-                    return -1; /* buffer overflow */
-                }
-                buffer[written++] = '1';
-                buffer[written++] = '0';
-                buffer[written++] = '0';
-            }
+        i++;
+        if (formatString[i] == 'u') {
+            if (written + valueSize >= buffer_size) abort(); /* buffer not large enough */
+            writeUint_varLen(buffer + written, buffer_size - written, value);
+            written += valueSize;
         } else if (formatString[i] == '%') { /* Check for escaped percent sign */
             buffer[written++] = '%';
         } else {
-            return -1; /* unsupported format */
+            abort(); /* unsupported format */
         }
     }
 
     if (written < buffer_size) {
         buffer[written] = '\0';
     } else {
-        buffer[0] = '\0'; /* Handle truncation */
+        abort(); /* buffer not large enough */
     }
 
     return (int)written;