Skip to content

Fix GH-15168: stack overflow in json_encode() - #16059

Closed
ndossche wants to merge 1 commit into
php:PHP-8.3from
ndossche:fix-15168
Closed

ndossche wants to merge 1 commit into
php:PHP-8.3from
ndossche:fix-15168

Conversation

@ndossche

Copy link
Copy Markdown
Member

The JSON encoder is recursive, and it's far from easy to make it iterative. Add a cheap stack limit check to prevent a segfault. This uses the PHP_JSON_ERROR_DEPTH error code that already talks about the stack depth. Previously this was only used for the $depth argument.

The JSON encoder is recursive, and it's far from easy to make it
iterative. Add a cheap stack limit check to prevent a segfault.
This uses the PHP_JSON_ERROR_DEPTH error code that already talks about
the stack depth. Previously this was only used for the $depth argument.
@ndossche
ndossche requested a review from bukka as a code owner September 25, 2024 15:59
Comment thread ext/json/json_encoder.c
HashTable *myht, *prop_ht;

if (php_json_check_stack_limit()) {
encoder->error_code = PHP_JSON_ERROR_DEPTH;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If it's not desirable to reuse the PHP_JSON_ERROR_DEPTH error code, then I can add a new one; but then this PR won't be able to target 8.3.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given the message associated with this error code, I think it's fine

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok I will give some time for Jakub to check this PR too so we know if he agrees because he is codeowner of json.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's for a bit different thing but guess we can repurpose it.

@ndossche ndossche linked an issue Sep 25, 2024 that may be closed by this pull request
@iluuu1994
iluuu1994 requested a review from arnaud-lb September 25, 2024 16:01

@arnaud-lb arnaud-lb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice!

Comment thread ext/json/json_encoder.c
HashTable *myht, *prop_ht;

if (php_json_check_stack_limit()) {
encoder->error_code = PHP_JSON_ERROR_DEPTH;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given the message associated with this error code, I think it's fine

@bukka bukka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, just one NIT but feel free to ignore it.

Comment thread ext/json/json_encoder.c
Comment on lines +34 to +42
static zend_always_inline bool php_json_check_stack_limit(void)
{
#ifdef ZEND_CHECK_STACK_LIMIT
return zend_call_stack_overflowed(EG(stack_limit));
#else
return false;
#endif
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wouldn't make sense to make this not json specific as it might be useful for serialization as well possibly?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Maybe this should be moved to the Zend/zend_call_stack.h header file, I think it would make sense there. What do you think @arnaud-lb ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agree, it would make sense to move this function to Zend/zend_call_stack.h

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's a bit annoying to do so as it would require us to pull in zend_globals.h to get access to EG fields, which pulls in a whole bunch more..

Comment thread ext/json/json_encoder.c
HashTable *myht, *prop_ht;

if (php_json_check_stack_limit()) {
encoder->error_code = PHP_JSON_ERROR_DEPTH;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's for a bit different thing but guess we can repurpose it.

@ndossche ndossche closed this in a551b99 Sep 30, 2024
jorgsowa pushed a commit to jorgsowa/php-src that referenced this pull request Oct 1, 2024
The JSON encoder is recursive, and it's far from easy to make it
iterative. Add a cheap stack limit check to prevent a segfault.
This uses the PHP_JSON_ERROR_DEPTH error code that already talks about
the stack depth. Previously this was only used for the $depth argument.

Closes phpGH-16059.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

stack overflow in json_encode()

3 participants