Front page | perl.perl5.porters |
Postings from July 2013
Re: Asan help request
Thread Previous
|
Thread Next
From:
Nicholas Clark
Date:
July 25, 2013 08:19
Subject:
Re: Asan help request
Message ID:
20130725081938.GO3729@plum.flirble.org
On Wed, Jul 24, 2013 at 10:15:32PM -0700, Father Chrysostomos wrote:
>
> On Jul 24, 2013, at 8:41 PM, George Greer <perl@greerga.m-l.org> wrote:
> > The re/pat_rt_report.t failure symbolizes to:
> >
> > ==4709==ERROR: AddressSanitizer: heap-use-after-free on address 0x60400009ad24 at pc 0x7def00 bp 0x7fffd63a7b00 sp 0x7fffd63a7af8
> > WRITE of size 4 at 0x60400009ad24 thread T0
> > #0 0x7deeff in S_cleanup_regmatch_info_aux regexec.c:7625
> > #1 0x7181a2 in Perl_leave_scope scope.c:1097
> > #2 0x7c757f in Perl_regexec_flags regexec.c:2804
> > #3 0x65401c in Perl_pp_match pp_hot.c:1452
> > #4 0x5dd710 in Perl_runops_debug dump.c:2240
> > #5 0x498a4f in S_run_body perl.c:2496
> > #6 0x49837c in perl_run perl.c:2412
> > #7 0x443709 in main perlmain.c:114
> > #8 0x7f6ad45a3ea4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260
> > #9 0x44343c in _start ??:?
> > 0x60400009ad24 is located 20 bytes inside of 40-byte region [0x60400009ad10,0x60400009ad38)
> > freed by thread T0 here:
> > #0 0x435b32 in free ??:?
> > #1 0x5f72de in Perl_mg_free mg.c:561
> > #2 0x6a73ae in Perl_sv_free2 sv.c:6625
> > previously allocated by thread T0 here:
> > #0 0x435c93 in calloc ??:?
> > #1 0x5deded in Perl_safesyscalloc util.c:330
> >
> > Looks like it is trying to write to magic that has already been reaped as unused by leaving the scope.
>
> Can you figure out which commit caused it to start? (I would do it with smoke-me, but that would take weeks.)
As it's a heap error, valgrind also detects it.
The test case can be cut down to:
#!./miniperl
{
our $count;
for my $l (10, 100, 1000) {
$count = 0;
('a' x $l) =~ /(.*)(?{$count++})[bc]/;
}
}
__END__
which will pass/fail with just miniperl. Hence I ran
bisect.pl --target=miniperl --valgrind --end ffd41f30484d4125f0905a5234a77034ea4555ed ../padconst
and got
HEAD is now at 0f1ecde [perl #78194] Make re-evals copy PADTMPs
bad - non-zero exit from valgrind --error-exitcode=124 ./miniperl -Ilib ../padconst
0f1ecde5aca60059c25da9773eaa993cee2999ea is the first bad commit
commit 0f1ecde5aca60059c25da9773eaa993cee2999ea
Author: Father Chrysostomos <sprout@cpan.org>
Date: Thu Jun 27 18:11:48 2013 -0700
[perl #78194] Make re-evals copy PADTMPs
So that \$_ == \$_ will be true in "$foo$bar" =~ /(?{...})/.
Many ops return the same scalar each time, for efficiency; refgen (\)
knows about that and copies them, to hide the implementation detail,
but constructs, such as regular expression code blocks in this case,
need to do the same thing.
:100644 100644 3869d048958c179cc5ac35791991c1bdfa08ae90 87e749ba41e71d325ce018c924c3ad11f3414d51 M regexec.c
:040000 040000 d5d5ac479a24d2bf52b6296f01f9b40daa8962e6 fbce484d99432015a54ed83df38e1b2fdf0141d3 M t
bisect run success
I've checked by hand, and that commit is the problem:
commit 0f1ecde5aca60059c25da9773eaa993cee2999ea
Author: Father Chrysostomos <sprout@cpan.org>
Date: Thu Jun 27 18:11:48 2013 -0700
[perl #78194] Make re-evals copy PADTMPs
So that \$_ == \$_ will be true in "$foo$bar" =~ /(?{...})/.
Many ops return the same scalar each time, for efficiency; refgen (\)
knows about that and copies them, to hide the implementation detail,
but constructs, such as regular expression code blocks in this case,
need to do the same thing.
diff --git a/regexec.c b/regexec.c
index 3869d04..87e749b 100644
--- a/regexec.c
+++ b/regexec.c
@@ -2135,6 +2135,9 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringar
/* see how far we have to get to not match where we matched before */
reginfo->till = startpos+minend;
+ if (prog->extflags & RXf_EVAL_SEEN && SvPADTMP(sv) && !IS_PADGV(sv))
+ reginfo->sv = sv_mortalcopy(sv), SvTEMP_off(reginfo->sv);
+
/* reserve next 2 or 3 slots in PL_regmatch_state:
* slot N+0: may currently be in use: skip it
* slot N+1: use for regmatch_info_aux struct
diff --git a/t/re/rxcode.t b/t/re/rxcode.t
index 2845b7b..19a859b 100644
--- a/t/re/rxcode.t
+++ b/t/re/rxcode.t
@@ -92,7 +92,6 @@ cmp_ok( scalar(@var), '==', 0, '..still nothing pushed (packag
is eval { "a" =~ /a++(?{})+$x/x } || $@, '1', '/a++(?{})+$code_block/'
}
-$::TODO = "not fixed yet";
# [perl #78194] $_ in code block aliasing op return values
"$_" =~ /(?{ is \$_, \$_,
'[perl #78194] \$_ == \$_ when $_ aliases "$x"' })/;
Happening to look at it, I think it would be clearer to write this:
if (prog->extflags & RXf_EVAL_SEEN && SvPADTMP(sv) && !IS_PADGV(sv))
reginfo->sv = sv_mortalcopy(sv), SvTEMP_off(reginfo->sv);
as this
if (prog->extflags & RXf_EVAL_SEEN && SvPADTMP(sv) && !IS_PADGV(sv)) {
reginfo->sv = sv_mortalcopy(sv);
SvTEMP_off(reginfo->sv);
}
as I don't think that using a comma operator in void context just to avoid
needing braces is really worth it. It doesn't feel like idiomatic C.
Nicholas Clark
Thread Previous
|
Thread Next