Front page | perl.perl5.porters |
Postings from January 2016
[perl #127232] Storable -- segmentation fault
Thread Next
From:
Ben Bullock via RT
Date:
January 26, 2016 14:57
Subject:
[perl #127232] Storable -- segmentation fault
Message ID:
rt-4.0.18-28846-1453778559-150.127232-15-0@perl.org
On Mon Jan 11 10:28:38 2016, arc wrote:
> I think this needs JSON::XS or Cpanel::JSON::XS installed to trigger.
> Here's a reduction that demonstrates the same behaviour:
>
> use Cpanel::JSON::XS;
> use Storable qw<freeze thaw>;
> thaw( freeze( Cpanel::JSON::XS->new ) );
It doesn't require JSON::XS or Cpanel::JSON::XS to trigger. Any XS module with a blessed object will do, this has nothing whatsoever to do with Cpanel::JSON::XS, JSON::XS, or any other module except Storable. For example:
use JSON::Create;
thaw( freeze( JSON::Create->new ) );
$ perl storable.pl
./json-create-perl.c:1496: n_mallocs = -1
Segmentation fault (core dumped)
> But I don't think this is a bug that can be fixed in anything that p5p
> maintains. As far as I can tell, what's happening is as follows.
>
> First, an instance of Cpanel::JSON::XS is created. Under the hood, the
> XS parts of that module allocate an internal C structure to serve as
> the guts of that instance, and populate it appropriately. The instance
> returned does contain the relevant guts, but in a way that's hidden
> from callers who don't know where to look for it.
This is called encapsulation of objects.
> This instance is then frozen and re-thawed using Storable. Storable
> has no way to know about the hidden guts, so it reconstructs an object
> that it thinks is a copy of the original, but in fact doesn't contain
> the hidden guts.
Storable breaks the encapsulation of the object, then it copies that into a new object, then it blesses the copy into the original class, and you're suggesting that the author of JSON::XS or Cpanel::JSON::XS should do something about that chain of events?
> Then the thawed instance is discarded, so its destructor gets run. The
> destructor is also in XS, but it doesn't notice that the hidden guts
> are absent. When the destructor tries to look at the hidden guts, this
> causes a segfault.
All of which is an exceedingly good example of why it's not a great idea to break object encapsulation of Perl objects, then bless copies of the fake object got by coping the broken encapsulation into the class of the original object. I don't know exactly what kind of structure is used by JSON::XS, but typically it would be a pointer into memory which is represented as an IV within Perl.
> In addition, it's possible that it would be worth those modules being
> a little more defensive about the instances they're given (though I
> admit I haven't thought about this in detail).
The authors of JSON::XS and Cpanel::JSON::XS, and any other XS module should not be forced to defensively program against this kind of misbehaviour by Storable. There is no possible way that a C programmer, given a pointer into random memory (the IV from Perl), can check that it is a valid instance of anything whatsoever, since that always involves accessing the memory, and there is no guarantee that even accessing the memory is possible.
> Regardless, I think these changes should be taken up with the
> maintainers of the modules in question.
Storable is the module which should be "in question" here. JSON::XS and Cpanel::JSON::XS are not misbehaving at all and do not need to be modified. The misbehaviour is to break object encapsulation and then bless the broken copy of the object into a class it doesn't belong to.
---
via perlbug: queue: perl5 status: rejected
https://rt.perl.org/Ticket/Display.html?id=127232
Thread Next