Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 15b03a8

Browse filesBrowse files
committed
bug #27236 [Filesystem] Fix usages of error_get_last() (nicolas-grekas)
This PR was merged into the 2.7 branch. Discussion ---------- [Filesystem] Fix usages of error_get_last() | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Same as #27232 for 2.7. When a userland error handler doesn't return `false`, `error_get_last()` is not updated, so we cannot see the real last error, but the previous one. See https://3v4l.org/Smmt7 Commits ------- 9d015c7 [Filesystem] Fix usages of error_get_last()
2 parents 8072eed + 9d015c7 commit 15b03a8
Copy full SHA for 15b03a8

File tree

7 files changed

+73
-38
lines changed
Filter options

7 files changed

+73
-38
lines changed

‎src/Symfony/Component/Console/Command/Command.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Command/Command.php
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,11 @@ public function run(InputInterface $input, OutputInterface $output)
205205

206206
if (null !== $this->processTitle) {
207207
if (function_exists('cli_set_process_title')) {
208-
if (false === @cli_set_process_title($this->processTitle)) {
208+
if (!@cli_set_process_title($this->processTitle)) {
209209
if ('Darwin' === PHP_OS) {
210210
$output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
211211
} else {
212-
$error = error_get_last();
213-
trigger_error($error['message'], E_USER_WARNING);
212+
cli_set_process_title($this->processTitle);
214213
}
215214
}
216215
} elseif (function_exists('setproctitle')) {

‎src/Symfony/Component/Filesystem/Filesystem.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Filesystem/Filesystem.php
+42-22Lines changed: 42 additions & 22 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,19 +334,16 @@ 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)) {
349-
$report = error_get_last();
350-
if (is_array($report)) {
351-
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
344+
if (!self::box('symlink', $originDir, $targetDir)) {
345+
if (null !== self::$lastError) {
346+
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
352347
throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', 0, null, $targetDir);
353348
}
354349
}
@@ -580,4 +575,29 @@ private function toIterator($files)
580575

581576
return $files;
582577
}
578+
579+
private static function box($func)
580+
{
581+
self::$lastError = null;
582+
\set_error_handler(__CLASS__.'::handleError');
583+
try {
584+
$result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
585+
\restore_error_handler();
586+
587+
return $result;
588+
} catch (\Throwable $e) {
589+
} catch (\Exception $e) {
590+
}
591+
\restore_error_handler();
592+
593+
throw $e;
594+
}
595+
596+
/**
597+
* @internal
598+
*/
599+
public static function handleError($type, $msg)
600+
{
601+
self::$lastError = $msg;
602+
}
583603
}

‎src/Symfony/Component/Finder/SplFileInfo.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Finder/SplFileInfo.php
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,11 @@ public function getRelativePathname()
6666
*/
6767
public function getContents()
6868
{
69-
$level = error_reporting(0);
69+
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
7070
$content = file_get_contents($this->getPathname());
71-
error_reporting($level);
71+
restore_error_handler();
7272
if (false === $content) {
73-
$error = error_get_last();
74-
throw new \RuntimeException($error['message']);
73+
throw new \RuntimeException($error);
7574
}
7675

7776
return $content;

‎src/Symfony/Component/HttpFoundation/File/File.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/File/File.php
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,11 @@ public function move($directory, $name = null)
9393
{
9494
$target = $this->getTargetFile($directory, $name);
9595

96-
if (!@rename($this->getPathname(), $target)) {
97-
$error = error_get_last();
98-
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
96+
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
97+
$renamed = rename($this->getPathname(), $target);
98+
restore_error_handler();
99+
if (!$renamed) {
100+
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
99101
}
100102

101103
@chmod($target, 0666 & ~umask());

‎src/Symfony/Component/HttpFoundation/File/UploadedFile.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/File/UploadedFile.php
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,11 @@ public function move($directory, $name = null)
192192

193193
$target = $this->getTargetFile($directory, $name);
194194

195-
if (!@move_uploaded_file($this->getPathname(), $target)) {
196-
$error = error_get_last();
197-
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
195+
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
196+
$moved = move_uploaded_file($this->getPathname(), $target);
197+
restore_error_handler();
198+
if (!$moved) {
199+
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
198200
}
199201

200202
@chmod($target, 0666 & ~umask());

‎src/Symfony/Component/Process/Pipes/AbstractPipes.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Pipes/AbstractPipes.php
+12-2Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ abstract class AbstractPipes implements PipesInterface
2323
private $inputBuffer = '';
2424
private $input;
2525
private $blocked = true;
26+
private $lastError;
2627

2728
/**
2829
* @param resource|null $input
@@ -56,10 +57,11 @@ public function close()
5657
*/
5758
protected function hasSystemCallBeenInterrupted()
5859
{
59-
$lastError = error_get_last();
60+
$lastError = $this->lastError;
61+
$this->lastError = null;
6062

6163
// stream_select returns false when the `select` system call is interrupted by an incoming signal
62-
return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
64+
return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
6365
}
6466

6567
/**
@@ -137,4 +139,12 @@ protected function write()
137139
return array($this->pipes[0]);
138140
}
139141
}
142+
143+
/**
144+
* @internal
145+
*/
146+
public function handleError($type, $msg)
147+
{
148+
$this->lastError = $msg;
149+
}
140150
}

‎src/Symfony/Component/Process/Pipes/UnixPipes.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Pipes/UnixPipes.php
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ public function readAndWrite($blocking, $close = false)
9999
unset($r[0]);
100100

101101
// let's have a look if something changed in streams
102-
if (($r || $w) && false === @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
102+
set_error_handler(array($this, 'handleError'));
103+
if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
104+
restore_error_handler();
103105
// if a system call has been interrupted, forget about it, let's try again
104106
// otherwise, an error occurred, let's reset pipes
105107
if (!$this->hasSystemCallBeenInterrupted()) {
@@ -108,6 +110,7 @@ public function readAndWrite($blocking, $close = false)
108110

109111
return $read;
110112
}
113+
restore_error_handler();
111114

112115
foreach ($r as $pipe) {
113116
// prior PHP 5.4 the array passed to stream_select is modified and

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.