Change 26339 by [EMAIL PROTECTED] on 2005/12/13 11:40:26 Add overflow check to EXPECT_NUMBER() used by sv_vcatpvfn(). sprintf() or printf() will now croak if any of the indexes and widths specified in the format string are too large.
Affected files ... ... //depot/perl/pod/perldiag.pod#424 edit ... //depot/perl/sv.c#1056 edit ... //depot/perl/t/op/sprintf.t#55 edit ... //depot/perl/t/op/sprintf2.t#6 edit Differences ... ==== //depot/perl/pod/perldiag.pod#424 (text) ==== Index: perl/pod/perldiag.pod --- perl/pod/perldiag.pod#423~26259~ 2005-12-05 08:19:35.000000000 -0800 +++ perl/pod/perldiag.pod 2005-12-13 03:40:26.000000000 -0800 @@ -1939,6 +1939,12 @@ internally--subject to loss of precision errors in subsequent operations. +=item Integer overflow in format string for %s + +(F) The indexes and widths specified in the format string of printf() +or sprintf() are too large. The numbers must not overflow the size of +integers for your architecture. + =item Integer overflow in version (F) Some portion of a version initialization is too large for the ==== //depot/perl/sv.c#1056 (text) ==== Index: perl/sv.c --- perl/sv.c#1055~26326~ 2005-12-12 02:41:04.000000000 -0800 +++ perl/sv.c 2005-12-13 03:40:26.000000000 -0800 @@ -7634,8 +7634,13 @@ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - while (isDIGIT(**pattern)) - var = var * 10 + (*(*pattern)++ - '0'); + var = *(*pattern)++ - '0'; + while (isDIGIT(**pattern)) { + I32 tmp = var * 10 + (*(*pattern)++ - '0'); + if (tmp < var) + Perl_croak(aTHX_ "Integer overflow in format string for %s", (PL_op ? OP_NAME(PL_op) : "sv_vcatpvfn")); + var = tmp; + } } return var; } ==== //depot/perl/t/op/sprintf.t#55 (xtext) ==== Index: perl/t/op/sprintf.t --- perl/t/op/sprintf.t#54~26326~ 2005-12-12 02:41:04.000000000 -0800 +++ perl/t/op/sprintf.t 2005-12-13 03:40:26.000000000 -0800 @@ -432,5 +432,5 @@ >%#b< >0< >0< >%#o< >0< >0< >%#x< >0< >0< ->%2918905856$v2d< >''< >< ->%*2918905856$v2d< >''< > UNINIT< +>%2147483647$v2d< >''< >< +>%*2147483647$v2d< >''< > UNINIT< ==== //depot/perl/t/op/sprintf2.t#6 (text) ==== Index: perl/t/op/sprintf2.t --- perl/t/op/sprintf2.t#5~26332~ 2005-12-12 07:24:06.000000000 -0800 +++ perl/t/op/sprintf2.t 2005-12-13 03:40:26.000000000 -0800 @@ -6,7 +6,7 @@ require './test.pl'; } -plan tests => 7 + 256; +plan tests => 283; is( sprintf("%.40g ",0.01), @@ -35,8 +35,15 @@ q(%n should not be able to modify read-only constants), ); -# check %NNN$ for range bounds, especially negative 2's complement +# check overflows +for (int(~0/2+1), ~0, ~0 + 1, ~0 + 2, "9999999999999999999") { + is(eval {sprintf "%${_}d", 0}, undef, "no sprintf result expected %${_}d"); + like($@, qr/^Integer overflow in format string for sprintf /, "overflow in sprintf"); + is(eval {printf "%${_}d\n", 0}, undef, "no printf result expected %${_}d"); + like($@, qr/^Integer overflow in format string for prtf /, "overflow in printf"); +} +# check %NNN$ for range bounds { my ($warn, $bad) = (0,0); local $SIG{__WARN__} = sub { @@ -47,9 +54,10 @@ $bad++ } }; - my $result = sprintf join('', map("%$_\$s%" . ~$_ . '$s', 1..20)), - qw(a b c d); - is($result, "abcd", "only four valid values"); + + my $fmt = join('', map("%$_\$s%" . int(~0/2+1-$_) . '$s', 1..20)); + my $result = sprintf $fmt, qw(a b c d); + is($result, "abcd", "only four valid values in $fmt"); is($warn, 36, "expected warnings"); is($bad, 0, "unexpected warnings"); } End of Patch.