mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-29 18:19:30 +00:00
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
This commit is contained in:
committed by
Torrey Searle
parent
2b8dbc9e00
commit
7901225261
@@ -26,6 +26,7 @@
|
|||||||
/* #define DEBUG_OPAQUE */
|
/* #define DEBUG_OPAQUE */
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "asterisk/utils.h"
|
#include "asterisk/utils.h"
|
||||||
#include "asterisk/threadstorage.h"
|
#include "asterisk/threadstorage.h"
|
||||||
@@ -1173,6 +1174,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
|
* \brief Compute a hash value on a string
|
||||||
*
|
*
|
||||||
@@ -1183,20 +1197,21 @@ char *ast_tech_to_upper(char *dev_str),
|
|||||||
*/
|
*/
|
||||||
static force_inline int attribute_pure ast_str_hash(const char *str)
|
static force_inline int attribute_pure ast_str_hash(const char *str)
|
||||||
{
|
{
|
||||||
int hash = 5381;
|
unsigned int hash = 5381;
|
||||||
|
|
||||||
while (*str)
|
while (*str) {
|
||||||
hash = hash * 33 ^ *str++;
|
hash = hash * 33 ^ (unsigned char) *str++;
|
||||||
|
}
|
||||||
|
|
||||||
return abs(hash);
|
return ast_str_hash_restrict(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Compute a hash value on a string
|
* \brief Compute a hash value on a string
|
||||||
*
|
*
|
||||||
* \param[in] str The string to add to the hash
|
* \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
|
* \details
|
||||||
* This version of the function is for when you need to compute a
|
* This version of the function is for when you need to compute a
|
||||||
* string hash of more than one string.
|
* 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
|
* \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)
|
unsigned int hash = (unsigned int) seed;
|
||||||
hash = hash * 33 ^ *str++;
|
|
||||||
|
|
||||||
return abs(hash);
|
while (*str) {
|
||||||
|
hash = hash * 33 ^ (unsigned char) *str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
static force_inline int attribute_pure ast_str_case_hash(const char *str)
|
||||||
{
|
{
|
||||||
int hash = 5381;
|
unsigned int hash = 5381;
|
||||||
|
|
||||||
while (*str) {
|
while (*str) {
|
||||||
hash = hash * 33 ^ tolower(*str++);
|
hash = hash * 33 ^ (unsigned char) tolower(*str++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return abs(hash);
|
return ast_str_hash_restrict(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Reference in New Issue
Block a user