Skip to content

Commit d695177

Browse files
authored
Merge pull request #808 from byroot/reported-segv
Fix: generate_json_float to reserve enough memory for large negative floats.
2 parents 60e80e1 + d73ae93 commit d695177

File tree

4 files changed

+13
-7
lines changed

4 files changed

+13
-7
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changes
22

3+
* Fix a potential crash in large negative floating point number generation.
4+
35
### Unreleased
46

57
* Fix for JSON.pretty_generate to use passed state object's generate instead of state class as the required parameters aren't available.

ext/json/ext/generator/generator.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,10 +1406,9 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
14061406
}
14071407

14081408
/* This implementation writes directly into the buffer. We reserve
1409-
* the 24 characters that fpconv_dtoa states as its maximum, plus
1410-
* 2 more characters for the potential ".0" suffix.
1409+
* the 28 characters that fpconv_dtoa states as its maximum.
14111410
*/
1412-
fbuffer_inc_capa(buffer, 26);
1411+
fbuffer_inc_capa(buffer, 28);
14131412
char* d = buffer->ptr + buffer->len;
14141413
int len = fpconv_dtoa(value, d);
14151414

ext/json/ext/vendor/fpconv.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,8 @@ static int filter_special(double fp, char* dest)
432432
*
433433
* Input:
434434
* fp -> the double to convert, dest -> destination buffer.
435-
* The generated string will never be longer than 24 characters.
436-
* Make sure to pass a pointer to at least 24 bytes of memory.
435+
* The generated string will never be longer than 28 characters.
436+
* Make sure to pass a pointer to at least 28 bytes of memory.
437437
* The emitted string will not be null terminated.
438438
*
439439
* Output:
@@ -443,15 +443,15 @@ static int filter_special(double fp, char* dest)
443443
*
444444
* void print(double d)
445445
* {
446-
* char buf[24 + 1] // plus null terminator
446+
* char buf[28 + 1] // plus null terminator
447447
* int str_len = fpconv_dtoa(d, buf);
448448
*
449449
* buf[str_len] = '\0';
450450
* printf("%s", buf);
451451
* }
452452
*
453453
*/
454-
static int fpconv_dtoa(double d, char dest[24])
454+
static int fpconv_dtoa(double d, char dest[28])
455455
{
456456
char digits[18];
457457

test/json/json_generator_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,11 @@ def test_json_generate_float
795795
expecteds << "1746861937.7842371"
796796
end
797797

798+
if RUBY_ENGINE == "ruby"
799+
values << -2.2471348024634545e-08 << -2.2471348024634545e-09 << -2.2471348024634545e-10
800+
expecteds << "-0.000000022471348024634545" << "-0.0000000022471348024634545" << "-2.2471348024634546e-10"
801+
end
802+
798803
values.zip(expecteds).each do |value, expected|
799804
assert_equal expected, value.to_json
800805
end

0 commit comments

Comments
 (0)