Skip to content

Commit eedbad9

Browse files
committed
Add overflow handling to strfrom functions
1 parent 995bb08 commit eedbad9

File tree

5 files changed

+31
-5
lines changed

5 files changed

+31
-5
lines changed

libc/src/stdlib/strfromd.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ LLVM_LIBC_FUNCTION(int, strfromd,
3636
if (n > 0)
3737
wb.buff[wb.buff_cur] = '\0';
3838

39-
// TODO overflow
39+
if (writer.get_chars_written() > cpp::numeric_limits<int>::max()) {
40+
libc_errno = EOVERFLOW;
41+
return -1;
42+
}
4043
return static_cast<int>(writer.get_chars_written());
4144
}
4245

libc/src/stdlib/strfromf.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ LLVM_LIBC_FUNCTION(int, strfromf,
3636
if (n > 0)
3737
wb.buff[wb.buff_cur] = '\0';
3838

39-
// TODO overflow
39+
if (writer.get_chars_written() > cpp::numeric_limits<int>::max()) {
40+
libc_errno = EOVERFLOW;
41+
return -1;
42+
}
4043
return static_cast<int>(writer.get_chars_written());
4144
}
4245

libc/src/stdlib/strfroml.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ LLVM_LIBC_FUNCTION(int, strfroml,
4141
if (n > 0)
4242
wb.buff[wb.buff_cur] = '\0';
4343

44-
// TODO overflow
44+
if (writer.get_chars_written() > cpp::numeric_limits<int>::max()) {
45+
libc_errno = EOVERFLOW;
46+
return -1;
47+
}
4548
return static_cast<int>(writer.get_chars_written());
4649
}
4750

libc/src/time/strftime_core/strftime_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int strftime_main(printf_core::Writer<write_mode> *writer,
3636
return result;
3737
}
3838

39+
// TODO could work similar to printf, retval is size_t in libc outer func
3940
return static_cast<int>(writer->get_chars_written());
4041
}
4142

libc/test/src/stdlib/StrfromTest.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "src/__support/CPP/limits.h"
910
#include "src/__support/CPP/type_traits.h"
1011
#include "src/__support/FPUtil/FPBits.h"
1112
#include "test/UnitTest/Test.h"
13+
#include "test/UnitTest/ErrnoCheckingTest.h"
14+
#include "test/UnitTest/ErrnoSetterMatcher.h"
1215

1316
#define ASSERT_STREQ_LEN(actual_written, actual_str, expected_str) \
1417
EXPECT_EQ(actual_written, static_cast<int>(sizeof(expected_str) - 1)); \
1518
EXPECT_STREQ(actual_str, expected_str);
1619

1720
template <typename InputT>
18-
class StrfromTest : public LIBC_NAMESPACE::testing::Test {
21+
class StrfromTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
1922

2023
static constexpr bool is_single_prec =
2124
LIBC_NAMESPACE::cpp::is_same<InputT, float>::value;
@@ -481,6 +484,16 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
481484
written = func(buff, 10, "%A", -ld_nan);
482485
ASSERT_STREQ_LEN(written, buff, "-NAN");
483486
}
487+
488+
void charsWrittenOverflow(FunctionT func) {
489+
char buff[100];
490+
// Trigger an overflow in the return value of strfrom by writing more than
491+
// INT_MAX bytes.
492+
int result = func(buff, sizeof(buff), "%.2147483647f", 1.0f);
493+
494+
EXPECT_LT(result, 0);
495+
ASSERT_ERRNO_EQ(EOVERFLOW);
496+
}
484497
};
485498

486499
#define STRFROM_TEST(InputType, name, func) \
@@ -501,4 +514,7 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
501514
TEST_F(LlvmLibc##name##Test, InsufficientBufferSize) { \
502515
insufficentBufsize(func); \
503516
} \
504-
TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); }
517+
TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); } \
518+
TEST_F(LlvmLibc##name##Test, CharsWrittenOverflow) { \
519+
charsWrittenOverflow(func); \
520+
}

0 commit comments

Comments
 (0)