diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 29ee595c17..272af5924c 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -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;