]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
util: Add StringParse* functions
authorShivani Bhardwaj <shivanib134@gmail.com>
Sun, 22 Dec 2019 16:58:54 +0000 (22:28 +0530)
committerShivani Bhardwaj <shivanib134@gmail.com>
Fri, 27 Mar 2020 21:20:12 +0000 (02:50 +0530)
StringParse* functions would perform a stricter check compared to
ByteExtractString* functions. These new functions shall also check if
any extra characters follow the extracted numeric value in addition to
the checks performed by ByteExtractString* and return -1 in that case.
This is particularly important in parser, configuration and setup functions.

src/util-byte.c
src/util-byte.h

index a57fecaf27eada122e3405b787d94605dc9fc632..66c9fa9e88705faeef49601262d0841f3e4f93e6 100644 (file)
@@ -182,7 +182,7 @@ int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
     return ret;
 }
 
-int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str)
+int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str, bool strict)
 {
     const char *ptr = str;
     char *endptr = NULL;
@@ -223,29 +223,24 @@ int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str)
         SCLogDebug("invalid numeric value");
         return -1;
     }
-    /* This will interfere with some rules that do not know the length
-     * in advance and instead are just using the max.
-     */
-#if 0
-    else if (len && *endptr != '\0') {
-        fprintf(stderr, "ByteExtractString: Extra characters following numeric value\n");
+    else if (strict && len && *endptr != '\0') {
+        SCLogError(SC_ERR_INVALID_NUMERIC_VALUE, "Extra characters following numeric value");
         return -1;
     }
-#endif
 
     return (endptr - ptr);
 }
 
 int ByteExtractStringUint64(uint64_t *res, int base, uint16_t len, const char *str)
 {
-    return ByteExtractString(res, base, len, str);
+    return ByteExtractString(res, base, len, str, false);
 }
 
 int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
 {
     uint64_t i64;
 
-    int ret = ByteExtractString(&i64, base, len, str);
+    int ret = ByteExtractString(&i64, base, len, str, false);
     if (ret <= 0) {
         return ret;
     }
@@ -265,7 +260,7 @@ int ByteExtractStringUint16(uint16_t *res, int base, uint16_t len, const char *s
 {
     uint64_t i64;
 
-    int ret = ByteExtractString(&i64, base, len, str);
+    int ret = ByteExtractString(&i64, base, len, str, false);
     if (ret <= 0) {
         return ret;
     }
@@ -285,7 +280,7 @@ int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str
 {
     uint64_t i64;
 
-    int ret = ByteExtractString(&i64, base, len, str);
+    int ret = ByteExtractString(&i64, base, len, str, false);
     if (ret <= 0) {
         return ret;
     }
@@ -301,7 +296,71 @@ int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str
     return ret;
 }
 
-int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str)
+int StringParseUint64(uint64_t *res, int base, uint16_t len, const char *str)
+{
+    return ByteExtractString(res, base, len, str, true);
+}
+
+int StringParseUint32(uint32_t *res, int base, uint16_t len, const char *str)
+{
+    uint64_t i64;
+
+    int ret = ByteExtractString(&i64, base, len, str, true);
+    if (ret <= 0) {
+        return ret;
+    }
+
+    *res = (uint32_t)i64;
+
+    if ((uint64_t)(*res) != i64) {
+        SCLogError("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
+                i64, (uintmax_t)UINT_MAX);
+        return -1;
+    }
+
+    return ret;
+}
+
+int StringParseUint16(uint16_t *res, int base, uint16_t len, const char *str)
+{
+    uint64_t i64;
+
+    int ret = ByteExtractString(&i64, base, len, str, true);
+    if (ret <= 0) {
+        return ret;
+    }
+
+    *res = (uint16_t)i64;
+
+    if ((uint64_t)(*res) != i64) {
+        SCLogError("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
+                i64, (uintmax_t)USHRT_MAX);
+        return -1;
+    }
+
+    return ret;
+}
+
+int StringParseUint8(uint8_t *res, int base, uint16_t len, const char *str)
+{
+    uint64_t i64;
+
+    int ret = ByteExtractString(&i64, base, len, str, true);
+    if (ret <= 0) {
+        return ret;
+    }
+
+    *res = (uint8_t)i64;
+
+    if ((uint64_t)(*res) != i64) {
+        SCLogError("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
+                i64, (uintmax_t)UCHAR_MAX);
+        return -1;
+    }
+
+    return ret;
+}
+int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str, bool strict)
 {
     const char *ptr = str;
     char *endptr;
@@ -337,15 +396,10 @@ int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *st
         SCLogError(SC_ERR_INVALID_NUMERIC_VALUE, "Invalid numeric value");
         return -1;
     }
-    /* This will interfere with some rules that do not know the length
-     * in advance and instead are just using the max.
-     */
-#if 0
-    else if (len && *endptr != '\0') {
-        fprintf(stderr, "ByteExtractStringSigned: Extra characters following numeric value\n");
+    else if (strict && len && *endptr != '\0') {
+        SCLogError(SC_ERR_INVALID_NUMERIC_VALUE, "Extra characters following numeric value");
         return -1;
     }
-#endif
 
     //fprintf(stderr, "ByteExtractStringSigned: Extracted base %d: 0x%" PRIx64 "\n", base, *res);
 
@@ -354,7 +408,7 @@ int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *st
 
 int ByteExtractStringInt64(int64_t *res, int base, uint16_t len, const char *str)
 {
-    return ByteExtractStringSigned(res, base, len, str);
+    return ByteExtractStringSigned(res, base, len, str, false);
 }
 
 int ByteExtractStringInt32(int32_t *res, int base, uint16_t len, const char *str)
@@ -362,7 +416,7 @@ int ByteExtractStringInt32(int32_t *res, int base, uint16_t len, const char *str
     int64_t i64;
     int ret;
 
-    ret = ByteExtractStringSigned(&i64, base, len, str);
+    ret = ByteExtractStringSigned(&i64, base, len, str, false);
     if (ret <= 0) {
         return ret;
     }
@@ -383,7 +437,7 @@ int ByteExtractStringInt16(int16_t *res, int base, uint16_t len, const char *str
     int64_t i64;
     int ret;
 
-    ret = ByteExtractStringSigned(&i64, base, len, str);
+    ret = ByteExtractStringSigned(&i64, base, len, str, false);
     if (ret <= 0) {
         return ret;
     }
@@ -404,7 +458,7 @@ int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str)
     int64_t i64;
     int ret;
 
-    ret = ByteExtractStringSigned(&i64, base, len, str);
+    ret = ByteExtractStringSigned(&i64, base, len, str, false);
     if (ret <= 0) {
         return ret;
     }
@@ -420,6 +474,73 @@ int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str)
     return ret;
 }
 
+int StringParseInt64(int64_t *res, int base, uint16_t len, const char *str)
+{
+    return ByteExtractStringSigned(res, base, len, str, true);
+}
+
+int StringParseInt32(int32_t *res, int base, uint16_t len, const char *str)
+{
+    int64_t i64;
+    int ret;
+
+    ret = ByteExtractStringSigned(&i64, base, len, str, true);
+    if (ret <= 0) {
+        return ret;
+    }
+
+    *res = (int32_t)i64;
+
+    if ((int64_t)(*res) != i64) {
+        SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
+                   "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)INT_MAX);
+        return -1;
+    }
+
+    return ret;
+}
+
+int StringParseInt16(int16_t *res, int base, uint16_t len, const char *str)
+{
+    int64_t i64;
+    int ret;
+
+    ret = ByteExtractStringSigned(&i64, base, len, str, true);
+    if (ret <= 0) {
+        return ret;
+    }
+
+    *res = (int16_t)i64;
+
+    if ((int64_t)(*res) != i64) {
+        SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
+                   "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)SHRT_MAX);
+        return -1;
+    }
+
+    return ret;
+}
+
+int StringParseInt8(int8_t *res, int base, uint16_t len, const char *str)
+{
+    int64_t i64;
+    int ret;
+
+    ret = ByteExtractStringSigned(&i64, base, len, str, true);
+    if (ret <= 0) {
+        return ret;
+    }
+
+    *res = (int8_t)i64;
+
+    if ((int64_t)(*res) != i64) {
+        SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
+                   "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)CHAR_MAX);
+        return -1;
+    }
+
+    return ret;
+}
 /* UNITTESTS */
 #ifdef UNITTESTS
 
index 7c09952bafe27a1c14c0ed368dafa7b95424e464..621f4cd5837328ebb6876fff057828f36c6f4823 100644 (file)
@@ -129,11 +129,12 @@ int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes);
  * \param base Base of the number to extract
  * \param len Number of bytes to extract (23 max or 0 for unbounded)
  * \param str String to extract from
+ * \param bool Enable strict check for parsers
  *
  * \return n Number of bytes extracted on success
  * \return -1 On error
  */
-int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str);
+int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str, bool strict);
 
 /**
  * Extract unsigned integer value from a string as uint64_t.
@@ -195,11 +196,12 @@ int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str
  * \param base Base of the number to extract
  * \param len Number of bytes to extract (23 max or 0 for unbounded)
  * \param str String to extract from
+ * \param bool Enable strict check for parsers
  *
  * \return n Number of bytes extracted on success
  * \return -1 On error
  */
-int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str);
+int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str, bool strict);
 
 /**
  * Extract signed integer value from a string as uint64_t.
@@ -253,6 +255,111 @@ int ByteExtractStringInt16(int16_t *res, int base, uint16_t len, const char *str
  */
 int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str);
 
+/**
+ * Extract unsigned integer value from a string as uint64_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param len Number of bytes to extract (23 max)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseUint64(uint64_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract unsigned integer value from a string as uint32_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseUint32(uint32_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract unsigned integer value from a string as uint16_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseUint16(uint16_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract unsigned integer value from a string as uint8_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseUint8(uint8_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract signed integer value from a string as int64_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseInt64(int64_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract signed integer value from a string as int32_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseInt32(int32_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract signed integer value from a string as int16_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseInt16(int16_t *res, int base, uint16_t len, const char *str);
+
+/**
+ * Extract signed integer value from a string as int8_t strictly.
+ *
+ * \param res Stores result
+ * \param base Base of the number to extract
+ * \param len Number of bytes to extract (23 max or 0 for unbounded)
+ * \param str String to extract from
+ *
+ * \return n Number of bytes extracted on success
+ * \return -1 On error
+ */
+int StringParseInt8(int8_t *res, int base, uint16_t len, const char *str);
+
 #ifdef UNITTESTS
 void ByteRegisterTests(void);
 #endif /* UNITTESTS */