develooper Front page | perl.perl5.porters | Postings from January 2016

[perl #127232] Storable -- segmentation fault

Thread Next
Ben Bullock via RT
January 26, 2016 14:57
[perl #127232] Storable -- segmentation fault
Message ID:
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
    ./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

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About