-
Notifications
You must be signed in to change notification settings - Fork 560
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 Perl_pp_formline pp_ctl.c:543 #15566
Comments
From @geeknikPerl v5.25.4-20-gc2f7c0b*, AFL, ASAN, libdislocator Unable to minimize the script as afl-tmin minimizes the crash away, so I've ==8600==ERROR: AddressSanitizer: heap-use-after-free on address 0x60f00000ebb0 is located 32 bytes inside of 168-byte region previously allocated by thread T0 here: SUMMARY: AddressSanitizer: heap-use-after-free /root/perl/pp_ctl.c:543 |
From @tonycozOn Sun Aug 28 23:29:59 2016, brian.carpenter@gmail.com wrote:
Simplifies to: my $x = '^@'; The compiled form is stored as magic on the SV ($x), when the chomp op pp_formline() then attempts to access the next op, but accesses freed Tony |
The RT System itself - Status changed from 'new' to 'open' |
From @tonycozOn Mon Aug 29 18:49:40 2016, tonyc wrote:
Here's a fix, though it might be a bit heavy-handed. Another possible fix would be to do the check only in FF_CHOP, and if the Tony |
From @tonycoz0001-perl-129125-avoid-freeing-the-compiled-format-too-ea.patchFrom 15c6e35b3bda690b323da54f6a94509cb9bc34e2 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Mon, 5 Sep 2016 12:07:23 +1000
Subject: (perl #129125) avoid freeing the compiled format too early
If the format SV also appeared as an argument, and the FF_CHOP
operator modified that argument, the magic and hence the compiled
format would be freed, and the next iteration of the processing
the compiled format would read freed memory.
---
pp_ctl.c | 22 +++++++++++++++++++++-
t/op/write.t | 11 ++++++++++-
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/pp_ctl.c b/pp_ctl.c
index 0d76286..13ced3f 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -464,7 +464,7 @@ S_rxres_free(pTHX_ void **rsp)
PP(pp_formline)
{
dSP; dMARK; dORIGMARK;
- SV * const tmpForm = *++MARK;
+ SV * tmpForm = *++MARK;
SV *formsv; /* contains text of original format */
U32 *fpc; /* format ops program counter */
char *t; /* current append position in target string */
@@ -491,6 +491,26 @@ PP(pp_formline)
STRLEN to_copy; /* how may bytes to append */
char trans; /* what chars to translate */
+ {
+ /* It's possible for tmpForm to be the same SV (or a magical alias)
+ to one of the arguments, if so, make a copy to avoid set magic
+ on the argument from releasing the compiled form.
+
+ If the copy is made the compiled form won't be cached.
+ */
+ SV **p;
+ bool copy_form = false;
+
+ for (p = MARK+1; p <= SP; ++p) {
+ if (*p == tmpForm || SvSMAGICAL(*p)) {
+ copy_form = true;
+ break;
+ }
+ }
+ if (copy_form || (SvGMAGICAL(tmpForm) && !sv_only_taint_gmagic(tmpForm)))
+ tmpForm = sv_mortalcopy(tmpForm);
+ }
+
mg = doparseform(tmpForm);
fpc = (U32*)mg->mg_ptr;
diff --git a/t/op/write.t b/t/op/write.t
index 93f70fa..1a2462c 100644
--- a/t/op/write.t
+++ b/t/op/write.t
@@ -98,7 +98,7 @@ for my $tref ( @NumTests ){
my $bas_tests = 21;
# number of tests in section 3
-my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 4 + 2 + 3 + 96 + 11 + 4;
+my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 5 + 2 + 3 + 96 + 11 + 4;
# number of tests in section 4
my $hmb_tests = 37;
@@ -1637,6 +1637,15 @@ printf ">%s<\n", ref $zamm;
print "$zamm->[0]\n";
EOP
+# [perl #129125] - detected by -fsanitize=address or valgrind
+# the compiled format would be freed when the format string was modified
+# by the chop operator
+fresh_perl_is(<<'EOP', "^", { stderr => 1 }, '#129125 - chop on format');
+my $x = '^@';
+formline$x=>$x;
+print $^A;
+EOP
+
# [perl #73690]
select +(select(RT73690), do {
--
2.1.4
|
From @tonycozOn Sun Sep 04 19:09:46 2016, tonyc wrote:
Attached. I don't *think* this is a security issue. Tony |
From @tonycoz0001-perl-129125-only-copy-the-form-data-if-needed.patchFrom 65318c6e5b5b8d347fcf04e35752a9f5dad8739f Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Mon, 24 Oct 2016 10:45:14 +1100
Subject: (perl #129125) only copy the form data if needed
Also, unlike my original patch this copies the formsv too, since
that is also stored in the magic, and is needed for presenting
literal text from the format.
---
pp_ctl.c | 18 ++++++++++++++++++
t/op/write.t | 19 ++++++++++++++++++-
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/pp_ctl.c b/pp_ctl.c
index 36b68b6..37ff886 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -478,6 +478,7 @@ PP(pp_formline)
U8 *source; /* source of bytes to append */
STRLEN to_copy; /* how may bytes to append */
char trans; /* what chars to translate */
+ bool copied_form = false; /* have we duplicated the form? */
mg = doparseform(tmpForm);
@@ -675,6 +676,23 @@ PP(pp_formline)
case FF_CHOP: /* (for ^*) chop the current item */
if (sv != &PL_sv_no) {
const char *s = chophere;
+ if (!copied_form &&
+ ((sv == tmpForm || SvSMAGICAL(sv))
+ || (SvGMAGICAL(tmpForm) && !sv_only_taint_gmagic(tmpForm))) ) {
+ /* sv and tmpForm are either the same SV, or magic might allow modification
+ of tmpForm when sv is modified, so copy */
+ SV *newformsv = sv_mortalcopy(formsv);
+ U32 *new_compiled;
+
+ f = SvPV_nolen(newformsv) + (f - SvPV_nolen(formsv));
+ Newx(new_compiled, mg->mg_len / sizeof(U32), U32);
+ memcpy(new_compiled, mg->mg_ptr, mg->mg_len);
+ SAVEFREEPV(new_compiled);
+ fpc = new_compiled + (fpc - (U32*)mg->mg_ptr);
+ formsv = newformsv;
+
+ copied_form = true;
+ }
if (chopspace) {
while (isSPACE(*s))
s++;
diff --git a/t/op/write.t b/t/op/write.t
index 93f70fa..3172681 100644
--- a/t/op/write.t
+++ b/t/op/write.t
@@ -98,7 +98,7 @@ for my $tref ( @NumTests ){
my $bas_tests = 21;
# number of tests in section 3
-my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 4 + 2 + 3 + 96 + 11 + 4;
+my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 6 + 2 + 3 + 96 + 11 + 4;
# number of tests in section 4
my $hmb_tests = 37;
@@ -1637,6 +1637,23 @@ printf ">%s<\n", ref $zamm;
print "$zamm->[0]\n";
EOP
+# [perl #129125] - detected by -fsanitize=address or valgrind
+# the compiled format would be freed when the format string was modified
+# by the chop operator
+fresh_perl_is(<<'EOP', "^", { stderr => 1 }, '#129125 - chop on format');
+my $x = '^@';
+formline$x=>$x;
+print $^A;
+EOP
+
+fresh_perl_is(<<'EOP', '<^< xx AA><xx ^<><>', { stderr => 1 }, '#129125 - chop on format, later values');
+my $x = '^< xx ^<';
+my $y = 'AA';
+formline $x => $x, $y;
+print "<$^A><$x><$y>";
+EOP
+
+
# [perl #73690]
select +(select(RT73690), do {
--
2.1.4
|
From @tonycozOn Sun, 23 Oct 2016 16:57:27 -0700, tonyc wrote:
Applied as 86191ae.
Everyone must agree, made it public. Tony |
@tonycoz - Status changed from 'open' to 'pending release' |
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#129125 (status was 'resolved')
Searchable as RT129125$
The text was updated successfully, but these errors were encountered: