Disallow sprintf's vector handling for non-integer formats.
Gisle Aas [Sun, 11 Dec 2005 18:14:24 +0000 (18:14 +0000)]
Avoids core dump for printf("%vs") and similar.

p4raw-id: //depot/perl@26321

sv.c
t/op/sprintf.t

diff --git a/sv.c b/sv.c
index fc2540d..f48e886 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -8103,12 +8103,14 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        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;
@@ -8123,7 +8125,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* 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) {
@@ -8139,7 +8143,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            goto string;
 
        case 's':
-           if (args && !vectorize) {
+           if (vectorize)
+               goto unknown;
+           if (args) {
                eptr = va_arg(*args, char*);
                if (eptr)
 #ifdef MACOS_TRADITIONAL
@@ -8170,7 +8176,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
 
        string:
-           vectorize = FALSE;
            if (has_precis && elen > precis)
                elen = precis;
            break;
@@ -8385,6 +8390,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        case 'e': case 'E':
        case 'f':
        case 'g': case 'G':
+           if (vectorize)
+               goto unknown;
 
            /* This is evil, but floating point is even more evil */
 
@@ -8417,7 +8424,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
 
            /* 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) :
@@ -8428,7 +8435,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                : 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
@@ -8586,8 +8592,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* 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;
@@ -8600,7 +8608,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
            else
                sv_setuv_mg(argsv, (UV)i);
-           vectorize = FALSE;
            continue;   /* not "break" */
 
            /* UNKNOWN */
index 4130a5a..d7f71e7 100755 (executable)
@@ -404,11 +404,18 @@ __END__
 >%*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<