From cd6134da9086bf66513a8fa842a4aa04e690025f Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Mon, 24 Feb 2020 23:36:35 -0800 Subject: [PATCH] Add ws_strtoi() and ws_strtoui() routines and use them. Those fetch gint and guint values, respectively, rather than values with specified sizes in bits. This should squelch Coverity CID 1457357. Change-Id: Ia8f100bd3fe90c266e24a4346f80b2667c653b93 Reviewed-on: https://code.wireshark.org/review/36177 Petri-Dish: Guy Harris Tested-by: Petri Dish Buildbot Reviewed-by: Guy Harris --- debian/libwsutil0.symbols | 4 ++ ui/capture_ui_utils.c | 34 ++++++---------- wsutil/strtoi.c | 84 +++++++++++++++++++++++++++++++++++++++ wsutil/strtoi.h | 4 ++ 4 files changed, 105 insertions(+), 21 deletions(-) diff --git a/debian/libwsutil0.symbols b/debian/libwsutil0.symbols index d05d203a03..f180cfb8a4 100644 --- a/debian/libwsutil0.symbols +++ b/debian/libwsutil0.symbols @@ -194,6 +194,7 @@ libwsutil.so.0 libwsutil0 #MINVER# ws_basestrtou32@Base 2.9.0 ws_basestrtou64@Base 2.9.0 ws_basestrtou8@Base 2.9.0 + ws_basestrtou@Base 3.3.0 ws_buffer_append@Base 1.99.0 ws_buffer_assure_space@Base 1.99.0 ws_buffer_free@Base 1.99.0 @@ -206,6 +207,7 @@ libwsutil.so.0 libwsutil0 #MINVER# ws_hexstrtou32@Base 2.3.0 ws_hexstrtou64@Base 2.3.0 ws_hexstrtou8@Base 2.3.0 + ws_hexstrtou@Base 3.3.0 ws_hmac_buffer@Base 2.3.0 ws_inet_ntop4@Base 2.1.2 ws_inet_ntop6@Base 2.1.2 @@ -225,10 +227,12 @@ libwsutil.so.0 libwsutil0 #MINVER# ws_strtoi32@Base 2.3.0 ws_strtoi64@Base 2.3.0 ws_strtoi8@Base 2.3.0 + ws_strtoi@Base 3.3.0 ws_strtou16@Base 2.3.0 ws_strtou32@Base 2.3.0 ws_strtou64@Base 2.3.0 ws_strtou8@Base 2.3.0 + ws_strtou@Base 3.3.0 ws_utf8_char_len@Base 1.12.0~rc1 ws_vadd_crash_info@Base 2.5.2 ws_xton@Base 1.12.0~rc1 diff --git a/ui/capture_ui_utils.c b/ui/capture_ui_utils.c index 43492c97e3..3bd0fbea6e 100644 --- a/ui/capture_ui_utils.c +++ b/ui/capture_ui_utils.c @@ -24,6 +24,7 @@ #include "ui/capture_globals.h" #include "wiretap/wtap.h" #include "epan/to_str.h" +#include "wsutil/strtoi.h" /* * In a list of interface information, in the form of a comma-separated @@ -93,28 +94,22 @@ capture_dev_get_if_property(const gchar *pref, const gchar *if_name) static gint capture_dev_get_if_int_property(const gchar *pref, const gchar *if_name) { - gchar *property_string, *next; - long property; + gchar *property_string; + gint property; property_string = capture_dev_get_if_property(pref, if_name); if (property_string == NULL) { /* No property found for this interface. */ return -1; } - property = strtol(property_string, &next, 10); - if (next == property_string || *next != '\0' || property < 0) { - /* Syntax error */ - g_free(property_string); - return -1; - } - if (property > G_MAXINT) { - /* Value doesn't fit in a gint */ + if (!ws_strtoi(property_string, NULL, &property)) { + /* Syntax error or range error */ g_free(property_string); return -1; } g_free(property_string); - return (gint)property; + return property; } /* @@ -165,8 +160,9 @@ capture_dev_user_snaplen_find(const gchar *if_name, gboolean *hassnap, int *snap */ if_tokens = g_strsplit(prefs.capture_devices_snaplen, ",", -1); for (i = 0; if_tokens[i] != NULL; i++) { - gchar *colonp, *next; - long value; + gchar *colonp; + const gchar *next; + gint value; /* * This one's a bit ugly. @@ -200,18 +196,14 @@ capture_dev_user_snaplen_find(const gchar *if_name, gboolean *hassnap, int *snap /* Not followed by a parenthesis. Give up. */ break; } - value = strtol(colonp + 3, &next, 10); - if (next == colonp + 3 || *next != ')' || value < 0) { - /* Syntax error. Give up. */ - break; - } - if (value > G_MAXINT) { - /* Value doesn't fit in a gint. Give up. */ + if (!ws_strtoi(colonp + 3, &next, &value) || + next == colonp + 3 || *next != ')' || value < 0) { + /* Syntax error or range error. Give up. */ break; } found = TRUE; *hassnap = TRUE; - *snaplen = (gint)value; + *snaplen = value; } else { /* Bad {hassnap}. Give up. */ break; diff --git a/wsutil/strtoi.c b/wsutil/strtoi.c index a70deced89..7a9a9001fe 100644 --- a/wsutil/strtoi.c +++ b/wsutil/strtoi.c @@ -102,6 +102,50 @@ DEFINE_WS_STRTOI_BITS(32) DEFINE_WS_STRTOI_BITS(16) DEFINE_WS_STRTOI_BITS(8) +gboolean ws_strtoi(const gchar* str, const gchar** endptr, gint* cint) +{ + gint64 val = 0; + if (!ws_strtoi64(str, endptr, &val)) { + /* + * For ERANGE, return either G_MININT or + * G_MAXINT so our caller knows whether + * to report the value as "too small" or "too + * large". + * + * For other errors, return 0, for parallelism + * with ws_strtoi64(). + */ + if (errno == ERANGE) { + if (val < 0) + *cint = G_MININT; + else + *cint = G_MAXINT; + } else + *cint = 0; + return FALSE; + } + if (val < G_MININT) { + /* + * Return G_MININT so our caller knows whether to + * report the value as "too small" or "too large". + */ + *cint = G_MININT; + errno = ERANGE; + return FALSE; + } + if (val > G_MAXINT) { + /* + * Return G_MAXINT so our caller knows whether to + * report the value as "too small" or "too large". + */ + *cint = G_MAXINT; + errno = ERANGE; + return FALSE; + } + *cint = (gint)val; + return TRUE; +} + gboolean ws_basestrtou64(const gchar* str, const gchar** endptr, guint64* cint, int base) { gchar* end; @@ -204,6 +248,46 @@ DEFINE_WS_STRTOU_BITS(32) DEFINE_WS_STRTOU_BITS(16) DEFINE_WS_STRTOU_BITS(8) +gboolean ws_basestrtou(const gchar* str, const gchar** endptr, guint* cint, int base) +{ + guint64 val; + if (!ws_basestrtou64(str, endptr, &val, base)) { + /* + * For ERANGE, return G_MAXUINT for parallelism + * with ws_strtoi(). + * + * For other errors, return 0, for parallelism + * with ws_basestrtou64(). + */ + if (errno == ERANGE) + *cint = G_MAXUINT; + else + *cint = 0; + return FALSE; + } + if (val > G_MAXUINT) { + /* + * Return G_MAXUINT for parallelism with + * ws_strtoi(). + */ + *cint = G_MAXUINT; + errno = ERANGE; + return FALSE; + } + *cint = (guint)val; + return TRUE; +} + +gboolean ws_strtou(const gchar* str, const gchar** endptr, guint* cint) +{ + return ws_basestrtou(str, endptr, cint, 10); +} +\ +gboolean ws_hexstrtou(const gchar* str, const gchar** endptr, guint* cint) +{ + return ws_basestrtou(str, endptr, cint, 16); +} + /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * diff --git a/wsutil/strtoi.h b/wsutil/strtoi.h index 072f05a0c1..6e2fabed07 100644 --- a/wsutil/strtoi.h +++ b/wsutil/strtoi.h @@ -37,11 +37,13 @@ WS_DLL_PUBLIC gboolean ws_strtoi64(const gchar* str, const gchar** endptr, gint6 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_strtoi (const gchar* str, const gchar** endptr, gint* 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); +WS_DLL_PUBLIC gboolean ws_strtou (const gchar* str, const gchar** endptr, guint* cint); /* * \brief Convert a hexadecimal string to an unsigned int, with error checks. @@ -60,6 +62,7 @@ WS_DLL_PUBLIC gboolean ws_hexstrtou64(const gchar* str, const gchar** endptr, gu WS_DLL_PUBLIC gboolean ws_hexstrtou32(const gchar* str, const gchar** endptr, guint32* cint); WS_DLL_PUBLIC gboolean ws_hexstrtou16(const gchar* str, const gchar** endptr, guint16* cint); WS_DLL_PUBLIC gboolean ws_hexstrtou8 (const gchar* str, const gchar** endptr, guint8* cint); +WS_DLL_PUBLIC gboolean ws_hexstrtou (const gchar* str, const gchar** endptr, guint* cint); /* * \brief Convert a string in the specified base to an unsigned int, with @@ -82,6 +85,7 @@ WS_DLL_PUBLIC gboolean ws_basestrtou64(const gchar* str, const gchar** endptr, g WS_DLL_PUBLIC gboolean ws_basestrtou32(const gchar* str, const gchar** endptr, guint32* cint, int base); WS_DLL_PUBLIC gboolean ws_basestrtou16(const gchar* str, const gchar** endptr, guint16* cint, int base); WS_DLL_PUBLIC gboolean ws_basestrtou8 (const gchar* str, const gchar** endptr, guint8* cint, int base); +WS_DLL_PUBLIC gboolean ws_basestrtou (const gchar* str, const gchar** endptr, guint* cint, int base); #ifdef __cplusplus }