vppinfra: fix mhash oob after unset and add tests

Fix out of buffer access after mhash_unset
Add format mhash pair functions
Add related mhash tests, similar to hash ones

Type: fix
Signed-off-by: Vladislav Grishenko <themiron@yandex-team.ru>
Change-Id: Idbefd7d32c4cd16b55d84ad4006c38251b4e2c33
This commit is contained in:
Vladislav Grishenko
2023-12-14 17:48:28 +01:00
committed by Damjan Marion
parent 2f5d094ddd
commit 703289224c
5 changed files with 455 additions and 7 deletions

View File

@ -265,6 +265,7 @@ if(VPP_BUILD_VPPINFRA_TESTS)
longjmp
macros
maplog
mhash
pmalloc
pool_alloc
pool_iterate

View File

@ -680,6 +680,7 @@ debug_elt (u8 * s, void *v, word i, word n)
i = -n / 2;
for (e = e0; 1; e = heap_next (e))
{
s = format (s, " ");
if (heap_is_free (e))
s = format (s, "index %4d, free\n", e - h->elts);
else if (h->format_elt)

View File

@ -164,6 +164,8 @@ mhash_sanitize_hash_user (mhash_t * mh)
h->user = pointer_to_uword (mh);
}
static u8 *mhash_format_pair_default (u8 *s, va_list *args);
__clib_export void
mhash_init (mhash_t * h, uword n_value_bytes, uword n_key_bytes)
{
@ -208,12 +210,12 @@ mhash_init (mhash_t * h, uword n_value_bytes, uword n_key_bytes)
vec_validate (h->key_tmps, os_get_nthreads () - 1);
ASSERT (n_key_bytes < ARRAY_LEN (t));
h->hash = hash_create2 ( /* elts */ 0,
h->hash = hash_create2 (/* elts */ 0,
/* user */ pointer_to_uword (h),
/* value_bytes */ n_value_bytes,
t[n_key_bytes].key_sum, t[n_key_bytes].key_equal,
/* format pair/arg */
0, 0);
mhash_format_pair_default, 0);
}
static uword
@ -331,8 +333,8 @@ mhash_set_mem (mhash_t * h, void *key, uword * new_value, uword * old_value)
{
if (key_alloc_from_free_list)
{
h->key_vector_free_indices[l] = i;
vec_set_len (h->key_vector_free_indices, l + 1);
vec_set_len (h->key_vector_free_indices, l);
h->key_vector_free_indices[l - 1] = i;
}
else
vec_dec_len (h->key_vector_or_heap, h->n_key_bytes);
@ -371,8 +373,8 @@ mhash_unset (mhash_t * h, void *key, uword * old_value)
return 1;
}
u8 *
format_mhash_key (u8 * s, va_list * va)
__clib_export u8 *
format_mhash_key (u8 *s, va_list *va)
{
mhash_t *h = va_arg (*va, mhash_t *);
u32 ki = va_arg (*va, u32);
@ -387,7 +389,43 @@ format_mhash_key (u8 * s, va_list * va)
else if (h->format_key)
s = format (s, "%U", h->format_key, k);
else
s = format (s, "%U", format_hex_bytes, k, h->n_key_bytes);
s = format (s, "0x%U", format_hex_bytes, k, h->n_key_bytes);
return s;
}
static u8 *
mhash_format_pair_default (u8 *s, va_list *args)
{
void *CLIB_UNUSED (user_arg) = va_arg (*args, void *);
void *v = va_arg (*args, void *);
hash_pair_t *p = va_arg (*args, hash_pair_t *);
hash_t *h = hash_header (v);
mhash_t *mh = uword_to_pointer (h->user, mhash_t *);
s = format (s, "%U", format_mhash_key, mh, (u32) p->key);
if (hash_value_bytes (h) > 0)
s = format (s, " -> 0x%8U", format_hex_bytes, &p->value[0],
hash_value_bytes (h));
return s;
}
__clib_export u8 *
format_mhash (u8 *s, va_list *va)
{
mhash_t *h = va_arg (*va, mhash_t *);
int verbose = va_arg (*va, int);
s = format (s, "mhash %p, %wd elts, \n", h, mhash_elts (h));
if (mhash_key_vector_is_heap (h))
s = format (s, " %U", format_heap, h->key_vector_or_heap, verbose);
else
s = format (s, " keys %wd elts, %wd size, %wd free, %wd bytes used\n",
vec_len (h->key_vector_or_heap) / h->n_key_bytes,
h->n_key_bytes, vec_len (h->key_vector_free_indices),
vec_bytes (h->key_vector_or_heap) +
vec_bytes (h->key_vector_free_indices));
s = format (s, " %U", format_hash, h->hash, verbose);
return s;
}

View File

@ -166,8 +166,13 @@ do { \
})); \
} while (0)
u8 *format_mhash (u8 *s, va_list *va);
format_function_t format_mhash_key;
/* Main test routine. */
int test_mhash_main (unformat_input_t *input);
#endif /* included_clib_mhash_h */
/*

403
src/vppinfra/test_mhash.c Normal file

File diff suppressed because it is too large Load Diff