diff --git a/Expat/Expat.xs b/Expat/Expat.xs index 7b7b5ec..6833a6b 100644 --- a/Expat/Expat.xs +++ b/Expat/Expat.xs @@ -2353,12 +2353,18 @@ XML_Do_External_Parse(parser, result) } else if (SvROK(result) && isGV(SvRV(result))) { /* Lexical filehandle (open my $fh) - a reference to a glob */ + IO *io = GvIOp((GV*)SvRV(result)); + if (!io) + croak("ExternEnt handler returned an unopened filehandle"); RETVAL = parse_stream(parser, - sv_2mortal(newRV_inc((SV*) GvIOp((GV*)SvRV(result))))); + sv_2mortal(newRV_inc((SV*) io))); } else if (isGV(result)) { + IO *io = GvIOp(result); + if (!io) + croak("ExternEnt handler returned an unopened filehandle"); RETVAL = parse_stream(parser, - sv_2mortal(newRV_inc((SV*) GvIOp(result)))); + sv_2mortal(newRV_inc((SV*) io))); } else if (SvPOK(result)) { STRLEN eslen; diff --git a/t/extern_ent_lexical_glob.t b/t/extern_ent_lexical_glob.t index 77d35ce..c3ed462 100644 --- a/t/extern_ent_lexical_glob.t +++ b/t/extern_ent_lexical_glob.t @@ -13,7 +13,7 @@ use File::Temp qw(tempfile); if ($] < 5.012) { plan skip_all => 'Lexical filehandles lack read() method before Perl 5.12'; } -plan tests => 2; +plan tests => 4; # Create a temporary entity file my ($fh, $entfile) = tempfile(UNLINK => 1, SUFFIX => '.ent'); @@ -46,3 +46,33 @@ XML is($@, '', 'parsing with lexical glob ExternEnt handler does not die'); is($chardata, 'hello world', 'character data from lexical glob entity is correct'); } + +# Test 3: unopened lexical glob croaks instead of segfaulting +{ + my $p = XML::Parser->new( + Handlers => { + ExternEnt => sub { + my $fh; # declared but never opened + return \$fh; # returns reference to undef scalar, not a glob + }, + }, + ); + + eval { $p->parse($xml) }; + ok($@, 'unopened lexical scalar ref dies gracefully'); +} + +# Test 4: unopened bare glob croaks instead of segfaulting +{ + no warnings 'once'; + my $p = XML::Parser->new( + Handlers => { + ExternEnt => sub { + return *UNOPENED_TEST_GLOB; # glob with no IO slot + }, + }, + ); + + eval { $p->parse($xml) }; + like($@, qr/unopened filehandle/i, 'bare unopened glob gives useful error'); +}