Skip to content

Commit 8e03ca3

Browse files
Merge branch '2.8' into 3.4
* 2.8: [Security] Fix logout #27250 limiting GET_LOCK key up to 64 char due to changes in MySQL 5.7.5 and later [Profiler] Remove propel & event_listener_loading category identifiers [Filesystem] Fix usages of error_get_last() [Debug] Fix populating error_get_last() for handled silent errors Suppress warnings when open_basedir is non-empty
2 parents d961178 + 1ed4b26 commit 8e03ca3

File tree

1 file changed

+43
-23
lines changed

1 file changed

+43
-23
lines changed

Filesystem.php

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
*/
2222
class Filesystem
2323
{
24+
private static $lastError;
25+
2426
/**
2527
* Copies a file.
2628
*
@@ -95,12 +97,11 @@ public function mkdir($dirs, $mode = 0777)
9597
continue;
9698
}
9799

98-
if (true !== @mkdir($dir, $mode, true)) {
99-
$error = error_get_last();
100+
if (!self::box('mkdir', $dir, $mode, true)) {
100101
if (!is_dir($dir)) {
101102
// The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
102-
if ($error) {
103-
throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
103+
if (self::$lastError) {
104+
throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
104105
}
105106
throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
106107
}
@@ -169,20 +170,17 @@ public function remove($files)
169170
foreach ($files as $file) {
170171
if (is_link($file)) {
171172
// See https://bugs.php.net/52176
172-
if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
173-
$error = error_get_last();
174-
throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
173+
if (!(self::box('unlink', $file) || '\\' !== DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
174+
throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
175175
}
176176
} elseif (is_dir($file)) {
177177
$this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
178178

179-
if (!@rmdir($file) && file_exists($file)) {
180-
$error = error_get_last();
181-
throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
179+
if (!self::box('rmdir', $file) && file_exists($file)) {
180+
throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
182181
}
183-
} elseif (!@unlink($file) && file_exists($file)) {
184-
$error = error_get_last();
185-
throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
182+
} elseif (!self::box('unlink', $file) && file_exists($file)) {
183+
throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
186184
}
187185
}
188186
}
@@ -336,16 +334,14 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false)
336334

337335
$this->mkdir(dirname($targetDir));
338336

339-
$ok = false;
340337
if (is_link($targetDir)) {
341-
if (readlink($targetDir) != $originDir) {
342-
$this->remove($targetDir);
343-
} else {
344-
$ok = true;
338+
if (readlink($targetDir) === $originDir) {
339+
return;
345340
}
341+
$this->remove($targetDir);
346342
}
347343

348-
if (!$ok && true !== @symlink($originDir, $targetDir)) {
344+
if (!self::box('symlink', $originDir, $targetDir)) {
349345
$this->linkException($originDir, $targetDir, 'symbolic');
350346
}
351347
}
@@ -377,7 +373,7 @@ public function hardlink($originFile, $targetFiles)
377373
$this->remove($targetFile);
378374
}
379375

380-
if (true !== @link($originFile, $targetFile)) {
376+
if (!self::box('link', $originFile, $targetFile)) {
381377
$this->linkException($originFile, $targetFile, 'hard');
382378
}
383379
}
@@ -390,9 +386,8 @@ public function hardlink($originFile, $targetFiles)
390386
*/
391387
private function linkException($origin, $target, $linkType)
392388
{
393-
$report = error_get_last();
394-
if (is_array($report)) {
395-
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
389+
if (self::$lastError) {
390+
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
396391
throw new IOException(sprintf('Unable to create %s link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target);
397392
}
398393
}
@@ -747,4 +742,29 @@ private function getSchemeAndHierarchy($filename)
747742

748743
return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
749744
}
745+
746+
private static function box($func)
747+
{
748+
self::$lastError = null;
749+
\set_error_handler(__CLASS__.'::handleError');
750+
try {
751+
$result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
752+
\restore_error_handler();
753+
754+
return $result;
755+
} catch (\Throwable $e) {
756+
} catch (\Exception $e) {
757+
}
758+
\restore_error_handler();
759+
760+
throw $e;
761+
}
762+
763+
/**
764+
* @internal
765+
*/
766+
public static function handleError($type, $msg)
767+
{
768+
self::$lastError = $msg;
769+
}
750770
}

0 commit comments

Comments
 (0)