Invalid input causes a segfault #1

Closed
cowens opened this Issue Sep 18, 2012 · 7 comments

Projects

None yet

3 participants

cowens commented Sep 18, 2012

When handed input that contains JSON without a container, perl segfaults.

#!/usr/bin/perl

use strict;
use warnings;

use JSON::SL;

my $p = JSON::SL->new;
$p->set_jsonpointer(["/^"]);

$p->feed("[ 5 ], [ 6 ]");
Owner

I've already found a fix. However note that this only works 'accidentally' (the comma should normally cause a parse error, but in this case it does not).

In any event segfaults are bad, so I'm fixing this and adding a test for it

Owner

btw the fix is in the latest commit

lamoz commented Nov 14, 2012

getting segfault here on perl 5.8.8 and JSON::SL 0.08 for

$p->feed(undef);

BTW, is there some way to find out that JSON stream is not properly ended ( bracket are not closed for instance ). I assumed that $p->fetch() should check this situation. Namely,

$p->feed('{ "report": [ "Hello, I will die in a mome...');
$p->fetch;

lives_ok. Is that a bug?

Tnanks for your work!

cowens commented Nov 14, 2012

lamoz, that is a feature. It allows you to break a file up into pieces. My code looks like this:

local $/ = \4096; #read 4k at a time
while (my $buf = <$fh>) {
    $p->feed($buf);
    while (my $part = $p->fetch) {
        #do stuff with $part
    }
}

It might be nice to be able to query the state of the parse though. Something like

my $fragment = $p->fragment; #remaining JSON that wasn't parsed
lamoz commented Nov 14, 2012

Oh I see you are using feed in void context. I just missed that kind of usage in docs. Thank you cowens!
So what about my first question ( without question mark, sorry)? Is there a way to know if JSON stream is syntactically complete? For example I'm reading 10GB file into DB:

$db->transaction(sub {
  while (my $buf = <$fh>) {
      $p->feed($buf);
      while (my $part = $p->fetch) {
          $db->insert( $part );
      }
  }
  $p->kind_of_finish(); # check for completeness, throw otherwise therefore rolling back transaction
});

In other words I want to import JSON file into DB and be sure that transaction is rolled back if file is truncated. $p->fragment from your example may not give me useful information in this case.

cowens commented Nov 14, 2012

Hmm, it does look like it is necessary to have an accessor like complete. It would return a true value if the parser thought the parse was done or a false value if the parse was still going or there was still JSON left to parse, but the parse was done.

So, the this code

my $p = JSON::SL->new;
$p->set_jsonpointer(["/^"]);
$p->feed("[ 1, 2");
say $p->complete;  #still parsing so 0
$p->feed("]");
say $p->complete; #we have everything we need, so 1
$p->feed(", [ 3, 4]");
say $p->complete; #oops, too much, back to 0

would produce

0
1
0

Alternately, we could have an end_of_data method or just pass undef to the feed method to indicate that there is no more data. In the case of an end_of_data method, I would suggest a true/false return value (i.e. it would work like complete above, but it could only be called once per parser's lifetime) and in the case of feed, I would suggest die'ing (since it already has a return value).

Owner

Closing this; refiling another issue which would be to the tune of allowing JSON::SL to handle multiple distinct trees

@mnunberg mnunberg closed this Dec 14, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment