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 GH-16812: UAF on readline_info() after readline_write_history() c… #16813

Closed
wants to merge 5 commits into from

Conversation

devnexen
Copy link
Member

…all.

@devnexen devnexen marked this pull request as ready for review November 15, 2024 10:17
@devnexen devnexen requested a review from petk November 15, 2024 10:17
@devnexen devnexen linked an issue Nov 15, 2024 that may be closed by this pull request
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.

This doesn't seem to be related to calling readline_write_history() upfront, but rather the issue can be replicated with two consecutive calls to readline_info('line_buffer', …'), e.g.

var_dump(readline_info('line_buffer', 'one'));
var_dump(readline_info('line_buffer', 'two'));

This causes a UAF for me, without the patch. With the patch, the UAF is resolved, but the function doesn't behave as expected. Output should be:

string(0) ""
string(3) "one"

var_dump(readline_info('line_buffer', 'test'));
?>
--EXPECT--
string(4) "test"
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't look right; I think readline_info() is supposed to return the old line_buffer which should be an empty string.

ext/readline/readline.c Outdated Show resolved Hide resolved
ext/readline/readline.c Outdated Show resolved Hide resolved
ext/readline/tests/gh16812.phpt Outdated Show resolved Hide resolved
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.

Thank you!

@@ -181,7 +181,7 @@ PHP_FUNCTION(readline_info)
add_assoc_long(return_value,"attempted_completion_over",rl_attempted_completion_over);
} else {
if (zend_string_equals_literal_ci(what,"line_buffer")) {
oldstr = rl_line_buffer;
oldstr = strdup(rl_line_buffer ? rl_line_buffer : "");
Copy link
Member

Choose a reason for hiding this comment

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

The strdup("") doesn't seem to be necessary (that's already handled by SAFE_STRING(). It's not wrong though, and performance is likely irrelevant here.

Comment on lines +194 to +195
free(oldstr);
oldstr = strdup(rl_line_buffer ? rl_line_buffer : "");
Copy link
Member

Choose a reason for hiding this comment

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

Since we touch this code path (libreadline only), we should also run the test against libreadline.

@@ -208,6 +209,7 @@ PHP_FUNCTION(readline_info)
#endif
}
RETVAL_STRING(SAFE_STRING(oldstr));
free(oldstr);
Copy link
Member

Choose a reason for hiding this comment

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

Ah, right, good idea!

@devnexen devnexen closed this in b8ba6f6 Nov 15, 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.

UAF in readline
2 participants