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

Skip to content

Commit 27346bc

Browse files
bug #53183 [Messenger] PhpSerializer: TypeError should throw MessageDecodingFailedException (B-Galati)
This PR was merged into the 5.4 branch. Discussion ---------- [Messenger] PhpSerializer: TypeError should throw `MessageDecodingFailedException` | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT <!-- Replace this notice by a description of your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too). - Features and deprecations must be submitted against the latest branch. - For new features, provide some code snippets to help understand usage. - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> At the moment, some unserialization issues don't throw a `MessageDecodingFailedException` which prevent transport to trigger their decoding failure logic. There are many possibilities to fix the issue. I've implemented a very conservative one. I believe we could simplify the code by a lot if we rely on the global error handler in user land. Commits ------- ebe5c3a [Messenger] PhpSerializer: TypeError should throw MessageDecodingFailedException
2 parents a63f545 + ebe5c3a commit 27346bc

File tree

3 files changed

+54
-19
lines changed

3 files changed

+54
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Symfony\Component\Messenger\Tests\Fixtures;
4+
5+
class DummyMessageTyped implements DummyMessageInterface
6+
{
7+
private string $message;
8+
9+
public function __construct(string $message)
10+
{
11+
$this->message = $message;
12+
}
13+
14+
public function getMessage(): string
15+
{
16+
return $this->message;
17+
}
18+
}

src/Symfony/Component/Messenger/Tests/Transport/Serialization/PhpSerializerTest.php

+25-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
1717
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
1818
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
19+
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageTyped;
1920
use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
2021

2122
class PhpSerializerTest extends TestCase
@@ -33,45 +34,45 @@ public function testEncodedIsDecodable()
3334

3435
public function testDecodingFailsWithMissingBodyKey()
3536
{
37+
$serializer = new PhpSerializer();
38+
3639
$this->expectException(MessageDecodingFailedException::class);
3740
$this->expectExceptionMessage('Encoded envelope should have at least a "body", or maybe you should implement your own serializer');
3841

39-
$serializer = new PhpSerializer();
40-
4142
$serializer->decode([]);
4243
}
4344

4445
public function testDecodingFailsWithBadFormat()
4546
{
47+
$serializer = new PhpSerializer();
48+
4649
$this->expectException(MessageDecodingFailedException::class);
4750
$this->expectExceptionMessageMatches('/Could not decode/');
4851

49-
$serializer = new PhpSerializer();
50-
5152
$serializer->decode([
5253
'body' => '{"message": "bar"}',
5354
]);
5455
}
5556

5657
public function testDecodingFailsWithBadBase64Body()
5758
{
59+
$serializer = new PhpSerializer();
60+
5861
$this->expectException(MessageDecodingFailedException::class);
5962
$this->expectExceptionMessageMatches('/Could not decode/');
6063

61-
$serializer = new PhpSerializer();
62-
6364
$serializer->decode([
6465
'body' => 'x',
6566
]);
6667
}
6768

6869
public function testDecodingFailsWithBadClass()
6970
{
71+
$serializer = new PhpSerializer();
72+
7073
$this->expectException(MessageDecodingFailedException::class);
7174
$this->expectExceptionMessageMatches('/class "ReceivedSt0mp" not found/');
7275

73-
$serializer = new PhpSerializer();
74-
7576
$serializer->decode([
7677
'body' => 'O:13:"ReceivedSt0mp":0:{}',
7778
]);
@@ -99,6 +100,22 @@ public function testNonUtf8IsBase64Encoded()
99100
$this->assertTrue((bool) preg_match('//u', $encoded['body']), 'Encodes non-UTF8 payloads');
100101
$this->assertEquals($envelope, $serializer->decode($encoded));
101102
}
103+
104+
/**
105+
* @requires PHP 7.4
106+
*/
107+
public function testDecodingFailsForPropertyTypeMismatch()
108+
{
109+
$serializer = new PhpSerializer();
110+
$encodedEnvelope = $serializer->encode(new Envelope(new DummyMessageTyped('true')));
111+
// Simulate a change of property type in the code base
112+
$encodedEnvelope['body'] = str_replace('s:4:\"true\"', 'b:1', $encodedEnvelope['body']);
113+
114+
$this->expectException(MessageDecodingFailedException::class);
115+
$this->expectExceptionMessageMatches('/Could not decode/');
116+
117+
$serializer->decode($encodedEnvelope);
118+
}
102119
}
103120

104121
class DummyPhpSerializerNonSendableStamp implements NonSendableStampInterface

src/Symfony/Component/Messenger/Transport/Serialization/PhpSerializer.php

+11-11
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020
*/
2121
class PhpSerializer implements SerializerInterface
2222
{
23-
/**
24-
* {@inheritdoc}
25-
*/
2623
public function decode(array $encodedEnvelope): Envelope
2724
{
2825
if (empty($encodedEnvelope['body'])) {
@@ -38,9 +35,6 @@ public function decode(array $encodedEnvelope): Envelope
3835
return $this->safelyUnserialize($serializeEnvelope);
3936
}
4037

41-
/**
42-
* {@inheritdoc}
43-
*/
4438
public function encode(Envelope $envelope): array
4539
{
4640
$envelope = $envelope->withoutStampsOfType(NonSendableStampInterface::class);
@@ -62,24 +56,30 @@ private function safelyUnserialize(string $contents)
6256
throw new MessageDecodingFailedException('Could not decode an empty message using PHP serialization.');
6357
}
6458

65-
$signalingException = new MessageDecodingFailedException(sprintf('Could not decode message using PHP serialization: %s.', $contents));
6659
$prevUnserializeHandler = ini_set('unserialize_callback_func', self::class.'::handleUnserializeCallback');
67-
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) {
60+
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler) {
6861
if (__FILE__ === $file) {
69-
throw $signalingException;
62+
throw new \ErrorException($msg, 0, $type, $file, $line);
7063
}
7164

7265
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
7366
});
7467

7568
try {
76-
$meta = unserialize($contents);
69+
/** @var Envelope */
70+
$envelope = unserialize($contents);
71+
} catch (\Throwable $e) {
72+
if ($e instanceof MessageDecodingFailedException) {
73+
throw $e;
74+
}
75+
76+
throw new MessageDecodingFailedException('Could not decode Envelope: '.$e->getMessage(), 0, $e);
7777
} finally {
7878
restore_error_handler();
7979
ini_set('unserialize_callback_func', $prevUnserializeHandler);
8080
}
8181

82-
return $meta;
82+
return $envelope;
8383
}
8484

8585
/**

0 commit comments

Comments
 (0)