Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions src/fptostring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,14 @@ std::string FpToString(T v, int precision = 0) {
}
}

std::array<char, 28> output_buffer; // max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
// Case 1 - scientific notation: max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
// Case 2 - default notation: require up to precision number of digits and one for a potential sign
std::array<char, 28> output_buffer;
auto output_ptr = &output_buffer[0];

// Helper variable that in Case 2 counts the overflowing number of zeros that do not fit into the buffer.
int overflow_zeros = 0;

// print '-' symbol for negative numbers
if (r.is_negative) {
*(output_ptr++) = '-';
Expand Down Expand Up @@ -172,18 +177,28 @@ std::string FpToString(T v, int precision = 0) {

// case 2: default notation
} else {
auto const digits_end = digits.begin() + digits_ct;
auto digits_iter = digits.begin();
auto const digits_end = digits.begin() + digits_ct;
auto digits_iter = digits.begin();

// print digits before point
int const before_decimal_digits = digits_ct + r.exponent;
if (before_decimal_digits > 0) {
// print digits before point
// print non-zero digits before point
for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
*(output_ptr++) = *(digits_iter++);
}

// number of digits that have to be zero
int const zero_digits_ct = before_decimal_digits - digits_ct;

// space left in the output_buffer (-1 because we need it for null-termination)
int const buffer_empty_space = output_buffer.data() + output_buffer.size() - output_ptr - 1;

// print all zeros not fitting into the buffer at the end of the function
overflow_zeros = std::max(0, zero_digits_ct - buffer_empty_space);

// print trailing zeros before point
for (int i{0}; i < before_decimal_digits - digits_ct; ++i) {
for (int i{0}; i < zero_digits_ct - overflow_zeros; ++i) {
*(output_ptr++) = '0';
}

Expand All @@ -207,7 +222,9 @@ std::string FpToString(T v, int precision = 0) {
}
}
*output_ptr = '\0';
return std::string{&output_buffer[0], output_ptr};
auto ret_value = std::string{&output_buffer[0], output_ptr};
ret_value.resize(ret_value.size() + overflow_zeros, '0');
return ret_value;
}

}
Expand Down
4 changes: 4 additions & 0 deletions test/fptostring_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,5 +238,9 @@ TEST(FpToStringTest, conversion_float) {
EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5f, 2));
}

TEST(FpToStringTest, vulnerability_stack_buffer_overflow) {
EXPECT_EQ(FpToString(1.0e100, 200), "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
}

} // namespace
} // namespace YAML