diff options
author | Jean Boussier <[email protected]> | 2025-05-23 09:28:56 +0200 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2025-05-26 11:46:12 +0900 |
commit | f171a263f76d6505b891f848bc5393ebbb973be3 (patch) | |
tree | 449db66c4f2c00e83aa3c43b8f7d3e7076689065 | |
parent | aa00a2d07bf56fc5def659e06104eb3173803ca7 (diff) |
[ruby/json] Fix: generate_json_float to reserve enough memory for large negative floats.
Fix: https://github.com/ruby/json/issues/807
Since https://github.com/ruby/json/pull/800, `fpconv_dtoa` can actually
generate up to 28 chars.
https://github.com/ruby/json/commit/d73ae93d3c
-rw-r--r-- | ext/json/generator/generator.c | 5 | ||||
-rw-r--r-- | ext/json/vendor/fpconv.c | 8 | ||||
-rwxr-xr-x | test/json/json_generator_test.rb | 5 |
3 files changed, 11 insertions, 7 deletions
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 06ab8010d9..e67351f8b4 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1406,10 +1406,9 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data } /* This implementation writes directly into the buffer. We reserve - * the 24 characters that fpconv_dtoa states as its maximum, plus - * 2 more characters for the potential ".0" suffix. + * the 28 characters that fpconv_dtoa states as its maximum. */ - fbuffer_inc_capa(buffer, 26); + fbuffer_inc_capa(buffer, 28); char* d = buffer->ptr + buffer->len; int len = fpconv_dtoa(value, d); diff --git a/ext/json/vendor/fpconv.c b/ext/json/vendor/fpconv.c index 1bbca28739..75efd46f11 100644 --- a/ext/json/vendor/fpconv.c +++ b/ext/json/vendor/fpconv.c @@ -432,8 +432,8 @@ static int filter_special(double fp, char* dest) * * Input: * fp -> the double to convert, dest -> destination buffer. - * The generated string will never be longer than 24 characters. - * Make sure to pass a pointer to at least 24 bytes of memory. + * The generated string will never be longer than 28 characters. + * Make sure to pass a pointer to at least 28 bytes of memory. * The emitted string will not be null terminated. * * Output: @@ -443,7 +443,7 @@ static int filter_special(double fp, char* dest) * * void print(double d) * { - * char buf[24 + 1] // plus null terminator + * char buf[28 + 1] // plus null terminator * int str_len = fpconv_dtoa(d, buf); * * buf[str_len] = '\0'; @@ -451,7 +451,7 @@ static int filter_special(double fp, char* dest) * } * */ -static int fpconv_dtoa(double d, char dest[24]) +static int fpconv_dtoa(double d, char dest[28]) { char digits[18]; diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index f869e43fbe..914b3f4ed0 100755 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -795,6 +795,11 @@ class JSONGeneratorTest < Test::Unit::TestCase expecteds << "1746861937.7842371" end + if RUBY_ENGINE == "ruby" + values << -2.2471348024634545e-08 << -2.2471348024634545e-09 << -2.2471348024634545e-10 + expecteds << "-0.000000022471348024634545" << "-0.0000000022471348024634545" << "-2.2471348024634546e-10" + end + values.zip(expecteds).each do |value, expected| assert_equal expected, value.to_json end |