diff --git a/wiretap/vms.c b/wiretap/vms.c index 7f6a779089..9180c0e461 100644 --- a/wiretap/vms.c +++ b/wiretap/vms.c @@ -328,6 +328,7 @@ parse_vms_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gch struct tm tm; char mon[4] = {'J', 'A', 'N', 0}; gchar *p; + const gchar *endp; static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; guint32 i; int offset = 0; @@ -388,7 +389,7 @@ parse_vms_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gch return FALSE; } - if (!ws_strtou32(p, &pkt_len)) { + if (!ws_strtou32(p, &endp, &pkt_len) || (*endp != '\0' && !g_ascii_isspace(*endp))) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("vms: Length field '%s' not valid", p); return FALSE; diff --git a/wsutil/clopts_common.c b/wsutil/clopts_common.c index 695559eb02..1967014c82 100644 --- a/wsutil/clopts_common.c +++ b/wsutil/clopts_common.c @@ -33,10 +33,11 @@ int get_natural_int(const char *string, const char *name) { + const char *end; gint32 number; - if (!ws_strtoi32(string, &number)) { - if (errno == EINVAL) { + if (!ws_strtoi32(string, &end, &number)) { + if (errno == EINVAL || *end != '\0') { cmdarg_err("The specified %s \"%s\" isn't a decimal number", name, string); exit(1); } diff --git a/wsutil/strtoi.c b/wsutil/strtoi.c index 96683d9d43..26e756d444 100644 --- a/wsutil/strtoi.c +++ b/wsutil/strtoi.c @@ -27,15 +27,17 @@ #include "strtoi.h" #include -gboolean ws_strtoi64(const gchar* str, gint64* cint) +gboolean ws_strtoi64(const gchar* str, const gchar** endptr, gint64* cint) { - gchar* endptr; + gchar* end; gint64 val; errno = 0; - val = g_ascii_strtoll(str, &endptr, 10); - if ((val == 0 && endptr == str) || (*endptr != 0)) { + val = g_ascii_strtoll(str, &end, 10); + if (val == 0 && end == str) { *cint = 0; + if (endptr != NULL) + *endptr = end; errno = EINVAL; return FALSE; } @@ -45,16 +47,20 @@ gboolean ws_strtoi64(const gchar* str, gint64* cint) * report the value as "too small" or "too large". */ *cint = val; + if (endptr != NULL) + *endptr = end; /* errno is already set */ return FALSE; } + if (endptr != NULL) + *endptr = end; *cint = val; return TRUE; } -gboolean ws_strtou64(const gchar* str, guint64* cint) +gboolean ws_strtou64(const gchar* str, const gchar** endptr, guint64* cint) { - gchar* endptr; + gchar* end; guint64 val; if (str[0] == '-' || str[0] == '+') { @@ -62,13 +68,17 @@ gboolean ws_strtou64(const gchar* str, guint64* cint) * Unsigned numbers don't have a sign. */ *cint = 0; + if (endptr != NULL) + *endptr = str; errno = EINVAL; return FALSE; } errno = 0; - val = g_ascii_strtoull(str, &endptr, 10); - if ((val == 0 && endptr == str) || (*endptr != 0)) { + val = g_ascii_strtoull(str, &end, 10); + if (val == 0 && end == str) { *cint = 0; + if (endptr != NULL) + *endptr = end; errno = EINVAL; return FALSE; } @@ -77,18 +87,22 @@ gboolean ws_strtou64(const gchar* str, guint64* cint) * Return the value, because ws_strtoi64() does. */ *cint = val; + if (endptr != NULL) + *endptr = end; /* errno is already set */ return FALSE; } + if (endptr != NULL) + *endptr = end; *cint = val; return TRUE; } #define DEFINE_WS_STRTOI_BITS(bits) \ -gboolean ws_strtoi##bits(const gchar* str, gint##bits* cint) \ +gboolean ws_strtoi##bits(const gchar* str, const gchar** endptr, gint##bits* cint) \ { \ gint64 val; \ - if (!ws_strtoi64(str, &val)) { \ + if (!ws_strtoi64(str, endptr, &val)) { \ /* \ * For ERANGE, return either G_MININT##bits or \ * G_MAXINT##bits so our caller knows whether \ @@ -134,10 +148,10 @@ DEFINE_WS_STRTOI_BITS(16) DEFINE_WS_STRTOI_BITS(8) #define DEFINE_WS_STRTOU_BITS(bits) \ -int ws_strtou##bits(const gchar* str, guint##bits* cint) \ +int ws_strtou##bits(const gchar* str, const gchar** endptr, guint##bits* cint) \ { \ guint64 val; \ - if (!ws_strtou64(str, &val)) { \ + if (!ws_strtou64(str, endptr, &val)) { \ /* \ * For ERANGE, return G_MAXUINT##bits for parallelism \ * with ws_strtoi##bits(). \ diff --git a/wsutil/strtoi.h b/wsutil/strtoi.h index 3b35bfc323..ed48b52aac 100644 --- a/wsutil/strtoi.h +++ b/wsutil/strtoi.h @@ -32,20 +32,22 @@ /* * \brief Convert a string to a signed/unsigned int, with error checks. * \param str The string to convert + * \param endptr NULL or pointer to a pointer set to point to the + * character after the last character of the number * \param cint The converted integer * \return TRUE if the conversion suceeds, FALSE otherwise. * On error, errno is set to EINVAL for unrecognized input and ERANGE * if the resulting number does not fit in the type. */ -WS_DLL_PUBLIC gboolean ws_strtoi64(const gchar* str, gint64* cint); -WS_DLL_PUBLIC gboolean ws_strtoi32(const gchar* str, gint32* cint); -WS_DLL_PUBLIC gboolean ws_strtoi16(const gchar* str, gint16* cint); -WS_DLL_PUBLIC gboolean ws_strtoi8 (const gchar* str, gint8* cint); +WS_DLL_PUBLIC gboolean ws_strtoi64(const gchar* str, const gchar** endptr, gint64* cint); +WS_DLL_PUBLIC gboolean ws_strtoi32(const gchar* str, const gchar** endptr, gint32* cint); +WS_DLL_PUBLIC gboolean ws_strtoi16(const gchar* str, const gchar** endptr, gint16* cint); +WS_DLL_PUBLIC gboolean ws_strtoi8 (const gchar* str, const gchar** endptr, gint8* cint); -WS_DLL_PUBLIC gboolean ws_strtou64(const gchar* str, guint64* cint); -WS_DLL_PUBLIC gboolean ws_strtou32(const gchar* str, guint32* cint); -WS_DLL_PUBLIC gboolean ws_strtou16(const gchar* str, guint16* cint); -WS_DLL_PUBLIC gboolean ws_strtou8 (const gchar* str, guint8* cint); +WS_DLL_PUBLIC gboolean ws_strtou64(const gchar* str, const gchar** endptr, guint64* cint); +WS_DLL_PUBLIC gboolean ws_strtou32(const gchar* str, const gchar** endptr, guint32* cint); +WS_DLL_PUBLIC gboolean ws_strtou16(const gchar* str, const gchar** endptr, guint16* cint); +WS_DLL_PUBLIC gboolean ws_strtou8 (const gchar* str, const gchar** endptr, guint8* cint); #endif