From: Shivani Bhardwaj Date: Sun, 22 Dec 2019 16:58:54 +0000 (+0530) Subject: util: Add StringParse* functions X-Git-Tag: suricata-6.0.0-beta1~589 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b2c7d5be845e1d8a09d39ff1c397e732e2df8c1;p=thirdparty%2Fsuricata.git util: Add StringParse* functions 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. --- diff --git a/src/util-byte.c b/src/util-byte.c index a57fecaf27..66c9fa9e88 100644 --- a/src/util-byte.c +++ b/src/util-byte.c @@ -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 diff --git a/src/util-byte.h b/src/util-byte.h index 7c09952baf..621f4cd583 100644 --- a/src/util-byte.h +++ b/src/util-byte.h @@ -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 */