diff --git a/double-conversion/fast-dtoa.cc b/double-conversion/fast-dtoa.cc index d7a23984..86fffd15 100644 --- a/double-conversion/fast-dtoa.cc +++ b/double-conversion/fast-dtoa.cc @@ -452,6 +452,15 @@ static bool DigitGenCounted(DiyFp w, *kappa = divisor_exponent_plus_one; *length = 0; + // With requested_digits <= 0 no digit can be produced. The integral loop + // below decrements requested_digits and only stops on an exact 0, so a + // non-positive value never trips that break and the loop emits every digit + // of 'integrals' past the end of the buffer. DoubleToAscii guards PRECISION + // with 0 digits before reaching here, but a direct FastDtoa caller does not. + if (requested_digits <= 0) { + return false; + } + // Loop invariant: buffer = w / 10^kappa (integer division) // The invariant holds for the first iteration: kappa has been initialized // with the divisor exponent + 1. And the divisor is the biggest power of ten diff --git a/test/cctest/test-fast-dtoa.cc b/test/cctest/test-fast-dtoa.cc index 5fb8975b..b059d412 100644 --- a/test/cctest/test-fast-dtoa.cc +++ b/test/cctest/test-fast-dtoa.cc @@ -296,6 +296,20 @@ TEST(FastDtoaPrecisionVariousDoubles) { CHECK(status); CHECK_EQ("7989", buffer.start()); CHECK_EQ(192, point); + + // requested_digits <= 0 must not write any digit. Fence the one-byte buffer + // with a sentinel and confirm FastDtoa fails without touching past it. + char tiny_container[2]; + tiny_container[1] = 0x7f; + Vector tiny(tiny_container, 1); + status = FastDtoa(1234567.0, FAST_DTOA_PRECISION, 0, tiny, &length, &point); + CHECK(!status); + CHECK_EQ(0, length); + CHECK_EQ(0x7f, static_cast(tiny_container[1])); + status = FastDtoa(1234567.0, FAST_DTOA_PRECISION, -3, tiny, &length, &point); + CHECK(!status); + CHECK_EQ(0, length); + CHECK_EQ(0x7f, static_cast(tiny_container[1])); }