how it interacts with other modules that hook ops.
- Adjust toke_scan_str logic to always show a positive effective length of
string source.
+ - Return undef from toke_scan_str if string was unterminated.
- Detect and croak if unwanted reallocation occurs during toke_scan_str.
- Avoid memory leak in toke_scan_str.
- Add MYMETA.{json,yml} to MANIFEST.SKIP and .gitignore.
if(SvPVX(PL_linestr) != old_pvx)
croak("PL_linestr reallocated during scan_str, "
"Devel::Declare can't continue");
+ if (!s)
+ return 0;
if (s <= base_s) {
s += SvCUR(line_copy);
sv_catsv(line_copy, PL_linestr);
OUTPUT:
RETVAL
-int
+SV*
toke_scan_str(int offset);
+ PREINIT:
+ int len;
CODE:
- RETVAL = dd_toke_scan_str(aTHX_ offset);
+ len = dd_toke_scan_str(aTHX_ offset);
+ RETVAL = len ? newSViv(len) : &PL_sv_undef;
OUTPUT:
RETVAL
returns, you can't rely on any content of the buffer preceding the end
of the string.
+If the string being scanned is not well formed (has no closing delimiter),
+C<toke_scan_str> returns C<undef>. In this case you cannot rely on the
+contents of the buffer.
+
=head4 C<get_lex_stuff>
This builtin returns what was matched by C<toke_scan_str>. To avoid segfaults,
Devel::Declare::clear_lex_stuff();
$linestr = $self->get_linestr();
- substr($linestr, $self->offset, $length) = '';
+ substr($linestr, $self->offset,
+ defined($length) ? $length : length($linestr)) = '';
$self->set_linestr($linestr);
return $proto;
my $content = Devel::Declare::get_lex_stuff();
Devel::Declare::clear_lex_stuff();
my $linestr = Devel::Declare::get_linestr();
- die "suprising len=$len" if $len <= 0;
+ die "surprising len=undef" if !defined($len);
+ die "surprising len=$len" if $len <= 0;
$content =~ s/(.)/sprintf("\\x{%x}", ord($1))/seg;
substr $linestr, $offset, $len, "(\"$content\")";
Devel::Declare::set_linestr($linestr);
--- /dev/null
+use warnings;
+use strict;
+
+use Devel::Declare ();
+use Test::More tests => 1;
+
+sub my_quote($) { $_[0] }
+
+sub my_quote_parser {
+ my($declarator, $offset) = @_;
+ $offset += Devel::Declare::toke_move_past_token($offset);
+ $offset += Devel::Declare::toke_skipspace($offset);
+ my $len = Devel::Declare::toke_scan_str($offset);
+ die "suprising len=$len" if defined $len;
+ die "toke_scan_str fail\n";
+}
+
+BEGIN {
+ Devel::Declare->setup_for(__PACKAGE__, {
+ my_quote => { const => \&my_quote_parser },
+ });
+}
+
+eval q{ my_quote[foo };
+is $@, "toke_scan_str fail\n";
+
+1;