-
Notifications
You must be signed in to change notification settings - Fork 550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
heap-use-after-free in Perl_sv_catpvn_flags (sv.c:5455) #15691
Comments
From @geeknikTriggered with Perl v5.25.7 (v5.25.6-134-g11327fa) and AFL+ASAN. Doesn't perl -e '$^X^=r'==2379==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300000eec1 is located 1 bytes inside of 17-byte region [0x60300000eec0, previously allocated by thread T0 here: SUMMARY: AddressSanitizer: heap-use-after-free ??:0 __asan_memmove |
From @tonycozCreated by @tonycozThe call to Perl_sv_catpvn_flags() from Perl_do_vop() can use memory Encountered as crashes in warnings.pm as it updated the warnings tony@mars:.../git/perl$ ./perl -Ilib -e '$x = "UUUUUUUUUU\325UUUUUU\0"; $y = "\0\0\0\0\0\0\0\0\0\0\200\0\0\0\0\0\0"; $x |= $y'==1334==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300000e3f1 at pc 0x8afbc5 bp 0x7ffe50e25e40 sp 0x7ffe50e25e38 0x60300000e3f1 is located 17 bytes inside of 20-byte region [0x60300000e3e0,0x60300000e3f4) previously allocated by thread T0 here: SUMMARY: AddressSanitizer: heap-use-after-free /home/tony/dev/perl/git/perl/sv.c:5455 Perl_sv_catpvn_flags This seems to have been introduced by While this change introduce the problem, I'm not inclined to blame the I'm not sure of the correct fix here. The simplest and least fragile is probably a mortal copy of the "left" Perl Info
|
From @cpansproutOn Tue Nov 01 21:18:01 2016, tonyc wrote:
Wouldn’t it be simpler to grow the scalar by the amount that is about to be appended before appending it (and, of course, update the pointer in between)? -- Father Chrysostomos |
The RT System itself - Status changed from 'new' to 'open' |
From @tonycozOn Wed Nov 02 15:43:05 2016, sprout wrote:
My main problem is that it's fragile - it broke this time because 7fdc4f5 It turns out there's a simple non-fragile fix, attached. Tony |
From @tonycoz0001-perl-129997-avoid-sv_catpvn-in-do_vop-when-unneeded.patchFrom e6cb268e1f28cb9bc8ce4c21c554fd155c13d90a Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Thu, 3 Nov 2016 16:07:35 +1100
Subject: (perl #129997) avoid sv_catpvn() in do_vop() when unneeded
---
doop.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/doop.c b/doop.c
index 5525c47..bc23c9e 100644
--- a/doop.c
+++ b/doop.c
@@ -1218,8 +1218,17 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
len = lensave;
if (rightlen > len)
sv_catpvn_nomg(sv, rsave + len, rightlen - len);
- else if (leftlen > (STRLEN)len)
- sv_catpvn_nomg(sv, lsave + len, leftlen - len);
+ else if (leftlen > (STRLEN)len) {
+ if (sv == left) {
+ /* sv_catpvn() might move the source from under us,
+ and the data is already in place, just adjust to
+ include it */
+ SvCUR_set(sv, leftlen);
+ *SvEND(sv) = '\0';
+ }
+ else
+ sv_catpvn_nomg(sv, lsave + len, leftlen - len);
+ }
else
*SvEND(sv) = '\0';
break;
--
2.1.4
|
From @tonycozOn Tue, 01 Nov 2016 12:39:09 -0700, brian.carpenter@gmail.com wrote:
As Brian pointed out in IRC, this is the same issue as 129997, so I've merged This *is* potentially a security issue, but it's only present in a development Fixed by dc529e6. Tony |
@tonycoz - Status changed from 'new' to 'pending release' |
From @iabynOn Wed, Nov 02, 2016 at 10:11:33PM -0700, Tony Cook via RT wrote:
Hi Tony, I didn't spot this while working on the same issue (I saw ASAN I fixed up the rhs-longer branch in addition to the lhs-longer branch. Secondly, rather than testing that sv == left etc, I checked whether the Do you have any opinion whether I should apply a reworked version of this Inline Patchdiff --git a/doop.c b/doop.c
index 5525c47..1aea1ea 100644
--- a/doop.c
+++ b/doop.c
@@ -1216,12 +1216,19 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
*dc++ = *lc++ | *rc++;
mop_up:
len = lensave;
- if (rightlen > len)
- sv_catpvn_nomg(sv, rsave + len, rightlen - len);
- else if (leftlen > (STRLEN)len)
- sv_catpvn_nomg(sv, lsave + len, leftlen - len);
- else
- *SvEND(sv) = '\0';
+ if (rightlen > len) {
+ if (dc == rc)
+ SvCUR(sv) = rightlen;
+ else
+ sv_catpvn_nomg(sv, rsave + len, rightlen - len);
+ }
+ else if (leftlen > (STRLEN)len) {
+ if (dc == lc)
+ SvCUR(sv) = leftlen;
+ else
+ sv_catpvn_nomg(sv, lsave + len, leftlen - len);
+ }
+ *SvEND(sv) = '\0';
-- More than any other time in history, mankind faces a crossroads. One path |
From @demerphqOn 8 November 2016 at 10:54, Dave Mitchell <davem@iabyn.com> wrote:
Leaving aside the patch to doop.c it looks to me like sv_catpvn in @@ -5507,7 +5497,7 @@ void PERL_ARGS_ASSERT_SV_CATPVN_FLAGS; |
From @tonycozOn Tue, 08 Nov 2016 01:54:59 -0800, davem wrote:
It won't do any harm, though as you say it can't happen with the current I don't think Perl_do_vop() can currently be called with sv == right,
It won't do any harm. Tony |
From @tonycozOn Tue, 08 Nov 2016 02:17:28 -0800, demerphq wrote:
That would break the check done on the next line, which appears to be STRLEN len; adjusts sstr to point at the new buffer for sv if that moves. This could have been extended to fix this particular problem, instead of: if (sstr == dstr) something like: if (sstr >= dstr && sstr + slen <= dstr + SvLEN(sv)) Tony |
From @iabynOn Tue, Nov 08, 2016 at 04:36:46PM -0800, Tony Cook via RT wrote:
Some of the bitwise tests under t/lib/warnings do: IIRC its ones testing -- |
From @iabynOn Tue, Nov 08, 2016 at 09:54:25AM +0000, Dave Mitchell wrote:
I've now applied it as v5.25.6-185-g392582f -- |
From @khwilliamsonThank you for filing this report. You have helped make Perl better. With the release today of Perl 5.26.0, this and 210 other issues have been Perl 5.26.0 may be downloaded via: If you find that the problem persists, feel free to reopen this ticket. |
@khwilliamson - Status changed from 'pending release' to 'resolved' |
Migrated from rt.perl.org#129995 (status was 'resolved')
Searchable as RT129995$
The text was updated successfully, but these errors were encountered: