Title: igbinary_unserialize dynamically creates conflicting properties when member access is changed · Issue #387 · igbinary/igbinary · GitHub
Open Graph Title: igbinary_unserialize dynamically creates conflicting properties when member access is changed · Issue #387 · igbinary/igbinary
X Title: igbinary_unserialize dynamically creates conflicting properties when member access is changed · Issue #387 · igbinary/igbinary
Description: This may be related to #156, I'm not sure. But that's a very old ticket so I'm wondering if I can expect a change to this behaviour, or at least a good workaround. When a class definition has changed since serialization, it's possible fo...
Open Graph Description: This may be related to #156, I'm not sure. But that's a very old ticket so I'm wondering if I can expect a change to this behaviour, or at least a good workaround. When a class definition has chang...
X Description: This may be related to #156, I'm not sure. But that's a very old ticket so I'm wondering if I can expect a change to this behaviour, or at least a good workaround. When a class definiti...
Opengraph URL: https://github.com/igbinary/igbinary/issues/387
X: @github
Domain: patch-diff.githubusercontent.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"igbinary_unserialize dynamically creates conflicting properties when member access is changed ","articleBody":"This may be related to #156, I'm not sure. But that's a very old ticket so I'm wondering if I can expect a change to this behaviour, or at least a good workaround.\r\n\r\nWhen a class definition has changed since serialization, it's possible for `igbinary_unserialize` to result in **multiple properties with the same name**, but different public/private access. I only noticed this behaviour when upgrading to PHP 8.2 where the creation of dynamic properties is deprecated, but the issue is reproducible in earlier PHP versions too.\r\n\r\nThe behaviour is best demonstrated with a working example:\r\n\r\nFirstly, serialize some legacy code (a simple object with a public property) and store the binary data somewhere:\r\n\r\n class Foo {\r\n public $bar;\r\n }\r\n $legacy = new Foo;\r\n $legacy-\u003ebar = 'baz';\r\n echo igbinary_serialize($legacy); // store the output\r\n\r\nThen update your class definition to use a private variable, and a default value to highlight the problem:\r\n\r\n class Foo {\r\n \r\n private string $bar = 'default';\r\n \r\n public function getBar():string {\r\n return $this-\u003ebar;\r\n }\r\n }\r\n\r\nThen unserialize your saved blob. I'll do this with the standard PHP unserialize function for comparison:\r\n\r\n $data = 'O:3:\"Foo\":1:{s:3:\"bar\";s:3:\"baz\";}';\r\n echo \"php unserialize =\u003e \",unserialize($data)-\u003egetBar(),\"\\n\";\r\n\r\n $data = \"\\0\\0\\0\\2\\x17\\3Foo\\x14\\1\\x11\\3bar\\x11\\3baz\";\r\n echo \"igbinary_unserialize =\u003e \",igbinary_unserialize($data)-\u003egetBar(),\"\\n\";\r\n\r\nThe above prints as follows, showing the PHP unserialize function is unaffected, but igbinary doesn't set the private property:\r\n\r\n php unserialize =\u003e baz\r\n igbinary_unserialize =\u003e default\r\n\r\nThe latter does in fact set a property, but it dynamically sets a public property with the same name. Under PHP \u003e= 8.2 you'll get a deprecation warning unless you annotate the class with `#[AllowDynamicProperties]`, but the behaviour exists regardless. If you dump the instance you'll see two properties named \"bar\" as follows:\r\n\r\n object(Foo)#1 (2) {\r\n [\"bar\":\"Foo\":private]=\u003e\r\n string(7) \"default\"\r\n [\"bar\"]=\u003e\r\n string(3) \"baz\"\r\n }\r\n\r\nIt was my own stupid fault for changing the class definition of serialized objects without a proper migration strategy, but I was blissfully unaware of this issue, and I don't imagine this is uncommon.\r\n\r\nThe only way I've found to access the originally serialized property is by casting the object to an array, like this:\r\n\r\n $foo = (array) igbinary_unserialize($data);\r\n echo \"dynamic =\u003e \",$foo['bar'],\"\\n\";\r\n echo \"private =\u003e \",$foo[\"\\0Foo\\0bar\"],\"\\n\";\r\n\r\nProduces:\r\n\r\n dynamic =\u003e baz\r\n private =\u003e default\r\n\r\n \r\nI'm currently working around this issue using a `__wakeup` method that copies the dynamically set property from the array (as shown above) back onto the private member. However, this isn't a permanent fix as the dynamically set property still exists in duplicate and will be serialized again. \u003cdel\u003eI've not found any way to unset it.\u003c/del\u003e\r\n\r\nAn easier fix is this: `$foo = unserialize(serialize($foo));` The PHP serializer lets the dynamic property overwrite the private member, but this has to be done outside the instance. It does however solve the problem of removing the duplicate property after the wakeup fix.\r\n\r\nIt seems that in PHP 8.3 the deprecated behaviour is still not removed, but I anticipate one day it will be and all my legacy objects will not be unserializable. I know this may not be considered a \"bug\" as such, but are there any plans to make `igbinary_unserialize` behave as per `unserialize` in this respect?\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n\r\n","author":{"url":"https://github.com/timwhitlock","@type":"Person","name":"timwhitlock"},"datePublished":"2024-01-18T10:58:06.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/387/igbinary/issues/387"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:149aba28-4e21-a83e-c5a5-b6f4391276dd |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D054:150FA6:735DBD:90C83A:697EF7C6 |
| html-safe-nonce | 71411918daa47c88ccc13fbc18c6c458c2ddd1c5596fa30e0e96d8066e033d0a |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEMDU0OjE1MEZBNjo3MzVEQkQ6OTBDODNBOjY5N0VGN0M2IiwidmlzaXRvcl9pZCI6IjUwNjM3MTMzNjIyNTMxMTczODIiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 7503386f442669dc3d27f4882723df9e11bffbe1c710ad3c73ec86ce90be92a7 |
| hovercard-subject-tag | issue:2088036878 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/igbinary/igbinary/387/issue_layout |
| twitter:image | https://opengraph.githubassets.com/56690c300a5fc2a39ecbeab540e221c361173998c79f3239bcbc94b66a5dff9c/igbinary/igbinary/issues/387 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/56690c300a5fc2a39ecbeab540e221c361173998c79f3239bcbc94b66a5dff9c/igbinary/igbinary/issues/387 |
| og:image:alt | This may be related to #156, I'm not sure. But that's a very old ticket so I'm wondering if I can expect a change to this behaviour, or at least a good workaround. When a class definition has chang... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | timwhitlock |
| hostname | github.com |
| expected-hostname | github.com |
| None | 60279d4097367e16897439d16d6bbe4180663db828c666eeed2656988ffe59f6 |
| turbo-cache-control | no-preview |
| go-import | github.com/igbinary/igbinary git https://github.com/igbinary/igbinary.git |
| octolytics-dimension-user_id | 555243 |
| octolytics-dimension-user_login | igbinary |
| octolytics-dimension-repository_id | 1237364 |
| octolytics-dimension-repository_nwo | igbinary/igbinary |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | true |
| octolytics-dimension-repository_parent_id | 155943 |
| octolytics-dimension-repository_parent_nwo | phadej/igbinary |
| octolytics-dimension-repository_network_root_id | 155943 |
| octolytics-dimension-repository_network_root_nwo | phadej/igbinary |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7c85641c598ad130c74f7bcc27f58575cac69551 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width