SYMNAME_HASH_INDEX is used as the index of symname hash table. It will be out of range if SYMNAME_HASH_INDEX is negative. This patch avoids the risk by changing the marco into a function, and casting and calculating the numbers as unsigned. Suggested-by: Lianbo Jiang <lijiang@xxxxxxxxxx> Suggested-by: Philipp Rudo <prudo@xxxxxxxxxx> Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- defs.h | 2 -- symbols.c | 31 +++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/defs.h b/defs.h index bbdca79..8b356d5 100644 --- a/defs.h +++ b/defs.h @@ -2728,8 +2728,6 @@ struct downsized { (((vaddr) >> machdep->pageshift) % SYMVAL_HASH) #define SYMNAME_HASH (512) -#define SYMNAME_HASH_INDEX(name) \ - ((name[0] ^ (name[strlen(name)-1] * name[strlen(name)/2])) % SYMNAME_HASH) #define PATCH_KERNEL_SYMBOLS_START ((char *)(1)) #define PATCH_KERNEL_SYMBOLS_STOP ((char *)(2)) diff --git a/symbols.c b/symbols.c index b62be1b..fc0e9f6 100644 --- a/symbols.c +++ b/symbols.c @@ -1127,6 +1127,21 @@ symname_hash_init(void) st->__per_cpu_end = sp->value; } +static unsigned int +symname_hash_index(char *name) +{ + unsigned int len, value; + unsigned char *array = (unsigned char *)name; + + len = strlen(name); + if (!len) + error(FATAL, "The length of the symbol name is zero!\n"); + + value = array[len - 1] * array[len / 2]; + + return (array[0] ^ value) % SYMNAME_HASH; +} + /* * Install a single static kernel symbol into the symname_hash. */ @@ -1134,9 +1149,9 @@ static void symname_hash_install(struct syment *spn) { struct syment *sp; - int index; + unsigned int index; - index = SYMNAME_HASH_INDEX(spn->name); + index = symname_hash_index(spn->name); spn->cnt = 1; if ((sp = st->symname_hash[index]) == NULL) @@ -1164,12 +1179,12 @@ static void mod_symname_hash_install(struct syment *spn) { struct syment *sp, *tmp; - int index; + unsigned int index; if (!spn) return; - index = SYMNAME_HASH_INDEX(spn->name); + index = symname_hash_index(spn->name); sp = st->mod_symname_hash[index]; @@ -1204,12 +1219,12 @@ static void mod_symname_hash_remove(struct syment *spn) { struct syment *sp; - int index; + unsigned int index; if (!spn) return; - index = SYMNAME_HASH_INDEX(spn->name); + index = symname_hash_index(spn->name); if (st->mod_symname_hash[index] == spn) st->mod_symname_hash[index] = spn->name_hash_next; @@ -1246,7 +1261,7 @@ symname_hash_search(struct syment *table[], char *name) { struct syment *sp; - sp = table[SYMNAME_HASH_INDEX(name)]; + sp = table[symname_hash_index(name)]; while (sp) { if (STREQ(sp->name, name)) @@ -4589,7 +4604,7 @@ symbol_search(char *s) return(sp); } - sp = st->mod_symname_hash[SYMNAME_HASH_INDEX(s)]; + sp = st->mod_symname_hash[symname_hash_index(s)]; while (sp) { if (skip_symbols(sp, s)) { sp = sp->name_hash_next; -- 2.29.2 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility