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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changes

* Fix a potential crash in large negative floating point number generation.

### Unreleased

* Fix for JSON.pretty_generate to use passed state object's generate instead of state class as the required parameters aren't available.
Expand Down
5 changes: 2 additions & 3 deletions ext/json/ext/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions ext/json/ext/vendor/fpconv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -443,15 +443,15 @@ 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';
* printf("%s", buf);
* }
*
*/
static int fpconv_dtoa(double d, char dest[24])
static int fpconv_dtoa(double d, char dest[28])
{
char digits[18];

Expand Down
5 changes: 5 additions & 0 deletions test/json/json_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,11 @@ def test_json_generate_float
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
Expand Down