Skip to content

Fix reference numbering for null values and value references#44

Open
alex-radch wants to merge 2 commits intoStringEpsilon:mainfrom
alex-radch:ReferencesFix
Open

Fix reference numbering for null values and value references#44
alex-radch wants to merge 2 commits intoStringEpsilon:mainfrom
alex-radch:ReferencesFix

Conversation

@alex-radch
Copy link

Summary

This PR fixes two bugs in reference handling during deserialization that caused incorrect reference resolution in complex serialized structures.

Problem

When deserializing PHP serialized strings containing references, the library would fail with errors like:

PhpSerializer exception
      PhpSerializerNET.DeserializationException: Exception encountered while trying to assign '255' to OrderLocalData.items. See inner exception for details.
       ---> PhpSerializerNET.DeserializationException: Exception encountered while trying to assign '255' to OrderItemLocalModel.comboInformation. See inner exception for details.
       ---> PhpSerializerNET.DeserializationException: Exception encountered while trying to assign '255' to ComboInformationLocalModel.comboId. See inner exception for details.
       ---> PhpSerializerNET.DeserializationException: Can not assign value "255" (at position 2935) to target type of LazyUuidFromString.

or

PhpSerializer exception
      PhpSerializerNET.DeserializationException: Exception encountered while trying to assign '11111111-1111-1111-1111-111111111111' to OrderLocalData.discountsInfo. See inner exception for details.
       ---> PhpSerializerNET.DeserializationException: Exception encountered while trying to assign '11111111-1111-1111-1111-111111111111' to DiscountsInfoLocalModel.discounts. See inner exception for details.
       ---> PhpSerializerNET.DeserializationException: Exception encountered while trying to assign '11111111-1111-1111-1111-111111111111' to DiscountLocalModel.selectivePositions. See inner exception for details.
       ---> PhpSerializerNET.DeserializationException: Can not assign value "11111111-1111-1111-1111-111111111111" (at position 404) to target type of LazyUuidFromString.

This happened because the reference numbering in the library did not match PHP's actual numbering scheme.

Root Causes

  1. Null values not counted in reference numbering
    PHP's serialize() counts ALL values in reference numbering, including null. The library was always assigning reference index 0 to null tokens instead of incrementing the counter.
  2. Value references (r:) not counted in reference numbering
    PHP has two types of references:
  • r: — value reference (object/value copy reference)
  • R: — variable reference (PHP &$var style reference)
    In PHP's serialization, value references are counted towards reference numbering, but variable references are not. The library was treating both the same way (not counting either).

Example

Given input with multiple value references like r:12 appearing several times before r:49, the library would resolve r:49 to the wrong token because each r:12 should have shifted the numbering by 1.

Changes

  • PhpTokenizer.cs: Modified null token creation to respect the countReference parameter
  • PhpTokenizer.cs: Split handling of r: and R: tokens — value references now increment the reference counter, variable references do not
  • ReferenceDeserializationTest.cs: Added two new tests specifically for this cases

Testing

  • All existing tests pass
  • Added 2 new tests specifically for these cases
  • Verified with real-world PHP serialized data containing multiple value references and null values

@StringEpsilon
Copy link
Owner

StringEpsilon commented Feb 11, 2026

Did you write the code with help of an LLM? The PR description very much reads so.
If so, have you checked that the code is not indirectly derivative of code from incompatible licenses?
I do not want to merge code that is potentially incompatible with the copyleft restrictions of the MPL 2.0.

@alex-radch
Copy link
Author

No, the code was written only by me, LLM helped me only with PR description.

When I was looking for a PHP de/serialization library for .NET, I found this one right away, so I didn't look at other implementations.
I had to manually check the counting algorithm using my examples.

I checked on 10+ different serialized strings from project I'm working on, but none of them have R: references (aka variable references).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants