Skip to content

Conversation

@JanTvrdik
Copy link
Contributor

PHP function json_decode has a nasty bug which lead to fatal error if key starts with a NULL byte. Simple workaround for this is to pass true as the second parameter. Any tips how to solve this issue in Nette\Utils\Json?

This pull contains only failing test for now.

@JanTvrdik JanTvrdik changed the title Json: workaroud for fatal error [WIP] Json: workaroud for PHP fatal error Mar 31, 2014
@stekycz
Copy link
Contributor

stekycz commented Mar 31, 2014

What about escape these characters before json_decode, process and then unescape in the result? If none character is found before escaping then there does not have to be escaping and unescaping to keep current performance. Do you think it is often to happen?

@JanTvrdik
Copy link
Contributor Author

This passes the test, but it fails on strings such as "\\u0000" 😸

@JanTvrdik
Copy link
Contributor Author

I've improved the fix. But will this really work in all cases?

@JanTvrdik
Copy link
Contributor Author

ping @dg

@JanTvrdik JanTvrdik changed the title [WIP] Json: workaroud for PHP fatal error Json: workaroud for PHP fatal error Apr 8, 2014
@dg
Copy link
Member

dg commented Apr 8, 2014

This replaces all correct NULLs after " with invalid charater, so it leads to „Control character error, possibly incorrectly encoded“. Strange ;-)

@JanTvrdik
Copy link
Contributor Author

Damn. In that case I have no idea how to efficiently prevent the fatal error.

@dg
Copy link
Member

dg commented Apr 8, 2014

This means "invalid" key [^\]"\u0000([^\"]|\\.)*": and this json should be rejected immediately.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or should I use Strings::match?

Copy link
Member

Choose a reason for hiding this comment

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

Are two nesting levels needed?

Copy link
Member

Choose a reason for hiding this comment

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

Strings::match is not needed, RE is corrent and when you use #[^\\\\]"\\\\u0000(?:[^"\\\\]|\\\\.)*+"\s*+: (two + added), there will be no chance for backtracking error.

@fprochazka
Copy link
Contributor

👍 I don't like people sending me invalid jsons to my API to make my server throw a fatal error.

This should be merged ASAP (I seems finished to me) and backported to 2.1

Copy link
Member

Choose a reason for hiding this comment

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

This is faster '#(?<!\\\\)"\\\\u0000(?:[^"\\\\]|\\\\.)*+"\s*+:#'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, you can take the same trick one step further – assuming that " is a lot more common in JSON than \ we get '#(?<=[^\\\\]")\\\\u0000(?:[^"\\\\]|\\\\.)*+"\s*+:#'. Performance on real-world JSON is 820 μs for my original, 157 μs for your improvement and 20 μs for my using \ as base matching character.

Copy link
Member

Choose a reason for hiding this comment

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

👍

dg added a commit that referenced this pull request Dec 21, 2014
Json: workaroud for PHP fatal error
@dg dg merged commit a80ec1c into nette:master Dec 21, 2014
@JanTvrdik JanTvrdik deleted the json_null_byte_fix branch December 21, 2014 18:14
@lookyman
Copy link

👍 nice job guys

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.

5 participants