]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Have a common routine for converting dates and times to strings. 1032/head
authorGuy Harris <[email protected]>
Tue, 31 Jan 2023 07:03:16 +0000 (23:03 -0800)
committerFrancois-Xavier Le Bail <[email protected]>
Thu, 2 Feb 2023 14:43:24 +0000 (15:43 +0100)
Have a routine that takes a buffer, a strftime format, and a struct tm *
as arguments, and:

* checks whether the struct tm * is null and, if so, returns a string
indicating that the date and time couldn't be converted;

* otherwise, passes it to strftime(), along with the buffer and the
format argument and, if strftime() returns 0, meaning the string didn't
fit into the buffer and thus that the buffer's contents are undefined,
returns a string indicating that the date and time didn't fit into the
buffer;

* otherwise, returns a pointer to the buffer.

Call that routine instead of directly calling strftime() in printers;
that prevents printing a buffer with undefined data if the buffer isn't
big enough for the string.

Also, when generating file names using an strftime format, check the
return value of strftime() to make sure the buffer didn't overflow.

netdissect.h
ntp.c
print-ahcp.c
print-arista.c
print-rx.c
print-zep.c
smbutil.c
tcpdump.c
util-print.c

index 5762c5848d37f2135976025e7431229705ad72d2..d953a464ea112172acfb5472d8763ed1380f6eec 100644 (file)
@@ -437,6 +437,9 @@ extern void ts_print(netdissect_options *, const struct timeval *);
 extern void signed_relts_print(netdissect_options *, int32_t);
 extern void unsigned_relts_print(netdissect_options *, uint32_t);
 
+extern const char *nd_format_time(char *buf, size_t bufsize,
+    const char *format, const struct tm *timeptr);
+
 extern void fn_print_char(netdissect_options *, u_char);
 extern void fn_print_str(netdissect_options *, const u_char *);
 extern u_int nd_printztn(netdissect_options *, const u_char *, u_int, const u_char *);
diff --git a/ntp.c b/ntp.c
index 10fabe4b6d13575b4578f78ec33cfb1497cb8ea2..ec8f659a4eb020b6232458226268676f3582654c 100644 (file)
--- a/ntp.c
+++ b/ntp.c
@@ -54,8 +54,8 @@ p_ntp_time(netdissect_options *ndo,
        if (i) {
            int64_t seconds_64bit = (int64_t)i - JAN_1970;
            time_t seconds;
-           struct tm *tm;
            char time_buf[128];
+           const char *time_string;
 
            seconds = (time_t)seconds_64bit;
            if (seconds != seconds_64bit) {
@@ -63,21 +63,12 @@ p_ntp_time(netdissect_options *ndo,
                 * It doesn't fit into a time_t, so we can't hand it
                 * to gmtime.
                 */
-               ND_PRINT(" (unrepresentable)");
+               time_string = "[Time is too large to fit into a time_t]";
            } else {
-               tm = gmtime(&seconds);
-               if (tm == NULL) {
-                   /*
-                    * gmtime() can't handle it.
-                    * (Yes, that might happen with some version of
-                    * Microsoft's C library.)
-                    */
-                   ND_PRINT(" (unrepresentable)");
-               } else {
-                   /* use ISO 8601 (RFC3339) format */
-                   strftime(time_buf, sizeof (time_buf), "%Y-%m-%dT%H:%M:%SZ", tm);
-                   ND_PRINT(" (%s)", time_buf);
-               }
+               /* use ISO 8601 (RFC3339) format */
+               time_string = nd_format_time(time_buf, sizeof (time_buf),
+                 "%Y-%m-%dT%H:%M:%SZ", gmtime(&seconds));
            }
+           ND_PRINT(" (%s)", time_string);
        }
 }
index 9859f76009d5953efffb8a0d9c2c60d4bcd23879..d57edda9e090f280c214de3a45e057d962461a7a 100644 (file)
@@ -102,18 +102,14 @@ ahcp_time_print(netdissect_options *ndo,
                 const u_char *cp, uint8_t len)
 {
        time_t t;
-       struct tm *tm;
-       char buf[BUFSIZE];
+       char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")];
 
        if (len != 4)
                goto invalid;
        t = GET_BE_U_4(cp);
-       if (NULL == (tm = gmtime(&t)))
-               ND_PRINT(": gmtime() error");
-       else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm))
-               ND_PRINT(": strftime() error");
-       else
-               ND_PRINT(": %s UTC", buf);
+       ND_PRINT(": %s",
+           nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC",
+             gmtime(&t)));
        return;
 
 invalid:
index 039a1ffd1e89bbea87e23918d98ffa12b8a530a6..079ad684bc1145dfb6e3264cc8b671474569f180 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "netdissect.h"
 #include "extract.h"
-#include "addrtoname.h"
 
 /*
 
@@ -93,17 +92,13 @@ arista_print_date_hms_time(netdissect_options *ndo, uint32_t seconds,
                uint32_t nanoseconds)
 {
        time_t ts;
-       struct tm *tm;
-       char buf[BUFSIZE];
+       char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss")];
 
        ts = seconds + (nanoseconds / 1000000000);
        nanoseconds %= 1000000000;
-       if (NULL == (tm = gmtime(&ts)))
-               ND_PRINT("gmtime() error");
-       else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm))
-               ND_PRINT("strftime() error");
-       else
-               ND_PRINT("%s.%09u", buf, nanoseconds);
+       ND_PRINT("%s.%09u",
+           nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
+              gmtime(&ts)), nanoseconds);
 }
 
 int
index 3f7589ea6bd517afe1cd7c714ccabdcdda70cf13..dbef71c05be4846dfc2f0c2b09e6a9979cae368d 100644 (file)
@@ -794,12 +794,12 @@ rx_cache_find(netdissect_options *ndo, const struct rx_header *rxh,
                        ND_PRINT(" %" PRIu64, _i); \
                }
 
-#define DATEOUT() { time_t _t; struct tm *tm; char str[256]; \
+#define DATEOUT() { time_t _t; char str[256]; \
                        _t = (time_t) GET_BE_S_4(bp); \
                        bp += sizeof(int32_t); \
-                       tm = localtime(&_t); \
-                       strftime(str, 256, "%Y/%m/%d %H:%M:%S", tm); \
-                       ND_PRINT(" %s", str); \
+                       ND_PRINT(" %s", \
+                           nd_format_time(str, sizeof(str), \
+                             "%Y/%m/%d %H:%M:%S", localtime(&_t))); \
                }
 
 #define STOREATTROUT() { uint32_t mask, _i; \
index da1e91c7d2122394803e3fa64924b5293ad934e6..b18437f0c784c8eb6d1a34f8f277a484a6e120e9 100644 (file)
@@ -82,12 +82,11 @@ static void zep_print_ts(netdissect_options *ndo, const u_char *p)
         */
        if (i) {
                time_t seconds = i - JAN_1970;
-               struct tm *tm;
                char time_buf[128];
 
-               tm = localtime(&seconds);
-               strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm);
-               ND_PRINT(" (%s)", time_buf);
+               ND_PRINT(" (%s)",
+                   nd_format_time(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S",
+                     localtime(&seconds)));
        }
 }
 
index 6e509ecf58fb804c8a3c3131d0ac86861248e43a..f33a323fbf2c7c4037ec7ffd8a84c62c40e25aa3 100644 (file)
--- a/smbutil.c
+++ b/smbutil.c
@@ -768,9 +768,8 @@ smb_fdata1(netdissect_options *ndo,
        case 'T':
          {
            time_t t;
-           struct tm *lt;
            const char *tstring;
-           char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy\n")];
+           char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy")];
            uint32_t x;
 
            switch (atoi(fmt + 1)) {
@@ -800,16 +799,11 @@ smb_fdata1(netdissect_options *ndo,
                break;
            }
            if (t != 0) {
-               lt = localtime(&t);
-               if (lt != NULL) {
-                   strftime(buffer, sizeof(buffer), "%a %b %e %T %Y%n", lt);
-                   tstring = buffer;
-               }
-               else
-                   tstring = "(Can't convert time)\n";
+                   tstring = nd_format_time(buffer, sizeof(buffer), "%a %b %e %T %Y",
+                   localtime(&t));
            } else
-               tstring = "NULL\n";
-           ND_PRINT("%s", tstring);
+               tstring = "NULL";
+           ND_PRINT("%s\n", tstring);
            fmt++;
            while (ND_ASCII_ISDIGIT(*fmt))
                fmt++;
index 515edf5d47c2bf72470cb8b1f2af34bbbb32a19e..08e038963ec02920bc42b3e2bf88bc8f98dc5fd8 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -833,6 +833,8 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
         char *filename = malloc(PATH_MAX + 1);
         if (filename == NULL)
             error("%s: malloc", __func__);
+        if (strlen(orig_name) == 0)
+            error("an empty string is not a valid file name");
 
         /* Process with strftime if Gflag is set. */
         if (Gflag != 0) {
@@ -844,9 +846,25 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
           }
 
           /* There's no good way to detect an error in strftime since a return
-           * value of 0 isn't necessarily failure.
+           * value of 0 isn't necessarily failure; if orig_name is an empty
+           * string, the formatted string will be empty.
+           *
+           * However, the C90 standard says that, if there *is* a
+           * buffer overflow, the content of the buffer is undefined,
+           * so we must check for a buffer overflow.
+           *
+           * So we check above for an empty orig_name, and only call
+           * strftime() if it's non-empty, in which case the return
+           * value will only be 0 if the formatted date doesn't fit
+           * in the buffer.
+           *
+           * (We check above because, even if we don't use -G, we
+           * want a better error message than "tcpdump: : No such
+           * file or directory" for this case.)
            */
-          strftime(filename, PATH_MAX, orig_name, local_tm);
+          if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) {
+            error("%s: strftime", __func__);
+          }
         } else {
           strncpy(filename, orig_name, PATH_MAX);
         }
index 6d408d15d4ad772a74b01712f44c10118185cdbf..f20139f2db2cc97d3d266ad2ef017148691cab72 100644 (file)
@@ -247,7 +247,8 @@ ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec,
 {
        time_t Time = sec;
        struct tm *tm;
-       char timestr[32];
+       char timebuf[32];
+       const char *timestr;
 
        if ((unsigned)sec & 0x80000000) {
                ND_PRINT("[Error converting time]");
@@ -259,14 +260,13 @@ ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec,
        else
                tm = gmtime(&Time);
 
-       if (!tm) {
-               ND_PRINT("[Error converting time]");
-               return;
+       if (date_flag == WITH_DATE) {
+               timestr = nd_format_time(timebuf, sizeof(timebuf),
+                   "%Y-%m-%d %H:%M:%S", tm);
+       } else {
+               timestr = nd_format_time(timebuf, sizeof(timebuf),
+                   "%H:%M:%S", tm);
        }
-       if (date_flag == WITH_DATE)
-               strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
-       else
-               strftime(timestr, sizeof(timestr), "%H:%M:%S", tm);
        ND_PRINT("%s", timestr);
 
        ts_frac_print(ndo, usec);
@@ -422,6 +422,26 @@ signed_relts_print(netdissect_options *ndo,
        unsigned_relts_print(ndo, secs);
 }
 
+/*
+ * Format a struct tm with strftime().
+ * If the pointer to the struct tm is null, that means that the
+ * routine to convert a time_t to a struct tm failed; the localtime()
+ * and gmtime() in the Microsoft Visual Studio C library will fail,
+ * returning null, if the value is before the UNIX Epoch.
+ */
+const char *
+nd_format_time(char *buf, size_t bufsize, const char *format,
+         const struct tm *timeptr)
+{
+       if (timeptr != NULL) {
+               if (strftime(buf, bufsize, format, timeptr) != 0)
+                       return (buf);
+               else
+                       return ("[nd_format_time() buffer is too small]");
+       } else
+               return ("[localtime() or gmtime() couldn't convert the date and time]");
+}
+
 /* Print the truncated string */
 void nd_print_trunc(netdissect_options *ndo)
 {