Skip to content

Fix GH-16592 msg_send() crashes when the type does not serialize as e… #16599

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

Closed
wants to merge 1 commit into from

Conversation

devnexen
Copy link
Member

…xpected.

It is assumed that the serialization always had initialised its buffer zend_string, but in the case of a type not serialising, it is null.

@devnexen devnexen marked this pull request as ready for review October 25, 2024 17:48
@devnexen devnexen linked an issue Oct 25, 2024 that may be closed by this pull request
@devnexen devnexen requested a review from cmb69 October 25, 2024 17:49
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

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

I think this is good as is, but see my comments below for an alternative solution, which appears to be cleaner, and which wouldn't have crashed in the first place.

Comment on lines 375 to 377
if (!message_len) {
RETURN_FALSE;
}
Copy link
Member

Choose a reason for hiding this comment

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

I cannot easily test this (non Windows extension), but I figure that even mesage_len == 0 wouldn't be a problem, if we didn't access msg_var.s directly, but rather via smart_str APIs only. See comment below.

Comment on lines 382 to 387
memcpy(messagebuffer->mtext, ZSTR_VAL(msg_var.s), message_len + 1);
smart_str_free(&msg_var);
Copy link
Member

@cmb69 cmb69 Oct 30, 2024

Choose a reason for hiding this comment

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

I think this shouldcould probably be something like (untested!):

Suggested change
memcpy(messagebuffer->mtext, ZSTR_VAL(msg_var.s), message_len + 1);
smart_str_free(&msg_var);
zend_string *str = smart_str_extract(msg_var);
memcpy(messagebuffer->mtext, ZSTR_VAL(str), message_len + 1);
zend_string_release(str);

Copy link
Member Author

Choose a reason for hiding this comment

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

Did not test it yet ; will do in the next hour, but that should work too, I just wanted to have an early exit/not bothering creating an empty message.

Copy link
Member

Choose a reason for hiding this comment

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

I just wanted to have an early exit/not bothering creating an empty message.

Makes sense, but still could use proper smart_str APIs instead of accessing the underlying zend_string directly.

@nielsdos
Copy link
Member

While this fix is good, it's not a full fix. Additionally, if serializing resulted in an exception we shouldn't even try to send a message in the first place.

@devnexen
Copy link
Member Author

While this fix is good, it's not a full fix. Additionally, if serializing resulted in an exception we shouldn't even try to send a message in the first place.

sure, will give a try.

Comment on lines 379 to 385
message_len = smart_str_get_len(&msg_var);

/* NB: php_msgbuf is 1 char bigger than a long, so there is no need to
* allocate the extra byte. */
messagebuffer = safe_emalloc(ZSTR_LEN(msg_var.s), 1, sizeof(struct php_msgbuf));
memcpy(messagebuffer->mtext, ZSTR_VAL(msg_var.s), ZSTR_LEN(msg_var.s) + 1);
message_len = ZSTR_LEN(msg_var.s);
messagebuffer = safe_emalloc(message_len, 1, sizeof(struct php_msgbuf));
zend_string *str = smart_str_extract(&msg_var);
memcpy(messagebuffer->mtext, ZSTR_VAL(str), message_len + 1);
Copy link
Member

Choose a reason for hiding this comment

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

If we use smart_str_extract(), I'd probably avoid getting the message_len from the smart_str, i.e.

zend_string *str = smart_str_extract(&msg_var);
messagebuffer = safe_emalloc(ZSTR_LEN(str), 1, sizeof(struct php_msgbuf));
memcpy(messagebuffer->mtext, ZSTR_VAL(str), ZSTR_LEN(str) + 1);

But it's okay for me as is.

Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

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

2 minor nits, but looks right otherwise

…s expected.

It is assumed that the serialization always had initialised its buffer
zend_string, but in the case of a type not serialising, it is null.
Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

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

Thanks

@devnexen devnexen closed this in 90aac52 Nov 3, 2024
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.

Null-deref in msg_send
3 participants