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.

Reply via email to