summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorrey Searle <torrey@voxbone.com>2017-04-07 15:58:23 +0200
committerTorrey Searle <tsearle@gmail.com>2017-04-11 13:34:28 -0500
commit7901225261653b5f883abdafaeb6ab47eb685a3e (patch)
treeea4128a8e55f008b8ab7144aaba9a9b6ab22e2f9
parent2b8dbc9e00094ad0913fa56580266086fc120f3c (diff)
strings.h: Avoid overflows in the string hash functions
On 2's compliment machines abs(INT_MIN) behavior is undefined and results in a negative value still being returnd. This results in negative hash codes that can result in crashes. ASTERISK-26528 #close Change-Id: Idff550145ca2133792a61a2e212b4a3e82c6517b
-rw-r--r--include/asterisk/strings.h44
1 files changed, 31 insertions, 13 deletions
diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h
index eb5b4e43c..1200eb983 100644
--- a/include/asterisk/strings.h
+++ b/include/asterisk/strings.h
@@ -26,6 +26,7 @@
/* #define DEBUG_OPAQUE */
#include <ctype.h>
+#include <limits.h>
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
@@ -1174,6 +1175,19 @@ char *ast_tech_to_upper(char *dev_str),
)
/*!
+ * \brief Restrict hash value range
+ *
+ * \details
+ * Hash values used all over asterisk are expected to be non-negative
+ * (signed) int values. This function restricts an unsigned int hash
+ * value to the positive half of the (signed) int values.
+ */
+static force_inline int attribute_pure ast_str_hash_restrict(unsigned int hash)
+{
+ return (int) (hash & (unsigned int) INT_MAX);
+}
+
+/*!
* \brief Compute a hash value on a string
*
* This famous hash algorithm was written by Dan Bernstein and is
@@ -1183,20 +1197,21 @@ char *ast_tech_to_upper(char *dev_str),
*/
static force_inline int attribute_pure ast_str_hash(const char *str)
{
- int hash = 5381;
+ unsigned int hash = 5381;
- while (*str)
- hash = hash * 33 ^ *str++;
+ while (*str) {
+ hash = hash * 33 ^ (unsigned char) *str++;
+ }
- return abs(hash);
+ return ast_str_hash_restrict(hash);
}
/*!
* \brief Compute a hash value on a string
*
* \param[in] str The string to add to the hash
- * \param[in] hash The hash value to add to
- *
+ * \param[in] seed The hash value to start with
+ *
* \details
* This version of the function is for when you need to compute a
* string hash of more than one string.
@@ -1206,12 +1221,15 @@ static force_inline int attribute_pure ast_str_hash(const char *str)
*
* \sa http://www.cse.yorku.ca/~oz/hash.html
*/
-static force_inline int ast_str_hash_add(const char *str, int hash)
+static force_inline int ast_str_hash_add(const char *str, int seed)
{
- while (*str)
- hash = hash * 33 ^ *str++;
+ unsigned int hash = (unsigned int) seed;
+
+ while (*str) {
+ hash = hash * 33 ^ (unsigned char) *str++;
+ }
- return abs(hash);
+ return ast_str_hash_restrict(hash);
}
/*!
@@ -1223,13 +1241,13 @@ static force_inline int ast_str_hash_add(const char *str, int hash)
*/
static force_inline int attribute_pure ast_str_case_hash(const char *str)
{
- int hash = 5381;
+ unsigned int hash = 5381;
while (*str) {
- hash = hash * 33 ^ tolower(*str++);
+ hash = hash * 33 ^ (unsigned char) tolower(*str++);
}
- return abs(hash);
+ return ast_str_hash_restrict(hash);
}
/*!