Skip to content
Permalink
Browse files Browse the repository at this point in the history
Have a common routine for converting dates and times to strings.
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.
  • Loading branch information
guyharris authored and fxlb committed Feb 2, 2023
1 parent 4d0dd4f commit 7578e1c
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 61 deletions.
3 changes: 3 additions & 0 deletions netdissect.h
Expand Up @@ -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 *);
Expand Down
21 changes: 6 additions & 15 deletions ntp.c
Expand Up @@ -54,30 +54,21 @@ 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) {
/*
* 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);
}
}
12 changes: 4 additions & 8 deletions print-ahcp.c
Expand Up @@ -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:
Expand Down
13 changes: 4 additions & 9 deletions print-arista.c
Expand Up @@ -10,7 +10,6 @@

#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"

/*
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions print-rx.c
Expand Up @@ -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; \
Expand Down
7 changes: 3 additions & 4 deletions print-zep.c
Expand Up @@ -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)));
}
}

Expand Down
16 changes: 5 additions & 11 deletions smbutil.c
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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++;
Expand Down
22 changes: 20 additions & 2 deletions tcpdump.c
Expand Up @@ -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) {
Expand All @@ -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);
}
Expand Down
36 changes: 28 additions & 8 deletions util-print.c
Expand Up @@ -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]");
Expand All @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit 7578e1c

Please sign in to comment.