This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Perl_sv_vcatpvfn_flags: use quick concat for %.0f
authorDavid Mitchell <davem@iabyn.com>
Fri, 19 May 2017 14:45:51 +0000 (15:45 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 7 Jun 2017 08:11:03 +0000 (09:11 +0100)
Most floating-point formats now use the quick concat path. But the
"%.0f" shortcut was accidentally bypassing that path. This commit fixes
that.

sv.c

diff --git a/sv.c b/sv.c
index 2e5b9fc..73e58e5 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -11802,6 +11802,11 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
     /* no matter what, this is a string now */
     (void)SvPV_force_nomg(sv, origlen);
 
+    /* the code that scans for flags etc following a % relies on
+     * a '\0' being present to avoid falling off the end. Ideally that
+     * should be fixed */
+    assert(pat[patlen] == '\0');
+
     /* special-case "", "%s", and "%-p" (SVf - see below) */
     if (patlen == 0) {
        if (svmax && ckWARN(WARN_REDUNDANT))
@@ -12724,7 +12729,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
             /* special-case "%.0f" */
             if (can_be_special && c == 'f' && !precis) {
                 if ((eptr = F0convert(nv, ebuf + sizeof ebuf, &elen)))
-                    break;
+                    goto float_concat_no_utf8;
             }
 
             /* Determine the buffer size needed for the various
@@ -12879,7 +12884,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                    /* May return an empty string for digits==0 */
                    if (*PL_efloatbuf) {
                        elen = strlen(PL_efloatbuf);
-                       goto float_converted;
+                       goto float_concat;
                    }
                 }
            }
@@ -12965,7 +12970,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 GCC_DIAG_RESTORE;
            }
 
-       float_converted:
+         float_concat:
            eptr = PL_efloatbuf;
 
             /* Since floating-point formats do their own formatting and
@@ -12973,12 +12978,6 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
              * loop which handles appending eptr to sv, and do our own
              * stripped-down version */
 
-            assert(!zeros);
-            assert(!esignlen);
-            assert(!vectorize);
-            assert(elen);
-            assert(elen >= width);
-
             /* floating-point formats only get is_utf8 if the radix point
              * is utf8. All other characters in the string are < 128
              * and so can be safely appended to both a non-utf8 and utf8
@@ -12989,6 +12988,15 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 has_utf8 = TRUE;
             }
 
+         float_concat_no_utf8:
+
+            assert(!zeros);
+            assert(!esignlen);
+            assert(!vectorize);
+            assert(elen);
+            assert(elen >= width);
+
+
             {
                 /* unrolled Perl_sv_catpvn */
                 STRLEN need = elen + SvCUR(sv) + 1;