Skip to content

Commit 4d41dff

Browse files
committed
Fix GH-12721: SplFileInfo::getFilename() segfault in combination with GlobIterator and no directory separator
This broke in 7cd8879 and 9bae9ab. NULL is a perfectly valid return value that should be handled. Closes GH-12722.
1 parent f90b404 commit 4d41dff

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ PHP NEWS
2222
- PHPDBG:
2323
. Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos)
2424

25+
- SPL:
26+
. Fixed bug GH-12721 (SplFileInfo::getFilename() segfault in combination
27+
with GlobIterator and no directory separator). (nielsdos)
28+
2529
- SQLite3:
2630
. Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0).
2731
(SakiTakamachi)

ext/spl/spl_directory.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -925,15 +925,16 @@ PHP_METHOD(SplFileInfo, getFilename)
925925

926926
path = spl_filesystem_object_get_path(intern);
927927

928-
ZEND_ASSERT(path);
929928
if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
930929
/* +1 to skip the trailing / of the path in the file name */
931930
size_t path_len = ZSTR_LEN(path) + 1;
932931
RETVAL_STRINGL(ZSTR_VAL(intern->file_name) + path_len, ZSTR_LEN(intern->file_name) - path_len);
933932
} else {
934933
RETVAL_STR_COPY(intern->file_name);
935934
}
936-
zend_string_release_ex(path, /* persistent */ false);
935+
if (path) {
936+
zend_string_release_ex(path, /* persistent */ false);
937+
}
937938
}
938939
/* }}} */
939940

@@ -973,14 +974,16 @@ PHP_METHOD(SplFileInfo, getExtension)
973974

974975
path = spl_filesystem_object_get_path(intern);
975976

976-
if (ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
977+
if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
977978
fname = ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1;
978979
flen = ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1);
979980
} else {
980981
fname = ZSTR_VAL(intern->file_name);
981982
flen = ZSTR_LEN(intern->file_name);
982983
}
983-
zend_string_release_ex(path, /* persistent */ false);
984+
if (path) {
985+
zend_string_release_ex(path, /* persistent */ false);
986+
}
984987

985988
ret = php_basename(fname, flen, NULL, 0);
986989

@@ -1052,7 +1055,9 @@ PHP_METHOD(SplFileInfo, getBasename)
10521055
fname = ZSTR_VAL(intern->file_name);
10531056
flen = ZSTR_LEN(intern->file_name);
10541057
}
1055-
zend_string_release_ex(path, /* persistent */ false);
1058+
if (path) {
1059+
zend_string_release_ex(path, /* persistent */ false);
1060+
}
10561061

10571062
RETURN_STR(php_basename(fname, flen, suffix, slen));
10581063
}

ext/spl/tests/gh12721.phpt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
GH-12721 (SplFileInfo::getFilename() segfault in combination with GlobIterator and no directory separator)
3+
--FILE--
4+
<?php
5+
6+
file_put_contents('file1.gh12721', 'hello');
7+
8+
echo "--- No slash ---\n";
9+
10+
foreach (new GlobIterator('*.gh12721') as $fileInfo) {
11+
echo $fileInfo->getFilename(), "\n";
12+
echo $fileInfo->getExtension(), "\n";
13+
echo $fileInfo->getBasename(), "\n";
14+
var_dump($fileInfo->getFileInfo());
15+
}
16+
17+
echo "--- With slash ---\n";
18+
19+
foreach (new GlobIterator('./*.gh12721') as $fileInfo) {
20+
echo $fileInfo->getFilename(), "\n";
21+
echo $fileInfo->getExtension(), "\n";
22+
echo $fileInfo->getBasename(), "\n";
23+
var_dump($fileInfo->getFileInfo());
24+
}
25+
26+
?>
27+
--CLEAN--
28+
<?php
29+
@unlink('file1.gh12721');
30+
?>
31+
--EXPECTF--
32+
--- No slash ---
33+
file1.gh12721
34+
gh12721
35+
file1.gh12721
36+
object(SplFileInfo)#4 (2) {
37+
["pathName":"SplFileInfo":private]=>
38+
string(13) "file1.gh12721"
39+
["fileName":"SplFileInfo":private]=>
40+
string(13) "file1.gh12721"
41+
}
42+
--- With slash ---
43+
file1.gh12721
44+
gh12721
45+
file1.gh12721
46+
object(SplFileInfo)#3 (2) {
47+
["pathName":"SplFileInfo":private]=>
48+
string(15) "%sfile1.gh12721"
49+
["fileName":"SplFileInfo":private]=>
50+
string(13) "file1.gh12721"
51+
}

0 commit comments

Comments
 (0)