Skip to content

Commit 25bd96e

Browse files
committed
Fix buffer underrun in fixed with SSE
1 parent f087a34 commit 25bd96e

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

test/zmij-test.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ auto write(char* out, size_t n, float value) noexcept -> size_t {
3636

3737

3838
auto dtoa(double value) -> std::string {
39-
char buffer[zmij::double_buffer_size] = {};
40-
auto n = zmij::write(buffer, sizeof(buffer), value);
41-
return {buffer, n};
39+
char buffer[zmij::double_buffer_size + 1] = {};
40+
memset(buffer, '?', sizeof(buffer));
41+
auto n = zmij::write(buffer + 1, sizeof(buffer), value);
42+
if (buffer[0] != '?') throw std::runtime_error("buffer underrun");
43+
return {buffer + 1, n};
4244
}
4345

4446
auto ftoa(float value) -> std::string {
@@ -235,6 +237,10 @@ TEST(dtoa_test, no_overrun) {
235237
EXPECT_EQ(buffer[zmij::double_buffer_size - 1], '\0');
236238
}
237239

240+
TEST(dtoa_test, no_underrun) {
241+
dtoa(9.061488e+15);
242+
}
243+
238244
TEST(ftoa_test, normal) {
239245
EXPECT_EQ(ftoa(6.62607e-34f), "6.62607e-34");
240246
EXPECT_EQ(ftoa(1.342178e+08f), "1.342178e+08");

zmij.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ typedef struct {
3434
#ifdef ZMIJ_USE_SSE
3535
// Use the provided definition
3636
#elif defined(__SSE2__)
37-
# define ZMIJ_USE_SSE ZMIJ_USE_SIMD
37+
# define ZMIJ_USE_SSE 0
3838
#elif defined(_M_AMD64) || (defined(_M_IX86_FP) && _M_IX86FP == 2)
39-
# define ZMIJ_USE_SSE ZMIJ_USE_SIMD
39+
# define ZMIJ_USE_SSE 0
4040
#else
4141
# define ZMIJ_USE_SSE 0
4242
#endif

zmij.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,10 @@ auto write_significand9(char* buffer, uint32_t value, bool has9digits) noexcept
515515
// normals) and removes trailing zeros. The significant digits start
516516
// from buffer[1]. buffer[0] may contain '0' after this function if
517517
// the significand has length 16.
518+
template <bool use_sse = ZMIJ_USE_SSE != 0>
518519
auto write_significand17(char* buffer, uint64_t value, bool has17digits,
519520
long long value_div10) noexcept -> char* {
520-
if (!ZMIJ_USE_NEON && !ZMIJ_USE_SSE) {
521+
if (!ZMIJ_USE_NEON && !use_sse) {
521522
// Digits/pairs of digits are denoted by letters: value = abbccddeeffgghhii.
522523
uint32_t abbccddee = uint32_t(value / 100'000'000);
523524
uint32_t ffgghhii = uint32_t(value % 100'000'000);
@@ -894,7 +895,7 @@ auto write_fixed(char* buffer, uint64_t dec_sig, int dec_exp, bool extra_digit,
894895
write8(buffer + (num_bits == 64 ? 16 : 7), 0);
895896

896897
char* start = buffer;
897-
buffer = num_bits == 64 ? write_significand17(buffer, dec_sig, extra_digit,
898+
buffer = num_bits == 64 ? write_significand17<false>(buffer, dec_sig, extra_digit,
898899
dec_sig_div10)
899900
: write_significand9(buffer, dec_sig, extra_digit);
900901

0 commit comments

Comments
 (0)