diff options
author | Tony Cook <tony@develop-help.com> | 2020-02-12 17:40:50 +0000 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2020-02-12 17:41:11 +0000 |
commit | 510a4b6a4e7b853c488ed6406503b4db5df212c6 (patch) | |
tree | c5acb5d86ce990cff2082bcad2423b74ba0b6864 | |
parent | 15e9128cbe4a395e707161bae1f535d2d5467d20 (diff) | |
download | perl-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.c | 11 | ||||
-rw-r--r-- | t/op/sprintf2.t | 10 |
2 files changed, 20 insertions, 1 deletions
@@ -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(); |