Skip to content

Commit b8ba6f6

Browse files
committed
Fix GH-16812: UAF on readline_info() after readline_write_history() call.
close GH-16813
1 parent 0ed855a commit b8ba6f6

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ PHP NEWS
2424
- PDO:
2525
. Fixed memory leak of `setFetchMode()`. (SakiTakamachi)
2626

27+
- Readline:
28+
. Fixed UAF with readline_info(). (David Carlier)
29+
2730
- Reflection:
2831
. Fixed the name of the second parameter of
2932
ReflectionClass::resetAsLazyGhost(). (Arnaud)

ext/readline/readline.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ PHP_FUNCTION(readline_info)
181181
add_assoc_long(return_value,"attempted_completion_over",rl_attempted_completion_over);
182182
} else {
183183
if (zend_string_equals_literal_ci(what,"line_buffer")) {
184-
oldstr = rl_line_buffer;
184+
oldstr = strdup(rl_line_buffer ? rl_line_buffer : "");
185185
if (value) {
186186
if (!try_convert_to_string(value)) {
187187
RETURN_THROWS();
@@ -191,7 +191,8 @@ PHP_FUNCTION(readline_info)
191191
rl_line_buffer = malloc(Z_STRLEN_P(value) + 1);
192192
} else if (strlen(oldstr) < Z_STRLEN_P(value)) {
193193
rl_extend_line_buffer(Z_STRLEN_P(value) + 1);
194-
oldstr = rl_line_buffer;
194+
free(oldstr);
195+
oldstr = strdup(rl_line_buffer ? rl_line_buffer : "");
195196
}
196197
memcpy(rl_line_buffer, Z_STRVAL_P(value), Z_STRLEN_P(value) + 1);
197198
#else
@@ -208,6 +209,7 @@ PHP_FUNCTION(readline_info)
208209
#endif
209210
}
210211
RETVAL_STRING(SAFE_STRING(oldstr));
212+
free(oldstr);
211213
} else if (zend_string_equals_literal_ci(what, "point")) {
212214
RETVAL_LONG(rl_point);
213215
#ifndef PHP_WIN32

ext/readline/tests/gh16812.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
GH-16812 readline_info(): UAF
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (getenv('SKIP_REPEAT')) die("skip readline has global state");
8+
?>
9+
--FILE--
10+
<?php
11+
readline_write_history(NULL);
12+
var_dump(readline_info('line_buffer', 'test'));
13+
?>
14+
--EXPECT--
15+
string(0) ""

0 commit comments

Comments
 (0)