Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit daa3248

Browse files
committed
minor #43778 Use try/finally to restore error handlers (derrabus)
This PR was merged into the 5.4 branch. Discussion ---------- Use try/finally to restore error handlers | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | N/A | License | MIT | Doc PR | N/A This PR attempts to make some code dealing with temporary error handlers a bit more robust by making sure the old error handler is always restored. A forgotten error handler is pretty hard to debug, so I'd like our code to be a it more defensive here. Commits ------- 057716c Use try/finally to restore error handlers
2 parents cddd1ff + 057716c commit daa3248

File tree

13 files changed

+108
-78
lines changed

13 files changed

+108
-78
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,11 @@ public function __construct($message, array $trace, $file)
102102
}
103103

104104
set_error_handler(function () {});
105-
$parsedMsg = unserialize($this->message);
106-
restore_error_handler();
105+
try {
106+
$parsedMsg = unserialize($this->message);
107+
} finally {
108+
restore_error_handler();
109+
}
107110
if ($parsedMsg && isset($parsedMsg['deprecation'])) {
108111
$this->message = $parsedMsg['deprecation'];
109112
$this->originClass = $parsedMsg['class'];

src/Symfony/Component/Cache/Traits/RedisTrait.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,11 @@ public static function createConnection(string $dsn, array $options = [])
205205
@$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') ? [['stream' => $params['ssl'] ?? null]] : []);
206206

207207
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
208-
$isConnected = $redis->isConnected();
209-
restore_error_handler();
208+
try {
209+
$isConnected = $redis->isConnected();
210+
} finally {
211+
restore_error_handler();
212+
}
210213
if (!$isConnected) {
211214
$error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : '';
212215
throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.');

src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,19 @@ public function testSetDeprecated()
254254
};
255255

256256
$prevErrorHandler = set_error_handler($deprecationHandler);
257-
$node->finalize([]);
258-
restore_error_handler();
259-
257+
try {
258+
$node->finalize([]);
259+
} finally {
260+
restore_error_handler();
261+
}
260262
$this->assertFalse($deprecationTriggered, '->finalize() should not trigger if the deprecated node is not set');
261263

262264
$prevErrorHandler = set_error_handler($deprecationHandler);
263-
$node->finalize(['foo' => []]);
264-
restore_error_handler();
265+
try {
266+
$node->finalize(['foo' => []]);
267+
} finally {
268+
restore_error_handler();
269+
}
265270
$this->assertTrue($deprecationTriggered, '->finalize() should trigger if the deprecated node is set');
266271
}
267272

src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,19 @@ public function testSetDeprecated()
6767
};
6868

6969
$prevErrorHandler = set_error_handler($deprecationHandler);
70-
$node->finalize([]);
71-
restore_error_handler();
70+
try {
71+
$node->finalize([]);
72+
} finally {
73+
restore_error_handler();
74+
}
7275
$this->assertSame(0, $deprecationTriggered, '->finalize() should not trigger if the deprecated node is not set');
7376

7477
$prevErrorHandler = set_error_handler($deprecationHandler);
75-
$node->finalize(['foo' => '']);
76-
restore_error_handler();
78+
try {
79+
$node->finalize(['foo' => '']);
80+
} finally {
81+
restore_error_handler();
82+
}
7783
$this->assertSame(1, $deprecationTriggered, '->finalize() should trigger if the deprecated node is set');
7884
}
7985

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -737,15 +737,10 @@ private static function box(callable $func, ...$args)
737737
self::$lastError = null;
738738
set_error_handler(__CLASS__.'::handleError');
739739
try {
740-
$result = $func(...$args);
740+
return $func(...$args);
741+
} finally {
741742
restore_error_handler();
742-
743-
return $result;
744-
} catch (\Throwable $e) {
745743
}
746-
restore_error_handler();
747-
748-
throw $e;
749744
}
750745

751746
/**

src/Symfony/Component/Finder/SplFileInfo.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,11 @@ public function getFilenameWithoutExtension(): string
7474
public function getContents()
7575
{
7676
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
77-
$content = file_get_contents($this->getPathname());
78-
restore_error_handler();
77+
try {
78+
$content = file_get_contents($this->getPathname());
79+
} finally {
80+
restore_error_handler();
81+
}
7982
if (false === $content) {
8083
throw new \RuntimeException($error);
8184
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,11 @@ public function move(string $directory, string $name = null)
9393
$target = $this->getTargetFile($directory, $name);
9494

9595
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
96-
$renamed = rename($this->getPathname(), $target);
97-
restore_error_handler();
96+
try {
97+
$renamed = rename($this->getPathname(), $target);
98+
} finally {
99+
restore_error_handler();
100+
}
98101
if (!$renamed) {
99102
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
100103
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,11 @@ public function move(string $directory, string $name = null)
182182
$target = $this->getTargetFile($directory, $name);
183183

184184
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
185-
$moved = move_uploaded_file($this->getPathname(), $target);
186-
restore_error_handler();
185+
try {
186+
$moved = move_uploaded_file($this->getPathname(), $target);
187+
} finally {
188+
restore_error_handler();
189+
}
187190
if (!$moved) {
188191
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
189192
}

src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ public function testConfigure()
5050
try {
5151
$listener->configure();
5252
} catch (\Exception $exception) {
53+
} finally {
54+
restore_exception_handler();
55+
restore_error_handler();
5356
}
54-
restore_exception_handler();
55-
restore_error_handler();
5657

5758
if (null !== $exception) {
5859
throw $exception;
@@ -116,9 +117,10 @@ public function testConsoleEvent()
116117
try {
117118
$dispatcher->dispatch($event, ConsoleEvents::COMMAND);
118119
} catch (\Exception $exception) {
120+
} finally {
121+
restore_exception_handler();
122+
restore_error_handler();
119123
}
120-
restore_exception_handler();
121-
restore_error_handler();
122124

123125
if (null !== $exception) {
124126
throw $exception;

src/Symfony/Component/Lock/Store/FlockStore.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,18 @@ private function lock(Key $key, bool $read, bool $blocking)
106106

107107
// Silence error reporting
108108
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
109-
if (!$handle = fopen($fileName, 'r+') ?: fopen($fileName, 'r')) {
110-
if ($handle = fopen($fileName, 'x')) {
111-
chmod($fileName, 0666);
112-
} elseif (!$handle = fopen($fileName, 'r+') ?: fopen($fileName, 'r')) {
113-
usleep(100); // Give some time for chmod() to complete
114-
$handle = fopen($fileName, 'r+') ?: fopen($fileName, 'r');
109+
try {
110+
if (!$handle = fopen($fileName, 'r+') ?: fopen($fileName, 'r')) {
111+
if ($handle = fopen($fileName, 'x')) {
112+
chmod($fileName, 0666);
113+
} elseif (!$handle = fopen($fileName, 'r+') ?: fopen($fileName, 'r')) {
114+
usleep(100); // Give some time for chmod() to complete
115+
$handle = fopen($fileName, 'r+') ?: fopen($fileName, 'r');
116+
}
115117
}
118+
} finally {
119+
restore_error_handler();
116120
}
117-
restore_error_handler();
118121
}
119122

120123
if (!$handle) {

src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,13 @@ public function testDeprecationMessages(\Closure $configureOptions, array $optio
537537
});
538538
$e = error_reporting(0);
539539

540-
$configureOptions($this->resolver);
541-
$this->resolver->resolve($options);
542-
543-
error_reporting($e);
544-
restore_error_handler();
540+
try {
541+
$configureOptions($this->resolver);
542+
$this->resolver->resolve($options);
543+
} finally {
544+
error_reporting($e);
545+
restore_error_handler();
546+
}
545547

546548
$lastError = error_get_last();
547549
unset($lastError['file'], $lastError['line']);

src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -151,40 +151,43 @@ private function getCommonPrefix(string $prefix, string $anotherPrefix): array
151151
$staticLength = null;
152152
set_error_handler([__CLASS__, 'handleError']);
153153

154-
for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) {
155-
if ('(' === $prefix[$i]) {
156-
$staticLength = $staticLength ?? $i;
157-
for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) {
158-
if ($prefix[$j] !== $anotherPrefix[$j]) {
159-
break 2;
154+
try {
155+
for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) {
156+
if ('(' === $prefix[$i]) {
157+
$staticLength = $staticLength ?? $i;
158+
for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) {
159+
if ($prefix[$j] !== $anotherPrefix[$j]) {
160+
break 2;
161+
}
162+
if ('(' === $prefix[$j]) {
163+
++$n;
164+
} elseif (')' === $prefix[$j]) {
165+
--$n;
166+
} elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) {
167+
--$j;
168+
break;
169+
}
160170
}
161-
if ('(' === $prefix[$j]) {
162-
++$n;
163-
} elseif (')' === $prefix[$j]) {
164-
--$n;
165-
} elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) {
166-
--$j;
171+
if (0 < $n) {
167172
break;
168173
}
169-
}
170-
if (0 < $n) {
171-
break;
172-
}
173-
if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) {
174-
break;
175-
}
176-
$subPattern = substr($prefix, $i, $j - $i);
177-
if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?<!'.$subPattern.')}', '')) {
178-
// sub-patterns of variable length are not considered as common prefixes because their greediness would break in-order matching
174+
if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) {
175+
break;
176+
}
177+
$subPattern = substr($prefix, $i, $j - $i);
178+
if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?<!'.$subPattern.')}', '')) {
179+
// sub-patterns of variable length are not considered as common prefixes because their greediness would break in-order matching
180+
break;
181+
}
182+
$i = $j - 1;
183+
} elseif ('\\' === $prefix[$i] && (++$i === $end || $prefix[$i] !== $anotherPrefix[$i])) {
184+
--$i;
179185
break;
180186
}
181-
$i = $j - 1;
182-
} elseif ('\\' === $prefix[$i] && (++$i === $end || $prefix[$i] !== $anotherPrefix[$i])) {
183-
--$i;
184-
break;
185187
}
188+
} finally {
189+
restore_error_handler();
186190
}
187-
restore_error_handler();
188191
if ($i < $end && 0b10 === (\ord($prefix[$i]) >> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) {
189192
do {
190193
// Prevent cutting in the middle of an UTF-8 characters

src/Symfony/Component/Security/Http/Firewall/ContextListener.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -298,29 +298,28 @@ protected function refreshUser(TokenInterface $token): ?TokenInterface
298298

299299
private function safelyUnserialize(string $serializedToken)
300300
{
301-
$e = $token = null;
301+
$token = null;
302302
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
303303
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler) {
304304
if (__FILE__ === $file) {
305-
throw new \ErrorException($msg, 0x37313bc, $type, $file, $line);
305+
throw new \ErrorException($msg, 0x37313BC, $type, $file, $line);
306306
}
307307

308308
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
309309
});
310310

311311
try {
312312
$token = unserialize($serializedToken);
313-
} catch (\Throwable $e) {
314-
}
315-
restore_error_handler();
316-
ini_set('unserialize_callback_func', $prevUnserializeHandler);
317-
if ($e) {
318-
if (!$e instanceof \ErrorException || 0x37313bc !== $e->getCode()) {
313+
} catch (\ErrorException $e) {
314+
if (0x37313BC !== $e->getCode()) {
319315
throw $e;
320316
}
321317
if ($this->logger) {
322318
$this->logger->warning('Failed to unserialize the security token from the session.', ['key' => $this->sessionKey, 'received' => $serializedToken, 'exception' => $e]);
323319
}
320+
} finally {
321+
restore_error_handler();
322+
ini_set('unserialize_callback_func', $prevUnserializeHandler);
324323
}
325324

326325
return $token;
@@ -388,7 +387,7 @@ private static function hasUserChanged($originalUser, TokenInterface $refreshedT
388387
*/
389388
public static function handleUnserializeCallback(string $class)
390389
{
391-
throw new \ErrorException('Class not found: '.$class, 0x37313bc);
390+
throw new \ErrorException('Class not found: '.$class, 0x37313BC);
392391
}
393392

394393
/**

0 commit comments

Comments
 (0)