Skip to content

Commit dab5f8c

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-13685: Unexpected null pointer in zend_string.h
2 parents 6c4e3c0 + aa34e0a commit dab5f8c

File tree

3 files changed

+83
-18
lines changed

3 files changed

+83
-18
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ PHP NEWS
3737
. Fixed bug GH-13680 (Segfault with session_decode and compilation error).
3838
(nielsdos)
3939

40+
- SPL:
41+
. Fixed bug GH-13685 (Unexpected null pointer in zend_string.h). (nielsdos)
42+
4043
- Standard:
4144
. Fixed bug GH-11808 (Live filesystem modified by tests). (nielsdos)
4245
. Fixed GH-13402 (Added validation of `\n` in $additional_headers of mail()).

ext/spl/spl_directory.c

+28-18
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,11 @@ static zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *
18591859
}
18601860
/* }}} */
18611861

1862+
static ZEND_COLD void spl_filesystem_file_cannot_read(spl_filesystem_object *intern)
1863+
{
1864+
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", ZSTR_VAL(intern->file_name));
1865+
}
1866+
18621867
static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bool silent, zend_long line_add, bool csv)
18631868
{
18641869
char *buf;
@@ -1868,7 +1873,7 @@ static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bo
18681873

18691874
if (php_stream_eof(intern->u.file.stream)) {
18701875
if (!silent) {
1871-
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", ZSTR_VAL(intern->file_name));
1876+
spl_filesystem_file_cannot_read(intern);
18721877
}
18731878
return FAILURE;
18741879
}
@@ -1923,10 +1928,10 @@ static bool is_line_empty(spl_filesystem_object *intern)
19231928
|| (current_line_len == 2 && current_line[0] == '\r' && current_line[1] == '\n'))));
19241929
}
19251930

1926-
static zend_result spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, int escape, zval *return_value) /* {{{ */
1931+
static zend_result spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, int escape, zval *return_value, bool silent) /* {{{ */
19271932
{
19281933
do {
1929-
zend_result ret = spl_filesystem_file_read(intern, /* silent */ true, /* csv */ true);
1934+
zend_result ret = spl_filesystem_file_read(intern, silent, /* csv */ true);
19301935
if (ret != SUCCESS) {
19311936
return ret;
19321937
}
@@ -1952,19 +1957,21 @@ static zend_result spl_filesystem_file_read_csv(spl_filesystem_object *intern, c
19521957
}
19531958
/* }}} */
19541959

1955-
/* Call to this function reads a line in a "silent" fashion and does not throw an exception */
1956-
static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */
1960+
static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, bool silent) /* {{{ */
19571961
{
19581962
zval retval;
19591963

19601964
/* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */
19611965
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) {
1962-
return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL);
1966+
return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL, silent);
19631967
}
19641968
if (intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
19651969
spl_filesystem_file_free_line(intern);
19661970

19671971
if (php_stream_eof(intern->u.file.stream)) {
1972+
if (!silent) {
1973+
spl_filesystem_file_cannot_read(intern);
1974+
}
19681975
return FAILURE;
19691976
}
19701977
zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(this_ptr), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
@@ -1988,18 +1995,17 @@ static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesys
19881995
zval_ptr_dtor(&retval);
19891996
return SUCCESS;
19901997
} else {
1991-
return spl_filesystem_file_read(intern, /* silent */ true, /* csv */ false);
1998+
return spl_filesystem_file_read(intern, silent, /* csv */ false);
19921999
}
19932000
} /* }}} */
19942001

1995-
/* Call to this function reads a line in a "silent" fashion and does not throw an exception */
1996-
static zend_result spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */
2002+
static zend_result spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, bool silent) /* {{{ */
19972003
{
1998-
zend_result ret = spl_filesystem_file_read_line_ex(this_ptr, intern);
2004+
zend_result ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
19992005

20002006
while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && is_line_empty(intern)) {
20012007
spl_filesystem_file_free_line(intern);
2002-
ret = spl_filesystem_file_read_line_ex(this_ptr, intern);
2008+
ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
20032009
}
20042010

20052011
return ret;
@@ -2021,7 +2027,7 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i
20212027
intern->u.file.current_line_num = 0;
20222028

20232029
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2024-
spl_filesystem_file_read_line(this_ptr, intern);
2030+
spl_filesystem_file_read_line(this_ptr, intern, true);
20252031
}
20262032
} /* }}} */
20272033

@@ -2175,7 +2181,7 @@ PHP_METHOD(SplFileObject, current)
21752181
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
21762182

21772183
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
2178-
spl_filesystem_file_read_line(ZEND_THIS, intern);
2184+
spl_filesystem_file_read_line(ZEND_THIS, intern, true);
21792185
}
21802186
if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
21812187
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
@@ -2214,7 +2220,7 @@ PHP_METHOD(SplFileObject, next)
22142220

22152221
spl_filesystem_file_free_line(intern);
22162222
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2217-
spl_filesystem_file_read_line(ZEND_THIS, intern);
2223+
spl_filesystem_file_read_line(ZEND_THIS, intern, true);
22182224
}
22192225
intern->u.file.current_line_num++;
22202226
} /* }}} */
@@ -2332,7 +2338,7 @@ PHP_METHOD(SplFileObject, fgetcsv)
23322338
}
23332339
}
23342340

2335-
if (spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value) == FAILURE) {
2341+
if (spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value, true) == FAILURE) {
23362342
RETURN_FALSE;
23372343
}
23382344
}
@@ -2713,7 +2719,7 @@ PHP_METHOD(SplFileObject, seek)
27132719
spl_filesystem_file_rewind(ZEND_THIS, intern);
27142720

27152721
for (i = 0; i < line_pos; i++) {
2716-
if (spl_filesystem_file_read_line(ZEND_THIS, intern) == FAILURE) {
2722+
if (spl_filesystem_file_read_line(ZEND_THIS, intern, true) == FAILURE) {
27172723
return;
27182724
}
27192725
}
@@ -2733,8 +2739,12 @@ PHP_METHOD(SplFileObject, __toString)
27332739

27342740
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
27352741

2736-
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
2737-
spl_filesystem_file_read_line(ZEND_THIS, intern);
2742+
if (!intern->u.file.current_line) {
2743+
ZEND_ASSERT(Z_ISUNDEF(intern->u.file.current_zval));
2744+
zend_result result = spl_filesystem_file_read_line(ZEND_THIS, intern, false);
2745+
if (UNEXPECTED(result != SUCCESS)) {
2746+
RETURN_THROWS();
2747+
}
27382748
}
27392749

27402750
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);

ext/spl/tests/gh13685.phpt

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
GH-13685 (Unexpected null pointer in zend_string.h)
3+
--FILE--
4+
<?php
5+
6+
$contents = <<<EOS
7+
"A", "B", "C"
8+
"D", "E", "F"
9+
EOS;
10+
11+
echo "--- Directly call fgetcsv ---\n";
12+
13+
$file = new SplTempFileObject;
14+
$file->fwrite($contents);
15+
$file->rewind();
16+
while (($data = $file->fgetcsv(',', '"', ''))) {
17+
var_dump((string) $file);
18+
}
19+
try {
20+
var_dump((string) $file);
21+
} catch (Exception $e) {
22+
echo $e->getMessage(), "\n";
23+
}
24+
25+
echo "--- Use csv control ---\n";
26+
27+
$file = new SplTempFileObject;
28+
$file->fwrite($contents);
29+
$file->rewind();
30+
$file->setFlags(SplFileObject::READ_CSV);
31+
$file->setCsvControl(',', '"', '');
32+
foreach ($file as $row) {
33+
var_dump((string) $file);
34+
}
35+
try {
36+
var_dump((string) $file);
37+
} catch (Exception $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
41+
?>
42+
--EXPECT--
43+
--- Directly call fgetcsv ---
44+
string(14) ""A", "B", "C"
45+
"
46+
string(13) ""D", "E", "F""
47+
Cannot read from file php://temp
48+
--- Use csv control ---
49+
string(14) ""A", "B", "C"
50+
"
51+
string(13) ""D", "E", "F""
52+
Cannot read from file php://temp

0 commit comments

Comments
 (0)