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