summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2020-02-12 17:40:50 +0000
committerSteve Hay <steve.m.hay@googlemail.com>2020-02-12 17:41:11 +0000
commit510a4b6a4e7b853c488ed6406503b4db5df212c6 (patch)
treec5acb5d86ce990cff2082bcad2423b74ba0b6864
parent15e9128cbe4a395e707161bae1f535d2d5467d20 (diff)
downloadperl-510a4b6a4e7b853c488ed6406503b4db5df212c6.tar.gz
fix panic caused by printf with %n with utf8 length magic
fix the reported issue with gh #17221 (cherry picked from commit 712e071bf4b91b0e2970bf38637b1a1b96dcc099)
-rw-r--r--sv.c11
-rw-r--r--t/op/sprintf2.t10
2 files changed, 20 insertions, 1 deletions
diff --git a/sv.c b/sv.c
index d650eafd51..648da9297b 100644
--- a/sv.c
+++ b/sv.c
@@ -13234,7 +13234,9 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
Perl_croak_nocontext(
"Missing argument for %%n in %s",
PL_op ? OP_DESC(PL_op) : "sv_vcatpvfn()");
- sv_setuv_mg(argsv, has_utf8 ? (UV)sv_len_utf8(sv) : (UV)len);
+ sv_setuv_mg(argsv, has_utf8
+ ? (UV)utf8_length((U8*)SvPVX(sv), (U8*)SvEND(sv))
+ : (UV)len);
}
goto done_valid_conversion;
}
@@ -13393,6 +13395,13 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
PL_op ? OP_DESC(PL_op) : "sv_vcatpvfn()");
}
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+ /* while we shouldn't set the cache, it may have been previously
+ set in the caller, so clear it */
+ MAGIC *mg = mg_find(sv, PERL_MAGIC_utf8);
+ if (mg)
+ magic_setutf8(sv,mg); /* clear UTF8 cache */
+ }
SvTAINT(sv);
#ifdef USE_LOCALE_NUMERIC
diff --git a/t/op/sprintf2.t b/t/op/sprintf2.t
index 569bd8053d..ea968790ce 100644
--- a/t/op/sprintf2.t
+++ b/t/op/sprintf2.t
@@ -1152,4 +1152,14 @@ foreach(
is sprintf("%.0f", $_), sprintf("%-.0f", $_), "special-case %.0f on $_";
}
+{
+ # gh #17221
+ my ($off1, $off2);
+ my $x = eval { sprintf "%n0%n\x{100}", $off1, $off2 };
+ is($@, "", "no exception");
+ is($x, "0\x{100}", "reasonable result");
+ is($off1, 0, "offset at start");
+ is($off2, 1, "offset after 0");
+}
+
done_testing();