This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: [perl #119425] strftime with %p
authorKarl Williamson <khw@cpan.org>
Fri, 6 Jun 2014 19:04:55 +0000 (13:04 -0600)
committerKarl Williamson <khw@cpan.org>
Sat, 7 Jun 2014 16:24:58 +0000 (10:24 -0600)
In a locale in which there is no a.m. nor p.m. indicator, a format with
only %p in it would print %p instead of nothing.

ext/POSIX/POSIX.xs
lib/locale.t

index 085c06b..7976334 100644 (file)
@@ -1737,6 +1737,7 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
     CODE:
        {
            char *buf;
+            SV *sv;
 
             /* allowing user-supplied (rather than literal) formats
              * is normally frowned upon as a potential security risk;
@@ -1744,14 +1745,23 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
             GCC_DIAG_IGNORE(-Wformat-nonliteral);
            buf = my_strftime(SvPV_nolen(fmt), sec, min, hour, mday, mon, year, wday, yday, isdst);
             GCC_DIAG_RESTORE;
+            sv = sv_newmortal();
            if (buf) {
-               SV *const sv = sv_newmortal();
                sv_usepvn_flags(sv, buf, strlen(buf), SV_HAS_TRAILING_NUL);
                if (SvUTF8(fmt)) {
                    SvUTF8_on(sv);
                }
-               ST(0) = sv;
-           }
+            }
+            else {  /* We can't distinguish between errors and just an empty
+                     * return; in all cases just return an empty string */
+                SvUPGRADE(sv, SVt_PV);
+                SvPV_set(sv, (char *) "");
+                SvPOK_on(sv);
+                SvCUR_set(sv, 0);
+                SvLEN_set(sv, 0);   /* Won't attempt to free the string when sv
+                                       gets destroyed */
+            }
+            ST(0) = sv;
        }
 
 void
index e9ed1a8..d0adbd8 100644 (file)
@@ -1665,6 +1665,7 @@ foreach my $Locale (@Locale) {
     my $ok16;
     my $ok17;
     my $ok18;
+    my $ok19;
 
     my $c;
     my $d;
@@ -1675,6 +1676,8 @@ foreach my $Locale (@Locale) {
     my $i;
     my $j;
 
+    my @times = CORE::localtime();
+
     if (! $is_utf8_locale) {
         use locale;
 
@@ -1733,6 +1736,7 @@ foreach my $Locale (@Locale) {
             $ok17 = "1.5:1.25" eq sprintf("%g:%g", $h, $i);
         }
         $ok18 = $j eq sprintf("%g:%g", $h, $i);
+        $ok19 = POSIX::strftime("%p",@times) ne "%p"; # [perl #119425]
     }
     else {
         use locale ':not_characters';
@@ -1811,6 +1815,7 @@ foreach my $Locale (@Locale) {
             $ok17 = "1.5:1.25" eq sprintf("%g:%g", $h, $i);
         }
         $ok18 = $j eq sprintf("%g:%g", $h, $i);
+        $ok19 = POSIX::strftime("%p",@times) ne "%p"; # [perl #119425]
     }
 
     report_result($Locale, ++$locales_test_number, $ok1);
@@ -1890,6 +1895,9 @@ foreach my $Locale (@Locale) {
     report_result($Locale, ++$locales_test_number, $ok18);
     $test_names{$locales_test_number} = 'Verify that a sprintf of a number back within locale scope uses locale radix';
 
+    report_result($Locale, ++$locales_test_number, $ok19);
+    $test_names{$locales_test_number} = 'Verify that strftime doesn\'t return "%p" in locales where %p is empty';
+
     debug "# $first_f_test..$locales_test_number: \$f = $f, \$g = $g, back to locale = $Locale\n";
 
     # Does taking lc separately differ from taking