diff --git a/editcap.c b/editcap.c index 582be2f2fe..5230c3920c 100644 --- a/editcap.c +++ b/editcap.c @@ -1449,7 +1449,7 @@ main(int argc, char *argv[]) nstime_t in_time; check_startstop = TRUE; - if ((0 < iso8601_to_nstime(&in_time, ws_optarg, ISO8601_DATETIME)) || (0 < unix_epoch_to_nstime(&in_time, ws_optarg))) { + if ((NULL != iso8601_to_nstime(&in_time, ws_optarg, ISO8601_DATETIME)) || (NULL != unix_epoch_to_nstime(&in_time, ws_optarg))) { if (opt == 'A') { nstime_copy(&starttime, &in_time); have_starttime = TRUE; diff --git a/epan/ftypes/ftype-time.c b/epan/ftypes/ftype-time.c index dbe85b09a7..417f79622f 100644 --- a/epan/ftypes/ftype-time.c +++ b/epan/ftypes/ftype-time.c @@ -246,10 +246,12 @@ absolute_val_from_string(fvalue_t *fv, const char *s, size_t len _U_, char **err return TRUE; /* Try ISO 8601 format. */ - if (iso8601_to_nstime(&fv->value.time, s, ISO8601_DATETIME) == strlen(s)) + endptr = iso8601_to_nstime(&fv->value.time, s, ISO8601_DATETIME); + /* Check whether it parsed all of the string */ + if (endptr != NULL && *endptr == '\0') return TRUE; - /* Try other legacy formats. */ + /* No - try other legacy formats. */ memset(&tm, 0, sizeof(tm)); /* Let the computer figure out if it's DST. */ tm.tm_isdst = -1; diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 501f27ca3a..3e88aaf797 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -1809,15 +1809,15 @@ tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length, if (*ptr) { if ((encoding & ENC_ISO_8601_DATE_TIME) == ENC_ISO_8601_DATE_TIME) { - if ((num_chars = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME))) { - end = ptr + num_chars; - } else { + if (!(end = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME))) { + + goto fail; } } else if ((encoding & ENC_ISO_8601_DATE_TIME_BASIC) == ENC_ISO_8601_DATE_TIME_BASIC) { - if ((num_chars = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME_BASIC))) { - end = ptr + num_chars; - } else { + if (!(end = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME_BASIC))) { + + goto fail; } } else { diff --git a/wiretap/eri_enb_log.c b/wiretap/eri_enb_log.c index 8ab5269107..20abcd7afe 100644 --- a/wiretap/eri_enb_log.c +++ b/wiretap/eri_enb_log.c @@ -47,7 +47,7 @@ static gboolean eri_enb_log_get_packet(FILE_T fh, wtap_rec* rec, length = length - 1; } - if (0 < iso8601_to_nstime(&packet_time, line+1, ISO8601_DATETIME)) { + if (NULL != iso8601_to_nstime(&packet_time, line+1, ISO8601_DATETIME)) { rec->ts.secs = packet_time.secs; rec->ts.nsecs = packet_time.nsecs; rec->presence_flags |= WTAP_HAS_TS; diff --git a/wiretap/nettrace_3gpp_32_423.c b/wiretap/nettrace_3gpp_32_423.c index dc856624fb..512f6f23d1 100644 --- a/wiretap/nettrace_3gpp_32_423.c +++ b/wiretap/nettrace_3gpp_32_423.c @@ -652,7 +652,8 @@ nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info) { char magic_buf[MAGIC_BUF_SIZE+1]; int bytes_read; - char *curr_pos; + const char *curr_pos; + nstime_t start_time; nettrace_3gpp_32_423_file_info_t *file_info; gint64 start_offset; @@ -689,10 +690,15 @@ nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info) return WTAP_OPEN_NOT_MINE; } curr_pos += CLEN(c_begin_time); + /* Next we expect an ISO 8601-format time */ + curr_pos = iso8601_to_nstime(&start_time, curr_pos, ISO8601_DATETIME); + if (!curr_pos) { + return WTAP_OPEN_NOT_MINE; + } /* Ok it's our file. From here we'll need to free memory */ file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1); - curr_pos += iso8601_to_nstime(&file_info->start_time, curr_pos, ISO8601_DATETIME); + file_info->start_time = start_time; file_info->start_offset = start_offset + (curr_pos - magic_buf); file_info->buffer = g_byte_array_sized_new(RINGBUFFER_START_SIZE); g_byte_array_append(file_info->buffer, curr_pos, (guint)(bytes_read - (curr_pos - magic_buf))); diff --git a/wsutil/nstime.c b/wsutil/nstime.c index 9c0f558e28..071757a1ec 100644 --- a/wsutil/nstime.c +++ b/wsutil/nstime.c @@ -277,7 +277,8 @@ nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime) * parses a character string for a date and time given in * ISO 8601 date-time format (eg: 2014-04-07T05:41:56.782+00:00) * and converts to an nstime_t - * returns number of chars parsed on success, or 0 on failure + * returns pointer to the first character after the last character + * parsed on success, or NULL on failure * * NB. ISO 8601 is actually a lot more flexible than the above format, * much to a developer's chagrin. The "basic format" is distinguished from @@ -299,7 +300,7 @@ nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime) * YYYY-Www-D, YYYY-DDD, etc. For a relatively easy introduction to * these formats, see wikipedia: https://en.wikipedia.org/wiki/ISO_8601 */ -guint8 +const char * iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) { struct tm tm; @@ -308,8 +309,6 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) guint frac = 0; gint off_hr = 0; gint off_min = 0; - guint8 ret_val = 0; - const char *start = ptr; char sign = '\0'; gboolean has_separator = FALSE; gboolean have_offset = FALSE; @@ -322,7 +321,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) * separator. */ for (n_scanned = 0; n_scanned < 4; n_scanned++) { if (!g_ascii_isdigit(*ptr)) { - return 0; + return NULL; } tm.tm_year *= 10; tm.tm_year += *ptr++ - '0'; @@ -330,7 +329,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) if (*ptr == '-') { switch (format) { case ISO8601_DATETIME_BASIC: - return 0; + return NULL; case ISO8601_DATETIME: case ISO8601_DATETIME_AUTO: @@ -341,7 +340,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) } else if (g_ascii_isdigit(*ptr)) { switch (format) { case ISO8601_DATETIME: - return 0; + return NULL; case ISO8601_DATETIME_BASIC: case ISO8601_DATETIME_AUTO: @@ -349,7 +348,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) has_separator = FALSE; }; } else { - return 0; + return NULL; } tm.tm_year -= 1900; /* struct tm expects number of years since 1900 */ @@ -375,7 +374,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) ptr += n_chars; } else { - return 0; + return NULL; } if (*ptr == 'T' || *ptr == ' ') { @@ -388,7 +387,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) /* Allow no separator between date and time iff we have no separator between units. (Some extended formats may negotiate no separator here, so this could be changed.) */ - return 0; + return NULL; } /* Now we're on to the time part. We'll require a minimum of hours and @@ -403,7 +402,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) } else { /* didn't get hours and minutes */ - return 0; + return NULL; } /* Test for (whole) seconds */ @@ -413,7 +412,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) if (1 > sscanf(ptr, has_separator ? ":%2u%n" : "%2u%n", &tm.tm_sec, &n_chars)) { /* Couldn't get them */ - return 0; + return NULL; } ptr += n_chars; @@ -453,7 +452,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) /* Validate what we got so far. mktime() doesn't care about strange values but we should at least start with something valid */ if (!tm_is_valid(&tm)) { - return 0; + return NULL; } /* Check for a time zone offset */ @@ -508,8 +507,7 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) nstime->secs = mktime(&tm); } nstime->nsecs = frac; - ret_val = (guint)(ptr-start); - return ret_val; + return ptr; } /* @@ -518,11 +516,12 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format) * a floating point number containing a Unix epoch date-time * format (e.g. 1600000000.000 for Sun Sep 13 05:26:40 AM PDT 2020) * and converts to an nstime_t - * returns number of chars parsed on success, or 0 on failure + * returns pointer to the first character after the last character + * parsed on success, or NULL on failure * * Reference: https://en.wikipedia.org/wiki/Unix_time */ -guint8 +const char * unix_epoch_to_nstime(nstime_t *nstime, const char *ptr) { gint64 secs; @@ -530,8 +529,6 @@ unix_epoch_to_nstime(nstime_t *nstime, const char *ptr) gint n_chars = 0; guint frac = 0; - guint8 ret_val = 0; - const char *start = ptr; nstime_set_unset(nstime); @@ -540,18 +537,18 @@ unix_epoch_to_nstime(nstime_t *nstime, const char *ptr) * might be 64-bit. */ if (!ws_strtoi64(ptr, &ptr_new, &secs)) { - return 0; + return NULL; } /* For now, reject times before the Epoch. */ if (secs < 0) { - return 0; + return NULL; } /* Make sure it fits. */ nstime->secs = (time_t) secs; if (nstime->secs != secs) { - return 0; + return NULL; } /* Now let's test for fractional seconds */ @@ -583,10 +580,7 @@ unix_epoch_to_nstime(nstime_t *nstime, const char *ptr) frac = 0; } nstime->nsecs = frac; - - /* return pointer shift */ - ret_val = (guint)(ptr_new-start); - return ret_val; + return ptr_new; } size_t nstime_to_iso8601(char *buf, size_t buf_size, const nstime_t *nstime) diff --git a/wsutil/nstime.h b/wsutil/nstime.h index e6b97fdfd5..fcccf55982 100644 --- a/wsutil/nstime.h +++ b/wsutil/nstime.h @@ -129,15 +129,15 @@ typedef enum { ISO8601_DATETIME_AUTO, /** Autodetect the presence of separators */ } iso8601_fmt_e; -/** parse an ISO 8601 format datetime string to nstime, returns number of - chars parsed on success, 0 on failure. +/** parse an ISO 8601 format datetime string to nstime, returns pointer + to the first character after the last character, NULL on failure Note that nstime is set to unset in the case of failure */ -WS_DLL_PUBLIC guint8 iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format); +WS_DLL_PUBLIC const char * iso8601_to_nstime(nstime_t *nstime, const char *ptr, iso8601_fmt_e format); /** parse an Unix epoch timestamp format datetime string to nstime, returns - number of chars parsed on success, 0 on failure. + pointer to the first character after the last character, NULL on failure Note that nstime is set to unset in the case of failure */ -WS_DLL_PUBLIC guint8 unix_epoch_to_nstime(nstime_t *nstime, const char *ptr); +WS_DLL_PUBLIC const char * unix_epoch_to_nstime(nstime_t *nstime, const char *ptr); #define NSTIME_ISO8601_BUFSIZE sizeof("YYYY-MM-DDTHH:MM:SS.123456789Z") diff --git a/wsutil/test_wsutil.c b/wsutil/test_wsutil.c index 1fbb9be1d2..52a60852ac 100644 --- a/wsutil/test_wsutil.c +++ b/wsutil/test_wsutil.c @@ -576,7 +576,7 @@ static void test_int64_to_str_back(void) void test_nstime_from_iso8601(void) { char *str; - size_t chars; + const char *endp; nstime_t result, expect; struct tm tm1; @@ -593,8 +593,9 @@ void test_nstime_from_iso8601(void) str = "2013-05-30T23:45:25.349124"; expect.secs = mktime(&tm1); expect.nsecs = 349124 * 1000; - chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); - g_assert_cmpuint(chars, ==, strlen(str)); + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); g_assert_cmpint(result.secs, ==, expect.secs); g_assert_cmpint(result.nsecs, ==, expect.nsecs); @@ -602,8 +603,9 @@ void test_nstime_from_iso8601(void) str = "2013-05-30T23:45:25.349124Z"; expect.secs = mktime_utc(&tm1); expect.nsecs = 349124 * 1000; - chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); - g_assert_cmpuint(chars, ==, strlen(str)); + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); g_assert_cmpint(result.secs, ==, expect.secs); g_assert_cmpint(result.nsecs, ==, expect.nsecs); @@ -611,8 +613,9 @@ void test_nstime_from_iso8601(void) str = "2013-05-30T23:45:25.349124+01:00"; expect.secs = mktime_utc(&tm1) - 1 * 60 * 60; expect.nsecs = 349124 * 1000; - chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); - g_assert_cmpuint(chars, ==, strlen(str)); + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); g_assert_cmpint(result.secs, ==, expect.secs); g_assert_cmpint(result.nsecs, ==, expect.nsecs); @@ -620,8 +623,9 @@ void test_nstime_from_iso8601(void) str = "2013-05-30T23:45:25.349124+0100"; expect.secs = mktime_utc(&tm1) - 1 * 60 * 60; expect.nsecs = 349124 * 1000; - chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); - g_assert_cmpuint(chars, ==, strlen(str)); + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); g_assert_cmpint(result.secs, ==, expect.secs); g_assert_cmpint(result.nsecs, ==, expect.nsecs); @@ -629,8 +633,9 @@ void test_nstime_from_iso8601(void) str = "2013-05-30T23:45:25.349124+01"; expect.secs = mktime_utc(&tm1) - 1 * 60 * 60; expect.nsecs = 349124 * 1000; - chars = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); - g_assert_cmpuint(chars, ==, strlen(str)); + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); g_assert_cmpint(result.secs, ==, expect.secs); g_assert_cmpint(result.nsecs, ==, expect.nsecs); }