Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix parser bug for empty string allocation #496

Merged
merged 1 commit into from
May 16, 2022

Conversation

abrom
Copy link
Contributor

@abrom abrom commented Apr 20, 2022

When HAVE_RB_ENC_INTERNED_STR is enabled it is possible to pass through a null pointer to rb_enc_interned_str resulting in a segfault.

Fixes #495

Kudos to @jeremyevans for identifying the fix

When `HAVE_RB_ENC_INTERNED_STR` is enabled it is possible to
pass through a null pointer to `rb_enc_interned_str` resulting
in a segfault

Fixes ruby#495
@@ -2363,9 +2363,17 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
char buf[4];

if (bufferSize > MAX_STACK_BUFFER_SIZE) {
# ifdef HAVE_RB_ENC_INTERNED_STR
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note, i've wrapped the fix with this HAVE_RB_ENC_INTERNED_STR guard as the issue only pertains to the call to rb_enc_interned_str below. Saves allocating the extra byte unnecessarily. Although, if there was concern about the extra allocation this would likely look like:

bufferStart = buffer = ALLOC_N(char, !intern || bufferSize ? bufferSize : 1);

Or would you prefer for simplicities sake to just go with the suggestion in #475 from @jeremyevans (ie without the HAVE_RB_ENC_INTERNED_STR guards)?

Of course the safest solution would be to simply allocate room for the null terminator all of the time (bufferSize + 1) but that's likely unnecessary given how the pointers are being used.

@@ -84,6 +84,7 @@ def test_parse_simple_objects
assert_equal({ "a" => 23 }, parse(' { "a" : 23 } '))
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
assert_equal({ "" => 123 }, parse('{"":123}'))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this test is a duplicate given https://github.com/flori/json/blob/master/tests/fixtures/pass1.json#L15 however it seems reasonable to have an explicit test for this case here too.

@taf2
Copy link

taf2 commented Apr 28, 2022

confirming this fixes the issue...

@TomA-R
Copy link

TomA-R commented May 2, 2022

Hey @hsbt, any chance this could be reviewed and released if you're happy with it? Thanks in advance!

@marc-neumann
Copy link

+1 for releasing the fix.

@thewoolleyman
Copy link

Hello @flori , there's no response from @hsbt for 9 days now, and people are waiting on this fix. Can we get it merged and released?

@flori flori merged commit 823760c into ruby:master May 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Segmentation fault in ruby 3.0.4
6 participants