While debugging startup issues encountered with Clang (see "eal: fix
undefined behavior in fbarray"), I noticed that fbarray stores indices,
sizes and masks on signed integers involved in bitwise operations.
Such operations almost invariably cause undefined behavior with values that
cannot be represented by the result type, as is often the case with
bit-masks and left-shifts.
This patch replaces them with unsigned integers as a safety measure and
promotes a few internal variables to larger types for consistency.
Coverity issue: 272598, 272599
Fixes:
c44d09811b40 ("eal: add shared indexed file-backed array")
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
#include <sys/mman.h>
#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdint.h>
#include <errno.h>
#include "rte_fbarray.h"
#define MASK_SHIFT 6ULL
#include "rte_fbarray.h"
#define MASK_SHIFT 6ULL
-#define MASK_ALIGN (1 << MASK_SHIFT)
+#define MASK_ALIGN (1ULL << MASK_SHIFT)
#define MASK_LEN_TO_IDX(x) ((x) >> MASK_SHIFT)
#define MASK_LEN_TO_MOD(x) ((x) - RTE_ALIGN_FLOOR(x, MASK_ALIGN))
#define MASK_GET_IDX(idx, mod) ((idx << MASK_SHIFT) + mod)
#define MASK_LEN_TO_IDX(x) ((x) >> MASK_SHIFT)
#define MASK_LEN_TO_MOD(x) ((x) - RTE_ALIGN_FLOOR(x, MASK_ALIGN))
#define MASK_GET_IDX(idx, mod) ((idx << MASK_SHIFT) + mod)
uint64_t data[];
};
static size_t
uint64_t data[];
};
static size_t
+calc_mask_size(unsigned int len)
{
/* mask must be multiple of MASK_ALIGN, even though length of array
* itself may not be aligned on that boundary.
{
/* mask must be multiple of MASK_ALIGN, even though length of array
* itself may not be aligned on that boundary.
-calc_data_size(size_t page_sz, int elt_sz, int len)
+calc_data_size(size_t page_sz, unsigned int elt_sz, unsigned int len)
{
size_t data_sz = elt_sz * len;
size_t msk_sz = calc_mask_size(len);
{
size_t data_sz = elt_sz * len;
size_t msk_sz = calc_mask_size(len);
}
static struct used_mask *
}
static struct used_mask *
-get_used_mask(void *data, int elt_sz, int len)
+get_used_mask(void *data, unsigned int elt_sz, unsigned int len)
{
return (struct used_mask *) RTE_PTR_ADD(data, elt_sz * len);
}
{
return (struct used_mask *) RTE_PTR_ADD(data, elt_sz * len);
}
-find_next_n(const struct rte_fbarray *arr, int start, int n, bool used)
+find_next_n(const struct rte_fbarray *arr, unsigned int start, unsigned int n,
+ bool used)
{
const struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz,
arr->len);
{
const struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz,
arr->len);
- int msk_idx, lookahead_idx, first, first_mod;
- int last, last_mod, last_msk;
- uint64_t ignore_msk;
+ unsigned int msk_idx, lookahead_idx, first, first_mod;
+ unsigned int last, last_mod;
+ uint64_t last_msk, ignore_msk;
/*
* mask only has granularity of MASK_ALIGN, but start may not be aligned
/*
* mask only has granularity of MASK_ALIGN, but start may not be aligned
*/
last = MASK_LEN_TO_IDX(arr->len);
last_mod = MASK_LEN_TO_MOD(arr->len);
*/
last = MASK_LEN_TO_IDX(arr->len);
last_mod = MASK_LEN_TO_MOD(arr->len);
- last_msk = ~(-(1ULL) << last_mod);
+ last_msk = ~(-1ULL << last_mod);
for (msk_idx = first; msk_idx < msk->n_masks; msk_idx++) {
uint64_t cur_msk, lookahead_msk;
for (msk_idx = first; msk_idx < msk->n_masks; msk_idx++) {
uint64_t cur_msk, lookahead_msk;
- int run_start, clz, left;
+ unsigned int run_start, clz, left;
bool found = false;
/*
* The process of getting n consecutive bits for arbitrary n is
bool found = false;
/*
* The process of getting n consecutive bits for arbitrary n is
/* if n can fit in within a single mask, do a search */
if (n <= MASK_ALIGN) {
uint64_t tmp_msk = cur_msk;
/* if n can fit in within a single mask, do a search */
if (n <= MASK_ALIGN) {
uint64_t tmp_msk = cur_msk;
for (s_idx = 0; s_idx < n - 1; s_idx++)
tmp_msk &= tmp_msk >> 1ULL;
/* we found what we were looking for */
for (s_idx = 0; s_idx < n - 1; s_idx++)
tmp_msk &= tmp_msk >> 1ULL;
/* we found what we were looking for */
for (lookahead_idx = msk_idx + 1; lookahead_idx < msk->n_masks;
lookahead_idx++) {
for (lookahead_idx = msk_idx + 1; lookahead_idx < msk->n_masks;
lookahead_idx++) {
+ unsigned int s_idx, need;
lookahead_msk = msk->data[lookahead_idx];
/* if we're looking for free space, invert the mask */
lookahead_msk = msk->data[lookahead_idx];
/* if we're looking for free space, invert the mask */
-find_next(const struct rte_fbarray *arr, int start, bool used)
+find_next(const struct rte_fbarray *arr, unsigned int start, bool used)
{
const struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz,
arr->len);
{
const struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz,
arr->len);
- int idx, first, first_mod;
- int last, last_mod, last_msk;
- uint64_t ignore_msk;
+ unsigned int idx, first, first_mod;
+ unsigned int last, last_mod;
+ uint64_t last_msk, ignore_msk;
/*
* mask only has granularity of MASK_ALIGN, but start may not be aligned
/*
* mask only has granularity of MASK_ALIGN, but start may not be aligned
-find_contig(const struct rte_fbarray *arr, int start, bool used)
+find_contig(const struct rte_fbarray *arr, unsigned int start, bool used)
{
const struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz,
arr->len);
{
const struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz,
arr->len);
- int idx, first, first_mod;
- int last, last_mod, last_msk;
- int need_len, result = 0;
+ unsigned int idx, first, first_mod;
+ unsigned int last, last_mod;
+ uint64_t last_msk;
+ unsigned int need_len, result = 0;
/* array length may not be aligned, so calculate ignore mask for last
* mask index.
/* array length may not be aligned, so calculate ignore mask for last
* mask index.
first_mod = MASK_LEN_TO_MOD(start);
for (idx = first; idx < msk->n_masks; idx++, result += need_len) {
uint64_t cur = msk->data[idx];
first_mod = MASK_LEN_TO_MOD(start);
for (idx = first; idx < msk->n_masks; idx++, result += need_len) {
uint64_t cur = msk->data[idx];
-set_used(struct rte_fbarray *arr, int idx, bool used)
+set_used(struct rte_fbarray *arr, unsigned int idx, bool used)
{
struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz, arr->len);
uint64_t msk_bit = 1ULL << MASK_LEN_TO_MOD(idx);
{
struct used_mask *msk = get_used_mask(arr->data, arr->elt_sz, arr->len);
uint64_t msk_bit = 1ULL << MASK_LEN_TO_MOD(idx);
- int msk_idx = MASK_LEN_TO_IDX(idx);
+ unsigned int msk_idx = MASK_LEN_TO_IDX(idx);
bool already_used;
int ret = -1;
bool already_used;
int ret = -1;
- if (arr == NULL || idx < 0 || idx >= arr->len) {
+ if (arr == NULL || idx >= arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
static int
fully_validate(const char *name, unsigned int elt_sz, unsigned int len)
{
static int
fully_validate(const char *name, unsigned int elt_sz, unsigned int len)
{
- if (name == NULL || elt_sz == 0 || len == 0) {
+ if (name == NULL || elt_sz == 0 || len == 0 || len > INT_MAX) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_init(struct rte_fbarray *arr, const char *name, int len, int elt_sz)
+rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,
+ unsigned int elt_sz)
{
size_t page_sz, mmap_len;
char path[PATH_MAX];
{
size_t page_sz, mmap_len;
char path[PATH_MAX];
return -1;
page_sz = sysconf(_SC_PAGESIZE);
return -1;
page_sz = sysconf(_SC_PAGESIZE);
+ if (page_sz == (size_t)-1)
+ goto fail;
/* calculate our memory limits */
mmap_len = calc_data_size(page_sz, elt_sz, len);
/* calculate our memory limits */
mmap_len = calc_data_size(page_sz, elt_sz, len);
return -1;
page_sz = sysconf(_SC_PAGESIZE);
return -1;
page_sz = sysconf(_SC_PAGESIZE);
+ if (page_sz == (size_t)-1)
+ goto fail;
mmap_len = calc_data_size(page_sz, arr->elt_sz, arr->len);
mmap_len = calc_data_size(page_sz, arr->elt_sz, arr->len);
}
void * __rte_experimental
}
void * __rte_experimental
-rte_fbarray_get(const struct rte_fbarray *arr, int idx)
+rte_fbarray_get(const struct rte_fbarray *arr, unsigned int idx)
- if (arr == NULL || idx < 0) {
rte_errno = EINVAL;
return NULL;
}
rte_errno = EINVAL;
return NULL;
}
-rte_fbarray_set_used(struct rte_fbarray *arr, int idx)
+rte_fbarray_set_used(struct rte_fbarray *arr, unsigned int idx)
{
return set_used(arr, idx, true);
}
int __rte_experimental
{
return set_used(arr, idx, true);
}
int __rte_experimental
-rte_fbarray_set_free(struct rte_fbarray *arr, int idx)
+rte_fbarray_set_free(struct rte_fbarray *arr, unsigned int idx)
{
return set_used(arr, idx, false);
}
int __rte_experimental
{
return set_used(arr, idx, false);
}
int __rte_experimental
-rte_fbarray_is_used(struct rte_fbarray *arr, int idx)
+rte_fbarray_is_used(struct rte_fbarray *arr, unsigned int idx)
{
struct used_mask *msk;
int msk_idx;
uint64_t msk_bit;
int ret = -1;
{
struct used_mask *msk;
int msk_idx;
uint64_t msk_bit;
int ret = -1;
- if (arr == NULL || idx < 0 || idx >= arr->len) {
+ if (arr == NULL || idx >= arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_find_next_free(struct rte_fbarray *arr, int start)
+rte_fbarray_find_next_free(struct rte_fbarray *arr, unsigned int start)
- if (arr == NULL || start < 0 || start >= arr->len) {
+ if (arr == NULL || start >= arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_find_next_used(struct rte_fbarray *arr, int start)
+rte_fbarray_find_next_used(struct rte_fbarray *arr, unsigned int start)
- if (arr == NULL || start < 0 || start >= arr->len) {
+ if (arr == NULL || start >= arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_find_next_n_free(struct rte_fbarray *arr, int start, int n)
+rte_fbarray_find_next_n_free(struct rte_fbarray *arr, unsigned int start,
+ unsigned int n)
- if (arr == NULL || start < 0 || start >= arr->len ||
- n < 0 || n > arr->len) {
+ if (arr == NULL || start >= arr->len || n > arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_find_next_n_used(struct rte_fbarray *arr, int start, int n)
+rte_fbarray_find_next_n_used(struct rte_fbarray *arr, unsigned int start,
+ unsigned int n)
- if (arr == NULL || start < 0 || start >= arr->len ||
- n < 0 || n > arr->len) {
+ if (arr == NULL || start >= arr->len || n > arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_find_contig_free(struct rte_fbarray *arr, int start)
+rte_fbarray_find_contig_free(struct rte_fbarray *arr, unsigned int start)
- if (arr == NULL || start < 0 || start >= arr->len) {
+ if (arr == NULL || start >= arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
-rte_fbarray_find_contig_used(struct rte_fbarray *arr, int start)
+rte_fbarray_find_contig_used(struct rte_fbarray *arr, unsigned int start)
- if (arr == NULL || start < 0 || start >= arr->len) {
+ if (arr == NULL || start >= arr->len) {
rte_errno = EINVAL;
return -1;
}
rte_errno = EINVAL;
return -1;
}
rte_fbarray_dump_metadata(struct rte_fbarray *arr, FILE *f)
{
struct used_mask *msk;
rte_fbarray_dump_metadata(struct rte_fbarray *arr, FILE *f)
{
struct used_mask *msk;
if (arr == NULL || f == NULL) {
rte_errno = EINVAL;
if (arr == NULL || f == NULL) {
rte_errno = EINVAL;
struct rte_fbarray {
char name[RTE_FBARRAY_NAME_LEN]; /**< name associated with an array */
struct rte_fbarray {
char name[RTE_FBARRAY_NAME_LEN]; /**< name associated with an array */
- int count; /**< number of entries stored */
- int len; /**< current length of the array */
- int elt_sz; /**< size of each element */
+ unsigned int count; /**< number of entries stored */
+ unsigned int len; /**< current length of the array */
+ unsigned int elt_sz; /**< size of each element */
void *data; /**< data pointer */
rte_rwlock_t rwlock; /**< multiprocess lock */
};
void *data; /**< data pointer */
rte_rwlock_t rwlock; /**< multiprocess lock */
};
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_init(struct rte_fbarray *arr, const char *name, int len,
- int elt_sz);
+rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len,
+ unsigned int elt_sz);
* - NULL on failure, with ``rte_errno`` indicating reason for failure.
*/
void * __rte_experimental
* - NULL on failure, with ``rte_errno`` indicating reason for failure.
*/
void * __rte_experimental
-rte_fbarray_get(const struct rte_fbarray *arr, int idx);
+rte_fbarray_get(const struct rte_fbarray *arr, unsigned int idx);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_set_used(struct rte_fbarray *arr, int idx);
+rte_fbarray_set_used(struct rte_fbarray *arr, unsigned int idx);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_set_free(struct rte_fbarray *arr, int idx);
+rte_fbarray_set_free(struct rte_fbarray *arr, unsigned int idx);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_is_used(struct rte_fbarray *arr, int idx);
+rte_fbarray_is_used(struct rte_fbarray *arr, unsigned int idx);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_find_next_free(struct rte_fbarray *arr, int start);
+rte_fbarray_find_next_free(struct rte_fbarray *arr, unsigned int start);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_find_next_used(struct rte_fbarray *arr, int start);
+rte_fbarray_find_next_used(struct rte_fbarray *arr, unsigned int start);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_find_next_n_free(struct rte_fbarray *arr, int start, int n);
+rte_fbarray_find_next_n_free(struct rte_fbarray *arr, unsigned int start,
+ unsigned int n);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_find_next_n_used(struct rte_fbarray *arr, int start, int n);
+rte_fbarray_find_next_n_used(struct rte_fbarray *arr, unsigned int start,
+ unsigned int n);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_find_contig_free(struct rte_fbarray *arr, int start);
+rte_fbarray_find_contig_free(struct rte_fbarray *arr,
+ unsigned int start);
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
* - -1 on failure, with ``rte_errno`` indicating reason for failure.
*/
int __rte_experimental
-rte_fbarray_find_contig_used(struct rte_fbarray *arr, int start);
+rte_fbarray_find_contig_used(struct rte_fbarray *arr, unsigned int start);