Change 29864 by [EMAIL PROTECTED] on 2007/01/17 23:29:13

        Integrate:
        [ 24912]
        Same fix, for the test, now.
        
        [ 26321]
        Disallow sprintf's vector handling for non-integer formats.
        Avoids core dump for printf("%vs") and similar.
        
        [ 26326]
        Drop "v" prefix from sprintf("%vd", $^V).
        
        The sprintf documentation has this example:
        
           printf "version is v%vd\n", $^V;
        
        and it printed 'version is vv5.9.3\n'.
        
        [ 26327]
        Oops, change 26326 broke t/run/switches.t
        Reverting change 24912 fixes it.
        
        [ 26339]
        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.
        
        [ 26342]
        Remove tests that were not portable to 64bit ints.

Affected files ...

... //depot/maint-5.8/perl/pod/perldiag.pod#93 integrate
... //depot/maint-5.8/perl/sv.c#288 integrate
... //depot/maint-5.8/perl/t/op/sprintf.t#16 edit
... //depot/maint-5.8/perl/t/op/sprintf2.t#5 integrate
... //depot/maint-5.8/perl/t/run/switches.t#6 integrate

Differences ...

==== //depot/maint-5.8/perl/pod/perldiag.pod#93 (text) ====
Index: perl/pod/perldiag.pod
--- perl/pod/perldiag.pod#92~29799~     2007-01-13 15:25:00.000000000 -0800
+++ perl/pod/perldiag.pod       2007-01-17 15:29:13.000000000 -0800
@@ -1911,6 +1911,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 Internal disaster in regex; marked by <-- HERE in m/%s/
 
 (P) Something went badly wrong in the regular expression parser.

==== //depot/maint-5.8/perl/sv.c#288 (text) ====
Index: perl/sv.c
--- perl/sv.c#287~29860~        2007-01-17 14:08:43.000000000 -0800
+++ perl/sv.c   2007-01-17 15:29:13.000000000 -0800
@@ -7509,8 +7509,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;
 }
@@ -7931,12 +7936,14 @@
        if (*q == '%') {
            eptr = q++;
            elen = 1;
+           if (vectorize) {
+               c = '%';
+               goto unknown;
+           }
            goto string;
        }
 
-       if (vectorize)
-           argsv = vecsv;
-       else if (!args) {
+       if (!vectorize && !args) {
            if (efix) {
                const I32 i = efix-1;
                argsv = (i >= 0 && i < svmax) ? svargs[i] : &PL_sv_undef;
@@ -7951,7 +7958,9 @@
            /* STRINGS */
 
        case 'c':
-           uv = (args && !vectorize) ? va_arg(*args, int) : SvIVx(argsv);
+           if (vectorize)
+               goto unknown;
+           uv = (args) ? va_arg(*args, int) : SvIVx(argsv);
            if ((uv > 255 ||
                 (!UNI_IS_INVARIANT(uv) && SvUTF8(sv)))
                && !IN_BYTES) {
@@ -7967,7 +7976,9 @@
            goto string;
 
        case 's':
-           if (args && !vectorize) {
+           if (vectorize)
+               goto unknown;
+           if (args) {
                eptr = va_arg(*args, char*);
                if (eptr)
 #ifdef MACOS_TRADITIONAL
@@ -8015,7 +8026,6 @@
                is_utf8 = TRUE;
 
        string:
-           vectorize = FALSE;
            if (has_precis && elen > precis)
                elen = precis;
            break;
@@ -8258,6 +8268,8 @@
        case 'e': case 'E':
        case 'f':
        case 'g': case 'G':
+           if (vectorize)
+               goto unknown;
 
            /* This is evil, but floating point is even more evil */
 
@@ -8290,7 +8302,7 @@
            }
 
            /* now we need (long double) if intsize == 'q', else (double) */
-           nv = (args && !vectorize) ?
+           nv = (args) ?
 #if LONG_DOUBLESIZE > DOUBLESIZE
                intsize == 'q' ?
                    va_arg(*args, long double) :
@@ -8301,7 +8313,6 @@
                : SvNVx(argsv);
 
            need = 0;
-           vectorize = FALSE;
            if (c != 'e' && c != 'E') {
                i = PERL_INT_MIN;
                /* FIXME: if HAS_LONG_DOUBLE but not USE_LONG_DOUBLE this
@@ -8464,8 +8475,10 @@
            /* SPECIAL */
 
        case 'n':
+           if (vectorize)
+               goto unknown;
            i = SvCUR(sv) - origlen;
-           if (args && !vectorize) {
+           if (args) {
                switch (intsize) {
                case 'h':       *(va_arg(*args, short*)) = i; break;
                default:        *(va_arg(*args, int*)) = i; break;
@@ -8478,7 +8491,6 @@
            }
            else
                sv_setuv_mg(argsv, (UV)i);
-           vectorize = FALSE;
            continue;   /* not "break" */
 
            /* UNKNOWN */

==== //depot/maint-5.8/perl/t/op/sprintf.t#16 (xtext) ====
Index: perl/t/op/sprintf.t
--- perl/t/op/sprintf.t#15~26697~       2006-01-07 05:18:30.000000000 -0800
+++ perl/t/op/sprintf.t 2007-01-17 15:29:13.000000000 -0800
@@ -241,6 +241,7 @@
 >%+vd<      >chr(1)<      >+1<
 >%#vd<      >chr(1)<      >1<
 >%vd<       >"\01\02\03"< >1.2.3<
+>%vd<       >v1.2.3<      >1.2.3<
 >%v.3d<     >"\01\02\03"< >001.002.003<
 >%0v3d<     >"\01\02\03"< >001.002.003<
 >%-v3d<     >"\01\02\03"< >1  .2  .3  <
@@ -406,11 +407,18 @@
 >%*2*2$d<      >[12, 3]<       >%*2*2$d INVALID<
 >%*2$1d<       >[12, 3]<       >%*2$1d INVALID<
 >%0v2.2d<      >''<    ><
->%vc,%d<       >[63, 64, 65]<  >?,64<
+>%vc,%d<       >[63, 64, 65]<  >%vc,63 INVALID<
+>%v%,%d<       >[63, 64, 65]<  >%v%,63 INVALID<
 >%vd,%d<       >[1, 2, 3]<     >49,2<
->%vf,%d<       >[1, 2, 3]<     >1.000000,2<
+>%vf,%d<       >[1, 2, 3]<     >%vf,1 INVALID<
+>%vF,%d<       >[1, 2, 3]<     >%vF,1 INVALID<
+>%ve,%d<       >[1, 2, 3]<     >%ve,1 INVALID<
+>%vE,%d<       >[1, 2, 3]<     >%vE,1 INVALID<
+>%vg,%d<       >[1, 2, 3]<     >%vg,1 INVALID<
+>%vG,%d<       >[1, 2, 3]<     >%vG,1 INVALID<
 >%vp<  >''<    >%vp INVALID<
->%vs,%d<       >[1, 2, 3]<     >1,2<
+>%vn<  >''<    >%vn INVALID<
+>%vs,%d<       >[1, 2, 3]<     >%vs,1 INVALID<
 >%v_<  >''<    >%v_ INVALID<
 >%v#x< >''<    >%v#x INVALID<
 >%v02x<        >"foo\012"<     >66.6f.6f.0a<
@@ -423,5 +431,5 @@
 >%#b<          >0<     >0<
 >%#o<          >0<     >0<
 >%#x<          >0<     >0<
->%2918905856$v2d<      >''<    ><
->%*2918905856$v2d<     >''<    > UNINIT<
+>%2147483647$v2d<      >''<    ><
+>%*2147483647$v2d<     >''<    > UNINIT<

==== //depot/maint-5.8/perl/t/op/sprintf2.t#5 (text) ====
Index: perl/t/op/sprintf2.t
--- perl/t/op/sprintf2.t#4~26333~       2005-12-12 07:40:56.000000000 -0800
+++ perl/t/op/sprintf2.t        2007-01-17 15:29:13.000000000 -0800
@@ -6,7 +6,7 @@
     require './test.pl';
 }   
 
-plan tests => 7 + 256;
+plan tests => 275;
 
 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, "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%" . ((1 << 31)-$_) . '$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