diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index d249f22676..ad4c778ea3 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -19,6 +19,23 @@ const char *si_prefix(unsigned int exp10); */ const char *iec_binary_prefix(unsigned int exp2); +const char *str_array_elem_or_null(const char *const *array, + size_t nelem, uint64_t index); + +/** + * STR_ARRAY_ELEM_OR_NULL() - Return a string array element, or NULL if + * out of bounds + * @array: array of strings to index + * @index: index of the element to return + * + * Return @array[@index] if @index is a valid index, otherwise return + * NULL. @index is converted to uint64_t, so negative values of signed + * types are out of bounds and also yield NULL. Useful to look up entries + * in enum-indexed string tables without a prior bounds check. + */ +#define STR_ARRAY_ELEM_OR_NULL(array, index) \ + str_array_elem_or_null(array, ARRAY_SIZE(array), index) + /** * pstrcpy: * @buf: buffer to copy string into diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 5d5695ade2..50c7ce33b6 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -532,6 +532,9 @@ void QEMU_ERROR("code path is reachable") * ARRAY_SIZE() - Return the number of elements of an array * @x: the array * + * For bounds-checked lookups in arrays of strings, see + * STR_ARRAY_ELEM_OR_NULL() in "qemu/cutils.h". + * * Note: fails to build if @x is a pointer. */ #ifndef ARRAY_SIZE diff --git a/util/cutils.c b/util/cutils.c index 91ddadfd15..d8a04ead5a 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -954,6 +954,12 @@ const char *iec_binary_prefix(unsigned int exp2) return prefixes[exp2 / 10]; } +const char *str_array_elem_or_null(const char *const *array, + size_t nelem, uint64_t index) +{ + return index >= nelem ? NULL : array[index]; +} + /* * Return human readable string for size @val. * @val can be anything that uint64_t allows (no more than "16 EiB").