The driver was not correctly validating the arguments for packet_size,
packet_copy, and no_rx. The original parsing had several issues:
- Empty strings were not rejected
- Trailing non-numeric characters were silently ignored
- Large values could wrap around causing unexpected behavior

Add a common helper function get_unsigned_arg() that properly validates
numeric arguments by checking for empty input, ensuring the entire
string is consumed, and enforcing appropriate maximum values for each
parameter.

Fixes: 4df90194f2a2 ("net/null: prefer unsigned int")
Cc: [email protected]

Signed-off-by: Stephen Hemminger <[email protected]>
---
 drivers/net/null/rte_eth_null.c | 59 +++++++++++++++------------------
 1 file changed, 26 insertions(+), 33 deletions(-)

diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index ba87c82a73..cd7a29bce9 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -602,56 +602,49 @@ eth_dev_null_create(struct rte_vdev_device *dev, struct 
pmd_options *args)
        return 0;
 }
 
-static inline int
-get_packet_size_arg(const char *key __rte_unused,
-               const char *value, void *extra_args)
+static int
+get_unsigned_arg(const char *str, unsigned int *retval,
+                unsigned int maxval)
 {
-       const char *a = value;
-       unsigned int *packet_size = extra_args;
+       char *endp = NULL;
+       unsigned long val;
 
-       if ((value == NULL) || (extra_args == NULL))
+       if (str == NULL || retval == NULL)
                return -EINVAL;
 
-       *packet_size = (unsigned int)strtoul(a, NULL, 0);
-       if (*packet_size == UINT_MAX)
-               return -1;
+       if (*str == '\0')
+               return -EINVAL; /* empty string */
 
+       val = strtoul(str, &endp, 0);
+       if (*endp != '\0')
+               return -EINVAL; /* non-numeric character */
+
+       if (val > maxval)
+               return -ERANGE;
+
+       *retval = val;
        return 0;
 }
 
-static inline int
-get_packet_copy_arg(const char *key __rte_unused,
+static int
+get_packet_size_arg(const char *key __rte_unused,
                const char *value, void *extra_args)
 {
-       const char *a = value;
-       unsigned int *packet_copy = extra_args;
-
-       if ((value == NULL) || (extra_args == NULL))
-               return -EINVAL;
-
-       *packet_copy = (unsigned int)strtoul(a, NULL, 0);
-       if (*packet_copy == UINT_MAX)
-               return -1;
+       return get_unsigned_arg(value, extra_args, UINT16_MAX);
+}
 
-       return 0;
+static int
+get_packet_copy_arg(const char *key __rte_unused,
+               const char *value, void *extra_args)
+{
+       return get_unsigned_arg(value, extra_args, UINT32_MAX);
 }
 
 static int
 get_packet_no_rx_arg(const char *key __rte_unused,
                const char *value, void *extra_args)
 {
-       const char *a = value;
-       unsigned int no_rx;
-
-       if (value == NULL || extra_args == NULL)
-               return -EINVAL;
-
-       no_rx = (unsigned int)strtoul(a, NULL, 0);
-       if (no_rx != 0 && no_rx != 1)
-               return -1;
-
-       *(unsigned int *)extra_args = no_rx;
-       return 0;
+       return get_unsigned_arg(value, extra_args, 1);
 }
 
 static int
-- 
2.51.0

Reply via email to