diff --git a/src/libstrongswan/collections/array.c b/src/libstrongswan/collections/array.c index 0543ca24e..46d473414 100644 --- a/src/libstrongswan/collections/array.c +++ b/src/libstrongswan/collections/array.c @@ -310,11 +310,30 @@ void array_insert_enumerator(array_t *array, int idx, enumerator_t *enumerator) enumerator->destroy(enumerator); } +/** + * Check if the given pointer points to an array element + */ +static bool is_in_array(array_t *array, void *ptr) +{ + return array->data && ptr >= array->data && + ptr < array->data + get_size(array, array->head + array->count + + array->tail); +} + void array_insert(array_t *array, int idx, void *data) { if (idx < 0 || idx <= array_count(array)) { - void *pos; + void *buf, *pos, *src = data; + + /* create a local copy if the source is another element in the array. + * due to the resizing/moving, it might get invalid */ + if (array->esize && is_in_array(array, data)) + { + buf = alloca(array->esize); + memcpy(buf, data, array->esize); + src = buf; + } if (idx < 0) { @@ -341,7 +360,7 @@ void array_insert(array_t *array, int idx, void *data) pos = array->data + get_size(array, array->head + idx); if (array->esize) { - memcpy(pos, data, get_size(array, 1)); + memcpy(pos, src, array->esize); } else { diff --git a/src/libstrongswan/collections/array.h b/src/libstrongswan/collections/array.h index d9924c34a..113e51fb4 100644 --- a/src/libstrongswan/collections/array.h +++ b/src/libstrongswan/collections/array.h @@ -113,7 +113,8 @@ void array_remove_at(array_t *array, enumerator_t *enumerator); * Insert an element to an array. * * If the array is pointer based (esize = 0), the pointer itself is appended. - * Otherwise the element gets copied from the pointer. + * Otherwise, the element gets copied from the pointer. + * * The idx must be either within array_count() or one above to append the item. * Passing -1 has the same effect as passing array_count(), i.e. appends the * item. It is always valid to pass idx 0 to prepend the item.