-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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 GH-17650: realloc with size 0 in user_filters.c #17656
Conversation
If the returned buffer string is of length 0, then a realloc can happen with length 0. However, the behaviour is implementation-defined. From 7.20.3.1 of C11 spec: > If the size of the space requested is zero, the behavior is > implementation-defined: either a null pointer is returned, > or the behavior is as if the size were some nonzero value, > except that the returned pointer shall not be used to access an object This is problematic for the test case on my system as it returns NULL, causing a memleak and later using it in memcpy causing UB. The bucket code is not prepared to handle a NULL pointer. To solve this, we use MAX to clamp the size to 1 at the least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LCTM
Quick thought: what if we treat empty |
Can you be a bit more specific please? |
I haven't really checked that, but the idea is ext/standard/user_filters.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c
index 737237f663..8997e9c038 100644
--- a/ext/standard/user_filters.c
+++ b/ext/standard/user_filters.c
@@ -393,7 +393,7 @@ static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS)
RETURN_THROWS();
}
- if (NULL != (pzdata = zend_hash_str_find_deref(Z_OBJPROP_P(zobject), "data", sizeof("data")-1)) && Z_TYPE_P(pzdata) == IS_STRING) {
+ if (NULL != (pzdata = zend_hash_str_find_deref(Z_OBJPROP_P(zobject), "data", sizeof("data")-1)) && Z_TYPE_P(pzdata) == IS_STRING && Z_STRLEN_P(data) > 0) {
if (!bucket->own_buf) {
bucket = php_stream_bucket_make_writeable(bucket);
} |
@cmb69 That's wrong, but the reason why it's wrong is not revealed by the test. I've updated the test so that would now be revealed. The difference with my approach and yours is that my approach won't output anything while yours will output the input data. Given that the data field of the bucket is overwritten by the code to an empty string, I think the output created by my approach is better. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation (makes perfect sense), and amending the test.
If the returned buffer string is of length 0, then a realloc can happen with length 0. However, the behaviour is implementation-defined. From 7.20.3.1 of C11 spec:
This is problematic for the test case on my system as it returns NULL, causing a memleak and later using it in memcpy causing UB. The bucket code is not prepared to handle a NULL pointer. To solve this, we use MAX to clamp the size to 1 at the least.