Always check return value of strftime().
authorBen Pfaff <blp@nicira.com>
Thu, 2 May 2013 23:16:06 +0000 (16:16 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 8 May 2013 17:53:07 +0000 (10:53 -0700)
strftime() returns 0 and leaves the contents of the output buffer
unspecified if the output buffer is not big enough.  Thus, one should
check strftime()'s return value.  Until now, OVS has had a few invocations
of strftime() that did not check the return value.  This commit fixes
those.  I believe that the buffers were always large enough in each case,
but it's better to be safe.

Reported-by: Andy Zhou <azhou@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/dynamic-string.c
lib/dynamic-string.h
lib/table.c
lib/vlog.c
ovsdb/ovsdb-tool.c
utilities/ovs-ofctl.c

index c373601..ba9aa6d 100644 (file)
@@ -183,17 +183,16 @@ ds_put_printable(struct ds *ds, const char *s, size_t n)
     }
 }
 
-/* Writes the current time to 'string' based on 'template'.
- * The current time is either local time or UTC based on 'utc'. */
+/* Writes time 'when' to 'string' based on 'template', in local time or UTC
+ * based on 'utc'. */
 void
-ds_put_strftime(struct ds *ds, const char *template, bool utc)
+ds_put_strftime(struct ds *ds, const char *template, time_t when, bool utc)
 {
     struct tm tm;
-    time_t now = time_wall();
     if (utc) {
-        gmtime_r(&now, &tm);
+        gmtime_r(&when, &tm);
     } else {
-        localtime_r(&now, &tm);
+        localtime_r(&when, &tm);
     }
 
     for (;;) {
@@ -207,6 +206,18 @@ ds_put_strftime(struct ds *ds, const char *template, bool utc)
     }
 }
 
+/* Returns a malloc()'d string for time 'when' based on 'template', in local
+ * time or UTC based on 'utc'. */
+char *
+xastrftime(const char *template, time_t when, bool utc)
+{
+    struct ds s;
+
+    ds_init(&s);
+    ds_put_strftime(&s, template, when, utc);
+    return s.string;
+}
+
 int
 ds_get_line(struct ds *ds, FILE *file)
 {
index 098caaf..b988e1f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <time.h>
 #include "compiler.h"
 
-struct tm;
-
 /* A "dynamic string", that is, a buffer that can be used to construct a
  * string across a series of operations that extend or modify it.
  *
@@ -56,14 +55,17 @@ void ds_put_format(struct ds *, const char *, ...) PRINTF_FORMAT(2, 3);
 void ds_put_format_valist(struct ds *, const char *, va_list)
     PRINTF_FORMAT(2, 0);
 void ds_put_printable(struct ds *, const char *, size_t);
-void ds_put_strftime(struct ds *, const char *, bool utc)
-    STRFTIME_FORMAT(2);
 void ds_put_hex_dump(struct ds *ds, const void *buf_, size_t size,
                      uintptr_t ofs, bool ascii);
 int ds_get_line(struct ds *, FILE *);
 int ds_get_preprocessed_line(struct ds *, FILE *);
 int ds_get_test_line(struct ds *, FILE *);
 
+void ds_put_strftime(struct ds *, const char *template, time_t when, bool utc)
+    STRFTIME_FORMAT(2);
+char *xastrftime(const char *template, time_t when, bool utc)
+    STRFTIME_FORMAT(1);
+
 char *ds_cstr(struct ds *);
 const char *ds_cstr_ro(const struct ds *);
 char *ds_steal_cstr(struct ds *);
index 266c410..21f4905 100644 (file)
@@ -218,22 +218,19 @@ table_print_table_line__(struct ds *line)
     ds_clear(line);
 }
 
-static void
-table_format_timestamp__(char *s, size_t size)
+static char *
+table_format_timestamp__(void)
 {
-    time_t now = time_wall();
-    struct tm tm;
-    strftime(s, size, "%Y-%m-%d %H:%M:%S", gmtime_r(&now, &tm));
+    return xastrftime("%Y-%m-%d %H:%M:%S", time_wall(), true);
 }
 
 static void
 table_print_timestamp__(const struct table *table)
 {
     if (table->timestamp) {
-        char s[32];
-
-        table_format_timestamp__(s, sizeof s);
+        char *s = table_format_timestamp__();
         puts(s);
+        free(s);
     }
 }
 
@@ -500,10 +497,9 @@ table_print_json__(const struct table *table, const struct table_style *style)
         json_object_put_string(json, "caption", table->caption);
     }
     if (table->timestamp) {
-        char s[32];
-
-        table_format_timestamp__(s, sizeof s);
+        char *s = table_format_timestamp__();
         json_object_put_string(json, "time", s);
+        free(s);
     }
 
     headings = json_array_create_empty();
index 275d02a..193e4f7 100644 (file)
@@ -570,12 +570,9 @@ vlog_init(void)
 
     now = time_wall();
     if (now < 0) {
-        struct tm tm;
-        char s[128];
-
-        gmtime_r(&now, &tm);
-        strftime(s, sizeof s, "%a, %d %b %Y %H:%M:%S", &tm);
+        char *s = xastrftime("%a, %d %b %Y %H:%M:%S", now, true);
         VLOG_ERR("current time is negative: %s (%ld)", s, (long int) now);
+        free(s);
     }
 
     unixctl_command_register(
@@ -709,11 +706,11 @@ format_log_message(const struct vlog_module *module, enum vlog_level level,
             break;
         case 'd':
             p = fetch_braces(p, "%Y-%m-%d %H:%M:%S", tmp, sizeof tmp);
-            ds_put_strftime(s, tmp, false);
+            ds_put_strftime(s, tmp, time_wall(), false);
             break;
         case 'D':
             p = fetch_braces(p, "%Y-%m-%d %H:%M:%S", tmp, sizeof tmp);
-            ds_put_strftime(s, tmp, true);
+            ds_put_strftime(s, tmp, time_wall(), true);
             break;
         case 'm':
             /* Format user-supplied log message and trim trailing new-lines. */
index 2ef4061..a8febda 100644 (file)
@@ -519,11 +519,9 @@ do_show_log(int argc, char *argv[])
             date = shash_find_data(json_object(json), "_date");
             if (date && date->type == JSON_INTEGER) {
                 time_t t = json_integer(date);
-                struct tm tm;
-                char s[128];
-
-                strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S", gmtime_r(&t, &tm));
-                printf(" %s", s);
+                char *s = xastrftime(" %Y-%m-%d %H:%M:%S", t, true);
+                fputs(s, stdout);
+                free(s);
             }
 
             comment = shash_find_data(json_object(json), "_comment");
index 582552c..24b9434 100644 (file)
@@ -1361,13 +1361,9 @@ monitor_vconn(struct vconn *vconn, bool reply_to_echo_requests)
             run(retval, "vconn_recv");
 
             if (timestamp) {
-                time_t now = time_wall();
-                struct tm tm;
-                char s[32];
-
-                strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S: ",
-                         gmtime_r(&now, &tm));
+                char *s = xastrftime("%Y-%m-%d %H:%M:%S: ", time_wall(), true);
                 fputs(s, stderr);
+                free(s);
             }
 
             ofptype_decode(&type, b->data);