The patch for APR trunk
* supposedly fixes bugs interpreting the apr_snprintf() retcode on
Windows (untested)
* adds a test for short input buffer (tested on Unix, anticipated
different retcode on Windows supposedly handled)
* adds weasel words to the apr_strftime() documentation since Windows
has had different possibilities on what happens to a short input
buffer (either whatever strftime() does on overflow or what the
extra-strftime function does on overflow)

Does anyone want to try it on Windows and/or eyeball it?

For 2.0, we can pick a specific behavior to use in all platforms*cases.
Index: time/win32/timestr.c
===================================================================
--- time/win32/timestr.c        (revision 1078737)
+++ time/win32/timestr.c        (working copy)
@@ -124,6 +124,7 @@
 
 #ifndef _WIN32_WCE
 
+/* Handle extra format strings which aren't supported by Win32 strftime() */
 apr_size_t win32_strftime_extra(char *s, size_t max, const char *format,
                                 const struct tm *tm) 
 {
@@ -142,9 +143,10 @@
         }
         switch (format[i+1]) {
             case 'C':
+                /* requirement, met by for-loop condition: max > j */
                 length_written = apr_snprintf(new_format + j, max - j, "%2d",
                     (tm->tm_year + 1970)/100);
-                j = (length_written == -1) ? max : (j + length_written);
+                j = (length_written != 2) ? max : (j + length_written);
                 i += 2;
                 break;
             case 'D':
@@ -170,9 +172,10 @@
                 j += 8;
                 break;
             case 'e':
+                /* requirement, met by for-loop condition: max > j */
                 length_written = apr_snprintf(new_format + j, max - j, "%2d",
                     tm->tm_mday);
-                j = (length_written == -1) ? max : (j + length_written);
+                j = (length_written != 2) ? max : (j + length_written);
                 i += 2;
                 break;
             default:
Index: test/testtime.c
===================================================================
--- test/testtime.c     (revision 1078737)
+++ test/testtime.c     (working copy)
@@ -227,6 +227,22 @@
     ABTS_STR_EQUAL(tc, "19:05:36", str);
 }
 
+static void test_strftimesmallbuffer(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_time_exp_t xt;
+    char str[STR_SIZE];
+    apr_size_t sz;
+
+    rv = apr_time_exp_gmt(&xt, now);
+    rv = apr_strftime(str, &sz, 1, "%C", &xt);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_strftime");
+    }
+    ABTS_TRUE(tc, rv == APR_SUCCESS);
+    ABTS_TRUE(tc, sz == 1 || sz == 0);
+}
+
 static void test_exp_tz(abts_case *tc, void *data)
 {
     apr_status_t rv;
@@ -297,6 +313,7 @@
     abts_run_test(suite, test_ctime, NULL);
     abts_run_test(suite, test_strftime, NULL);
     abts_run_test(suite, test_strftimesmall, NULL);
+    abts_run_test(suite, test_strftimesmallbuffer, NULL);
     abts_run_test(suite, test_exp_tz, NULL);
     abts_run_test(suite, test_strftimeoffset, NULL);
     abts_run_test(suite, test_2038, NULL);
Index: include/apr_time.h
===================================================================
--- include/apr_time.h  (revision 1078737)
+++ include/apr_time.h  (working copy)
@@ -209,7 +209,9 @@
 /**
  * formats the exploded time according to the format specified
  * @param s string to write to
- * @param retsize The length of the returned string
+ * @param retsize The number of characters stored, not including terminating
+ * '\0'; if the buffer is insufficient, a partial string may or may not be
+ * stored.
  * @param max The maximum length of the string
  * @param format The format for the time string
  * @param tm The time to convert

Reply via email to