Skip to content

Commit 767a77a

Browse files
committed
Fix #36365: scandir duplicates file name at every 65535th file
Since DIR_W32.offset is declared as `uint16_t`, we have an overflow for directories with many entries. This patch changes the field to `uint32_t`.
1 parent 41a04f9 commit 767a77a

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ PHP NEWS
2020
(cmb)
2121
. Fixed bug #79368 ("Unexpected end of file" is not an acceptable error
2222
message). (Alex Dowad)
23+
. Fixed bug #36365 (scandir duplicates file name at every 65535th file).
24+
(cmb)
2325

2426
- BZ2:
2527
. Fixed bug #71263 (fread() does not report bzip2.decompress errors). (cmb)

ext/standard/tests/file/bug36365.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #36365 (scandir duplicates file name at every 65535th file)
3+
--SKIPIF--
4+
<?php
5+
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
6+
?>
7+
--FILE--
8+
<?php
9+
$testdir = __DIR__ . '/bug36365';
10+
11+
mkdir($testdir);
12+
for ($i = 0; $i < 70000; $i++) {
13+
touch(sprintf("$testdir/%05d.txt", $i));
14+
}
15+
16+
var_dump(count(scandir($testdir)));
17+
?>
18+
--CLEAN--
19+
<?php
20+
$testdir = __DIR__ . '/bug36365';
21+
for ($i = 0; $i < 70000; $i++) {
22+
unlink(sprintf("$testdir/%05d.txt", $i));
23+
}
24+
rmdir($testdir);
25+
?>
26+
--EXPECT--
27+
int(70002)

win32/readdir.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct dirent {
2626
/* typedef DIR - not the same as Unix */
2727
struct DIR_W32 {
2828
HANDLE handle; /* _findfirst/_findnext handle */
29-
uint16_t offset; /* offset into directory */
29+
uint32_t offset; /* offset into directory */
3030
uint8_t finished; /* 1 if there are not more files */
3131
WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */
3232
wchar_t *dirw; /* the dir we are reading */

0 commit comments

Comments
 (0)