Skip to content

Commit b4e5529

Browse files
[libc] Fix printf long double inf, bitcast in msan (#70067)
These bugs were found with the new printf long double fuzzing. The long double inf vs nan bug was introduced when we changed to get_explicit_exponent. The bitcast msan issue hadn't come up previously, but isn't a real bug, just a poisoning confusion.
1 parent 567a660 commit b4e5529

File tree

5 files changed

+25
-4
lines changed

5 files changed

+25
-4
lines changed

libc/src/__support/CPP/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ add_header_library(
1515
HDRS
1616
bit.h
1717
DEPENDS
18-
libc.src.__support.macros.properties.compiler
18+
.type_traits
19+
libc.src.__support.macros.attributes
20+
libc.src.__support.macros.config
21+
libc.src.__support.macros.sanitizer
1922
)
2023

2124
add_header_library(

libc/src/__support/CPP/bit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "src/__support/CPP/type_traits.h"
1313
#include "src/__support/macros/attributes.h"
1414
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
15+
#include "src/__support/macros/sanitizer.h"
1516

1617
namespace LIBC_NAMESPACE::cpp {
1718

@@ -31,6 +32,7 @@ LIBC_INLINE constexpr To bit_cast(const From &from) {
3132
static_assert(cpp::is_trivially_copyable<To>::value &&
3233
cpp::is_trivially_copyable<From>::value,
3334
"Cannot bit-cast instances of non-trivially copyable classes.");
35+
MSAN_UNPOISON(&from, sizeof(From));
3436
#if defined(LLVM_LIBC_HAS_BUILTIN_BIT_CAST)
3537
return __builtin_bit_cast(To, from);
3638
#else

libc/src/stdio/printf_core/float_inf_nan_converter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ LIBC_INLINE int convert_inf_nan(Writer *writer, const FormatSection &to_conv) {
3434
fputil::FPBits<long double>::UIntType float_raw = to_conv.conv_val_raw;
3535
fputil::FPBits<long double> float_bits(float_raw);
3636
is_negative = float_bits.get_sign();
37-
mantissa = float_bits.get_explicit_mantissa();
37+
mantissa = float_bits.get_mantissa();
3838
} else {
3939
fputil::FPBits<double>::UIntType float_raw =
4040
static_cast<fputil::FPBits<double>::UIntType>(to_conv.conv_val_raw);
4141
fputil::FPBits<double> float_bits(float_raw);
4242
is_negative = float_bits.get_sign();
43-
mantissa = float_bits.get_explicit_mantissa();
43+
mantissa = float_bits.get_mantissa();
4444
}
4545

4646
char sign_char = 0;

libc/test/src/stdio/sprintf_test.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,6 @@ TEST_F(LlvmLibcSPrintfTest, FloatHexExpConv) {
572572
ForceRoundingMode r(RoundingMode::Nearest);
573573
double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
574574
double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(1);
575-
576575
written = LIBC_NAMESPACE::sprintf(buff, "%a", 1.0);
577576
ASSERT_STREQ_LEN(written, buff, "0x1p+0");
578577

@@ -937,6 +936,10 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {
937936
ForceRoundingMode r(RoundingMode::Nearest);
938937
double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
939938
double nan = LIBC_NAMESPACE::fputil::FPBits<double>::build_nan(1);
939+
long double ld_inf =
940+
LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
941+
long double ld_nan =
942+
LIBC_NAMESPACE::fputil::FPBits<long double>::build_nan(1);
940943

941944
char big_buff[10000]; // Used for long doubles and other extremely wide
942945
// numbers.
@@ -996,6 +999,18 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) {
996999
written = LIBC_NAMESPACE::sprintf(buff, "%F", -nan);
9971000
ASSERT_STREQ_LEN(written, buff, "-NAN");
9981001

1002+
written = LIBC_NAMESPACE::sprintf(buff, "%Lf", ld_inf);
1003+
ASSERT_STREQ_LEN(written, buff, "inf");
1004+
1005+
written = LIBC_NAMESPACE::sprintf(buff, "%LF", -ld_inf);
1006+
ASSERT_STREQ_LEN(written, buff, "-INF");
1007+
1008+
written = LIBC_NAMESPACE::sprintf(buff, "%Lf", ld_nan);
1009+
ASSERT_STREQ_LEN(written, buff, "nan");
1010+
1011+
written = LIBC_NAMESPACE::sprintf(buff, "%LF", -ld_nan);
1012+
ASSERT_STREQ_LEN(written, buff, "-NAN");
1013+
9991014
// Length Modifier Tests.
10001015

10011016
// TODO(michaelrj): Add tests for LONG_DOUBLE_IS_DOUBLE and 128 bit long

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ libc_support_library(
170170
":__support_cpp_type_traits",
171171
":__support_macros_attributes",
172172
":__support_macros_config",
173+
":__support_macros_sanitizer",
173174
":libc_root",
174175
],
175176
)

0 commit comments

Comments
 (0)