Skip Menu |

This queue is for tickets about the Data-Transform-ExplicitMetadata CPAN distribution.

Report information
The Basics
Id: 130362
Status: resolved
Priority: 0/
Queue: Data-Transform-ExplicitMetadata

People
Owner: BRUMMETT [...] cpan.org
Requestors: SREZIC [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.08
Fixed in: (no value)



Subject: Wrong encoding in presence of overloading
If a data structure has objects with overloaded stringification, then encode() may create wrong data structures which would fail to correctly decode() to the same data structure again. Attached are two test scripts showing the problem. The first test case in data-transform-explicitmetadata.t has a data structure with a boolean and a Math::BigInt object --- and both happen to stringify to the same value "1". The decoded data structure happens to have two boolean objects. The second test case in the same file also fails. Explanation here is somewhat more difficult, but I think it's because Math::BigInt objects have an inner Math::BigInt::Calc object which also implements overloaded stringification. The second test file data-transform-explicitmetadata-overload.t shows the problem using self-defined classes. I think the problem is that the $self hash in encode() uses $value as the key. This is fine if the object's class does not have its own stringification (in this case it stringifies to a unique value like Foo=HASH(0x13da220)), but may fail if it doesn't. Probably the problem can be fixed by using $refaddr instead of $value here (did not test it here, but I have similar code where this approach worked).
Subject: data-transform-explicitmetadata-overload.t
use strict; use warnings; use Test::More; use Test::Deep; use Data::Transform::ExplicitMetadata qw(encode decode); { package Class1; use overload '""' => sub { $_[0]->{value} }; sub new { my($class, $value) = @_; bless { value => $value }, $class } } { package Class2; use overload '""' => sub { $_[0]->{v} }; sub new { my($class, $value) = @_; bless { v => $value }, $class } } { my $ds = [ Class1->new(1), Class2->new(1), ]; cmp_deeply decode(encode($ds)), $ds; } done_testing;
Subject: data-transform-explicitmetadata.t
use strict; use warnings; use Test::More; use Test::Deep; use Data::Transform::ExplicitMetadata qw(encode decode); use Math::BigInt; use boolean; { my $ds = [true, Math::BigInt->new("1")]; cmp_deeply decode(encode($ds)), $ds, 'two objects stringfying to the same value (1)'; } { my $ds = [Math::BigInt->new("1234")]; cmp_deeply decode(encode($ds)), $ds, 'probably inner object stringifies to the same value like the outer object'; } done_testing;
On Fri Aug 23 08:13:35 2019, SREZIC wrote: Show quoted text
> If a data structure has objects with overloaded stringification, then > encode() may create wrong data structures which would fail to > correctly decode() to the same data structure again. > > [...] > > I think the problem is that the $self hash in encode() uses $value as > the key. This is fine if the object's class does not have its own > stringification (in this case it stringifies to a unique value like > Foo=HASH(0x13da220)), but may fail if it doesn't. Probably the problem > can be fixed by using $refaddr instead of $value here (did not test it > here, but I have similar code where this approach worked).
You were right about the problem and the fix. I've just uploaded v0.09 which fixes this issue.