|
| 1 | +--TEST-- |
| 2 | +unserialize() respects class_alias for private properties |
| 3 | +--FILE-- |
| 4 | +<?php |
| 5 | + |
| 6 | +// Test 1: Basic class_alias with private property |
| 7 | +class HelloAlias { |
| 8 | + public function __construct( |
| 9 | + private readonly int $answer = 0 |
| 10 | + ) {} |
| 11 | + |
| 12 | + public function getAnswer(): int { |
| 13 | + return $this->answer; |
| 14 | + } |
| 15 | +} |
| 16 | +class_alias(HelloAlias::class, 'Hello'); |
| 17 | + |
| 18 | +$serialized = 'O:5:"Hello":1:{s:13:"' . "\0Hello\0" . 'answer";i:42;}'; |
| 19 | +$obj = unserialize($serialized); |
| 20 | +var_dump($obj instanceof HelloAlias); |
| 21 | +var_dump($obj->getAnswer()); |
| 22 | + |
| 23 | +// Test 2: Protected property (should continue to work) |
| 24 | +class ProtoAlias { |
| 25 | + public function __construct( |
| 26 | + protected int $value = 0 |
| 27 | + ) {} |
| 28 | + public function getValue(): int { return $this->value; } |
| 29 | +} |
| 30 | +class_alias(ProtoAlias::class, 'Proto'); |
| 31 | + |
| 32 | +$serialized2 = 'O:5:"Proto":1:{s:8:"' . "\0*\0" . 'value";i:99;}'; |
| 33 | +$obj2 = unserialize($serialized2); |
| 34 | +var_dump($obj2 instanceof ProtoAlias); |
| 35 | +var_dump($obj2->getValue()); |
| 36 | + |
| 37 | +// Test 3: Public property (should continue to work) |
| 38 | +class PubAlias { |
| 39 | + public int $data = 0; |
| 40 | +} |
| 41 | +class_alias(PubAlias::class, 'Pub'); |
| 42 | + |
| 43 | +$serialized3 = 'O:3:"Pub":1:{s:4:"data";i:77;}'; |
| 44 | +$obj3 = unserialize($serialized3); |
| 45 | +var_dump($obj3 instanceof PubAlias); |
| 46 | +var_dump($obj3->data); |
| 47 | + |
| 48 | +// Test 4: Inheritance — child class with parent's private property via alias |
| 49 | +class ParentClass { |
| 50 | + public function __construct( |
| 51 | + private int $secret = 0 |
| 52 | + ) {} |
| 53 | + public function getSecret(): int { return $this->secret; } |
| 54 | +} |
| 55 | + |
| 56 | +class ChildClass extends ParentClass { |
| 57 | + public function __construct( |
| 58 | + private int $childProp = 0, |
| 59 | + int $secret = 0 |
| 60 | + ) { |
| 61 | + parent::__construct($secret); |
| 62 | + } |
| 63 | + public function getChildProp(): int { return $this->childProp; } |
| 64 | +} |
| 65 | +class_alias(ChildClass::class, 'Kid'); |
| 66 | + |
| 67 | +// Serialized with alias name for the child's private prop, canonical name for parent's |
| 68 | +$serialized4 = 'O:3:"Kid":2:{s:14:"' . "\0Kid\0" . 'childProp";i:10;s:19:"' . "\0ParentClass\0" . 'secret";i:20;}'; |
| 69 | +$obj4 = unserialize($serialized4); |
| 70 | +var_dump($obj4 instanceof ChildClass); |
| 71 | +var_dump($obj4->getChildProp()); |
| 72 | +var_dump($obj4->getSecret()); |
| 73 | + |
| 74 | +// Test 5: Multiple private properties with alias |
| 75 | +class MultiPropAlias { |
| 76 | + public function __construct( |
| 77 | + private int $x = 0, |
| 78 | + private string $y = '', |
| 79 | + private bool $z = false |
| 80 | + ) {} |
| 81 | + public function getX(): int { return $this->x; } |
| 82 | + public function getY(): string { return $this->y; } |
| 83 | + public function getZ(): bool { return $this->z; } |
| 84 | +} |
| 85 | +class_alias(MultiPropAlias::class, 'Multi'); |
| 86 | + |
| 87 | +$serialized5 = 'O:5:"Multi":3:{s:8:"' . "\0Multi\0" . 'x";i:1;s:8:"' . "\0Multi\0" . 'y";s:3:"abc";s:8:"' . "\0Multi\0" . 'z";b:1;}'; |
| 88 | +$obj5 = unserialize($serialized5); |
| 89 | +var_dump($obj5 instanceof MultiPropAlias); |
| 90 | +var_dump($obj5->getX()); |
| 91 | +var_dump($obj5->getY()); |
| 92 | +var_dump($obj5->getZ()); |
| 93 | + |
| 94 | +// Test 6: Canonical name still works (non-alias path, regression check) |
| 95 | +$serialized6 = 'O:14:"MultiPropAlias":3:{s:17:"' . "\0MultiPropAlias\0" . 'x";i:5;s:17:"' . "\0MultiPropAlias\0" . 'y";s:2:"hi";s:17:"' . "\0MultiPropAlias\0" . 'z";b:0;}'; |
| 96 | +$obj6 = unserialize($serialized6); |
| 97 | +var_dump($obj6 instanceof MultiPropAlias); |
| 98 | +var_dump($obj6->getX()); |
| 99 | +var_dump($obj6->getY()); |
| 100 | +var_dump($obj6->getZ()); |
| 101 | + |
| 102 | +echo "Done\n"; |
| 103 | +?> |
| 104 | +--EXPECT-- |
| 105 | +bool(true) |
| 106 | +int(42) |
| 107 | +bool(true) |
| 108 | +int(99) |
| 109 | +bool(true) |
| 110 | +int(77) |
| 111 | +bool(true) |
| 112 | +int(10) |
| 113 | +int(20) |
| 114 | +bool(true) |
| 115 | +int(1) |
| 116 | +string(3) "abc" |
| 117 | +bool(true) |
| 118 | +bool(true) |
| 119 | +int(5) |
| 120 | +string(2) "hi" |
| 121 | +bool(false) |
| 122 | +Done |
0 commit comments