Skip to content

Commit a393873

Browse files
authored
Merge pull request #6193 from kenjis/fix-Autoloader-sanitizeFilename
feat: Autoloader::sanitizeFilename() throws Exception
2 parents 26aece4 + d9c4d8c commit a393873

File tree

3 files changed

+63
-11
lines changed

3 files changed

+63
-11
lines changed

rector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
// check on constant compare
9595
UnwrapFutureCompatibleIfPhpVersionRector::class => [
9696
__DIR__ . '/system/CodeIgniter.php',
97+
__DIR__ . '/system/Autoloader/Autoloader.php',
9798
],
9899

99100
// session handlers have the gc() method with underscored parameter `$max_lifetime`

system/Autoloader/Autoloader.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Config\Autoload;
1616
use Config\Modules;
1717
use InvalidArgumentException;
18+
use RuntimeException;
1819

1920
/**
2021
* An autoloader that uses both PSR4 autoloading, and traditional classmaps.
@@ -290,9 +291,9 @@ protected function includeFile(string $file)
290291
}
291292

292293
/**
293-
* Sanitizes a filename, replacing spaces with dashes.
294+
* Check file path.
294295
*
295-
* Removes special characters that are illegal in filenames on certain
296+
* Checks special characters that are illegal in filenames on certain
296297
* operating systems and special characters requiring special escaping
297298
* to manipulate at the command line. Replaces spaces and consecutive
298299
* dashes with a single dash. Trim period, dash and underscore from beginning
@@ -306,10 +307,34 @@ public function sanitizeFilename(string $filename): string
306307
// Plus the forward slash for directory separators since this might be a path.
307308
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278
308309
// Modified to allow backslash and colons for on Windows machines.
309-
$filename = preg_replace('/[^0-9\p{L}\s\/\-\_\.\:\\\\]/u', '', $filename);
310+
$result = preg_match_all('/[^0-9\p{L}\s\/\-_.:\\\\]/u', $filename, $matches);
311+
312+
if ($result > 0) {
313+
$chars = implode('', $matches[0]);
314+
315+
throw new InvalidArgumentException(
316+
'The file path contains special characters "' . $chars
317+
. '" that are not allowed: "' . $filename . '"'
318+
);
319+
}
320+
if ($result === false) {
321+
if (version_compare(PHP_VERSION, '8.0.0', '>=')) {
322+
$message = preg_last_error_msg();
323+
} else {
324+
$message = 'Regex error. error code: ' . preg_last_error();
325+
}
326+
327+
throw new RuntimeException($message . '. filename: "' . $filename . '"');
328+
}
310329

311330
// Clean up our filename edges.
312-
return trim($filename, '.-_');
331+
$cleanFilename = trim($filename, '.-_');
332+
333+
if ($filename !== $cleanFilename) {
334+
throw new InvalidArgumentException('The characters ".-_" are not allowed in filename edges: "' . $filename . '"');
335+
}
336+
337+
return $cleanFilename;
313338
}
314339

315340
private function loadComposerNamespaces(ClassLoader $composer): void

tests/system/Autoloader/AutoloaderTest.php

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use Config\Autoload;
1717
use Config\Modules;
1818
use Config\Services;
19+
use InvalidArgumentException;
20+
use RuntimeException;
1921
use UnnamespacedClass;
2022

2123
/**
@@ -197,20 +199,44 @@ public function testloadClassNonNamespaced()
197199
$this->assertFalse($this->loader->loadClass('Modules'));
198200
}
199201

200-
public function testSanitizationSimply()
202+
public function testSanitizationContailsSpecialChars()
201203
{
202-
$test = '${../path}!#/to/some/file.php_';
203-
$expected = '/path/to/some/file.php';
204+
$this->expectException(InvalidArgumentException::class);
205+
$this->expectExceptionMessage(
206+
'The file path contains special characters "${}!#" that are not allowed: "${../path}!#/to/some/file.php_"'
207+
);
208+
209+
$test = '${../path}!#/to/some/file.php_';
210+
211+
$this->loader->sanitizeFilename($test);
212+
}
213+
214+
public function testSanitizationFilenameEdges()
215+
{
216+
$this->expectException(InvalidArgumentException::class);
217+
$this->expectExceptionMessage(
218+
'The characters ".-_" are not allowed in filename edges: "/path/to/some/file.php_"'
219+
);
204220

205-
$this->assertSame($expected, $this->loader->sanitizeFilename($test));
221+
$test = '/path/to/some/file.php_';
222+
223+
$this->loader->sanitizeFilename($test);
224+
}
225+
226+
public function testSanitizationRegexError()
227+
{
228+
$this->expectException(RuntimeException::class);
229+
230+
$test = mb_convert_encoding('クラスファイル.php', 'EUC-JP', 'UTF-8');
231+
232+
$this->loader->sanitizeFilename($test);
206233
}
207234

208235
public function testSanitizationAllowUnicodeChars()
209236
{
210-
$test = 'Ä/path/to/some/file.php_';
211-
$expected = 'Ä/path/to/some/file.php';
237+
$test = 'Ä/path/to/some/file.php';
212238

213-
$this->assertSame($expected, $this->loader->sanitizeFilename($test));
239+
$this->assertSame($test, $this->loader->sanitizeFilename($test));
214240
}
215241

216242
public function testSanitizationAllowsWindowsFilepaths()

0 commit comments

Comments
 (0)