aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Valter <d-valter@yandex-team.com>2024-01-05 14:28:08 +0000
committerDamjan Marion <dmarion@0xa5.net>2024-01-19 12:37:49 +0000
commit8263888f463b566e77e8243763e05c35d20bb4d7 (patch)
tree302e307694b9a8e410c60a6f61b59273cbde345a
parentc60266d1ea9604f4651092d79bed8ec0b571544a (diff)
vppinfra: fix vec_prepend use-after-free
Don't access free'd memory in vec_prepend. Don't allow prepend when v1 == v2 as it also causes a use-after-free. Found via ASAN. Type: fix Signed-off-by: Dmitry Valter <d-valter@yandex-team.com> Change-Id: I21f8422c007d07d40d237e873b84c042be1fe8e8
-rw-r--r--src/vppinfra/vec.h16
1 files changed, 9 insertions, 7 deletions
diff --git a/src/vppinfra/vec.h b/src/vppinfra/vec.h
index 607fc282897..1a64a69a1e6 100644
--- a/src/vppinfra/vec.h
+++ b/src/vppinfra/vec.h
@@ -1067,26 +1067,28 @@ _vec_append (void **v1p, void *v2, uword v1_elt_sz, uword v2_elt_sz,
#define vec_append(v1, v2) vec_append_aligned (v1, v2, 0)
static_always_inline void
-_vec_prepend (void **v1p, void *v2, uword v1_elt_sz, uword v2_elt_sz,
- uword align)
+_vec_prepend (void *restrict *v1p, void *restrict v2, uword v1_elt_sz,
+ uword v2_elt_sz, uword align)
{
- void *v1 = v1p[0];
+ void *restrict v1 = v1p[0];
uword len1 = vec_len (v1);
uword len2 = vec_len (v2);
if (PREDICT_TRUE (len2 > 0))
{
+ /* prepending vector to itself would result in use-after-free */
+ ASSERT (v1 != v2);
const vec_attr_t va = { .elt_sz = v2_elt_sz, .align = align };
v1 = _vec_resize_internal (v1, len1 + len2, &va);
- clib_memmove (v1 + len2 * v2_elt_sz, v1p[0], len1 * v1_elt_sz);
+ clib_memmove (v1 + len2 * v2_elt_sz, v1, len1 * v1_elt_sz);
clib_memcpy_fast (v1, v2, len2 * v2_elt_sz);
- _vec_update_pointer (v1p, v1);
+ _vec_update_pointer ((void **) v1p, v1);
}
}
/** \brief Prepend v2 before v1. Result in v1. Specified alignment
@param V1 target vector
- @param V2 vector to prepend
+ @param V2 vector to prepend, V1 != V2
@param align required alignment
*/
@@ -1096,7 +1098,7 @@ _vec_prepend (void **v1p, void *v2, uword v1_elt_sz, uword v2_elt_sz,
/** \brief Prepend v2 before v1. Result in v1.
@param V1 target vector
- @param V2 vector to prepend
+ @param V2 vector to prepend, V1 != V2
*/
#define vec_prepend(v1, v2) vec_prepend_aligned (v1, v2, 0)