Make the ws_strto* routines more like the strto* routines.
authorGuy Harris <guy@alum.mit.edu>
Wed, 7 Sep 2016 17:43:15 +0000 (10:43 -0700)
committerGuy Harris <guy@alum.mit.edu>
Wed, 7 Sep 2016 20:41:53 +0000 (20:41 +0000)
Not all uses of atoi() or various strto* routines in Wireshark expect
the string to contain *only* a number, so not all uses should require
that the byte after the number be a '\0'.  Have the ws_strto* routines
take a "pointer a pointer set to point to the character after the
number" argument, and have the callers do the appropriate checks of the
character after that.

This fixes the VMS trace reading code so that it can read those files
again.

The get_ routines are handed command-line arguments, so they *do* expect
the string to contain only a number; have them check to make sure the
byte after the number is a '\0'.

Change-Id: I46fc1bea7912b9278e385fe38491a0a2ad60d697
Reviewed-on: https://code.wireshark.org/review/17560
Reviewed-by: Guy Harris <guy@alum.mit.edu>
wiretap/vms.c
wsutil/clopts_common.c
wsutil/strtoi.c
wsutil/strtoi.h

index 7f6a77908939d8db29f3d2387a1862afa8cfc058..9180c0e461af055a10169fef8e4d6228e00fbf97 100644 (file)
@@ -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;
index 695559eb021ecab38042e0fdea398fd0a70eb2c8..1967014c8279626da152d8de6f1072e0666d1fb1 100644 (file)
 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);
     }
index 96683d9d43ce36976e0cd343a918a3c90880c56e..26e756d444014f17e2bb18be415f69f9b7f5dbaf 100644 (file)
 #include "strtoi.h"
 #include <errno.h>
 
-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(). \
index 3b35bfc323040183484bd4a72e3511cf93eb20a4..ed48b52aac9bc1fc0d604b5bcf7710b0807700fd 100644 (file)
 /*
  * \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