diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h --- a/libc/src/stdio/printf_core/float_hex_converter.h +++ b/libc/src/stdio/printf_core/float_hex_converter.h @@ -204,7 +204,7 @@ constexpr int EXP_SEPERATOR_LEN = 1; padding = static_cast(to_conv.min_width - (sign_char > 0 ? 1 : 0) - - PREFIX_LEN - mant_digits - + PREFIX_LEN - mant_digits - trailing_zeroes - static_cast(has_hexadecimal_point) - EXP_SEPERATOR_LEN - (EXP_LEN - exp_cur)); if (padding < 0) diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp --- a/libc/test/src/stdio/sprintf_test.cpp +++ b/libc/test/src/stdio/sprintf_test.cpp @@ -865,6 +865,19 @@ written = __llvm_libc::sprintf(buff, "%+-#12.3a % 012.3a", 0.1256, 1256.0); ASSERT_STREQ_LEN(written, buff, "+0x1.014p-3 0x1.3a0p+10"); + + // Found via fuzzing + + // The trailing zeroes were previously not counted when calculating the + // padding, which caused a high-precision number to get too much padding. + written = __llvm_libc::sprintf(buff, "%50.50a", 0x1.0p0); + ASSERT_STREQ_LEN(written, buff, + "0x1.00000000000000000000000000000000000000000000000000p+0"); + + written = __llvm_libc::sprintf(buff, "%58.50a", 0x1.0p0); + ASSERT_STREQ_LEN( + written, buff, + " 0x1.00000000000000000000000000000000000000000000000000p+0"); } TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {