attractivechaos / klib

A standalone and lightweight C library

Home Page:http://attractivechaos.github.io/klib/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

khashl - Out of bounds memory read when querying an element not in hash table.

7PintsOfCherryGarcia opened this issue · comments

Valgrind is throwing an "invalid read" when querying if an element not in a hash is present in a hash table.

The following code produces the error:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "klib/khashl.h"
KHASHL_MAP_INIT(static,
                intmap_t, intmap,
                uint64_t, uint32_t,
                kh_hash_uint64,
                kh_eq_generic)

int main()
{
    intmap_t *map = intmap_init();
    khint_t itr;
    int absent;
    for (uint64_t i = 0; i < 100; i++) {
        itr = intmap_put(map, i, &absent);
        kh_val(map, itr) = (uint32_t)(i+1);
    }
    fprintf(stderr, "size: %u\n", kh_size(map));
    for (uint64_t i = 95; i < 105; i++) {
        itr = intmap_get(map, i);
        fprintf(stderr, "%lu exits? %s\n", i , kh_exist(map, itr) ? "yes" : "no");
    }
    intmap_destroy(map);
}

The error:

gcc -Wall -Wextra -pedantic -Ilib -o tmp tmp.c
valgrind --leak-check=yes ./tmp
 memory error detector
==14974== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14974== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==14974== Command: ./tmp
==14974==
size: 100
95 exits? yes
96 exits? yes
97 exits? yes
98 exits? yes
99 exits? yes
==14974== Invalid read of size 4
==14974==    at 0x109EA8: main (tmp.c:23)
==14974==  Address 0x4a5cff0 is 0 bytes after a block of size 32 alloc'd
==14974==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==14974==    by 0x109551: intmap_m_resize (tmp.c:5)
==14974==    by 0x109968: intmap_m_putp (tmp.c:5)
==14974==    by 0x109DBD: intmap_put (tmp.c:5)
==14974==    by 0x109E18: main (tmp.c:17)
==14974==
100 exits? no
101 exits? no
102 exits? no
103 exits? no
104 exits? no
==14974==
==14974== HEAP SUMMARY:
==14974==     in use at exit: 0 bytes in 0 blocks
==14974==   total heap usage: 15 allocs, 15 frees, 6,192 bytes allocated
==14974==
==14974== All heap blocks were freed -- no leaks are possible
==14974==
==14974== For lists of detected and suppressed errors, rerun with: -s
==14974== ERROR SUMMARY: 5 errors from 1 contexts (suppressed: 0 from 0)

I suspect the error resides in ##_getp but not sure how to fix it, I will keep giving it a try.

The right way to test itr == kh_end(map). kh_exist() is only used when you iterate a hash table. I know the naming is confusing. Sorry for that.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "klib/khashl.h"
KHASHL_MAP_INIT(static,
                intmap_t, intmap,
                uint64_t, uint32_t,
                kh_hash_uint64,
                kh_eq_generic)

int main()
{
    intmap_t *map = intmap_init();
    khint_t itr;
    int absent;
    for (uint64_t i = 0; i < 100; i++) {
        itr = intmap_put(map, i, &absent);
        kh_val(map, itr) = (uint32_t)(i+1);
    }
    fprintf(stderr, "size: %u\n", kh_size(map));
    for (uint64_t i = 95; i < 105; i++) {
        itr = intmap_get(map, i);
        fprintf(stderr, "%lu exits? %s\n", i , itr == kh_end(map) ? "yes" : "no");
    }
    intmap_destroy(map);
}