From: SADAHIRO Tomoyuki Date: Sun, 21 May 2006 19:33:21 +0000 (+0900) Subject: Re: [perl #39126] possible memory related bug when using sprintf with an utf-8 encode... X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cc61b222958c07650542902d07ee4c04d4d76213;p=p5sagit%2Fp5-mst-13.2.git Re: [perl #39126] possible memory related bug when using sprintf with an utf-8 encoded format-string and iso-8859-1 encoded string variables. Message-Id: <20060521193259.81E5.BQW10602@nifty.com> with test tweaks further suggested by the same p4raw-id: //depot/perl@28328 --- diff --git a/sv.c b/sv.c index d6e307d..3653b86 100644 --- a/sv.c +++ b/sv.c @@ -9338,27 +9338,29 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV continue; /* not "break" */ } - /* calculate width before utf8_upgrade changes it */ + if (is_utf8 != has_utf8) { + if (is_utf8) { + if (SvCUR(sv)) + sv_utf8_upgrade(sv); + } + else { + const STRLEN old_elen = elen; + SV * const nsv = sv_2mortal(newSVpvn(eptr, elen)); + sv_utf8_upgrade(nsv); + eptr = SvPVX_const(nsv); + elen = SvCUR(nsv); + + if (width) { /* fudge width (can't fudge elen) */ + width += elen - old_elen; + } + is_utf8 = TRUE; + } + } + have = esignlen + zeros + elen; if (have < zeros) Perl_croak_nocontext(PL_memory_wrap); - if (is_utf8 != has_utf8) { - if (is_utf8) { - if (SvCUR(sv)) - sv_utf8_upgrade(sv); - } - else { - SV * const nsv = sv_2mortal(newSVpvn(eptr, elen)); - sv_utf8_upgrade(nsv); - eptr = SvPVX_const(nsv); - elen = SvCUR(nsv); - } - SvGROW(sv, SvCUR(sv) + elen + 1); - p = SvEND(sv); - *p = '\0'; - } - need = (have > width ? have : width); gap = need - have; diff --git a/t/op/sprintf2.t b/t/op/sprintf2.t index 7544705..81450ce 100644 --- a/t/op/sprintf2.t +++ b/t/op/sprintf2.t @@ -6,7 +6,7 @@ BEGIN { require './test.pl'; } -plan tests => 275; +plan tests => 280; is( sprintf("%.40g ",0.01), @@ -18,13 +18,14 @@ is( sprintf("%.40f", 0.01)." ", q(the sprintf "%.f" optimization) ); -{ - chop(my $utf8_format = "%-3s\x{100}"); - is( - sprintf($utf8_format, "\xe4"), - "\xe4 ", - q(width calculation under utf8 upgrade) - ); + +# cases of $i > 1 are against [perl #39126] +for my $i (1, 5, 10, 20, 50, 100) { + chop(my $utf8_format = "%-*s\x{100}"); + my $string = "\xB4"x$i; # latin1 ACUTE or ebcdic COPYRIGHT + my $expect = $string." "x$i; # followed by 2*$i spaces + is(sprintf($utf8_format, 3*$i, $string), $expect, + "width calculation under utf8 upgrade, length=$i"); } # Used to mangle PL_sv_undef