Skip to content

Commit

Permalink
store: avoid pointer arithmetic UB
Browse files Browse the repository at this point in the history
when iterating backwards or when nr_snips is 0, the pointer will
be decremented outside of the `cs_snip` array object and into
the header, which is technically UB [0].

avoid it by returning early on nr_snips == 0 case and by
checking against the "stop" pointer before doing the decrement.

0: https://port70.net/~nsz/c/c11/n1570.html#6.5.6p8
  • Loading branch information
N-R-K authored and cdown committed Nov 9, 2024
1 parent 008642f commit 0960029
Showing 1 changed file with 10 additions and 11 deletions.
21 changes: 10 additions & 11 deletions src/store.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,23 +562,22 @@ int cs_add(struct clip_store *cs, const char *content, uint64_t *out_hash) {
*/
bool cs_snip_iter(struct ref_guard *guard, enum cs_iter_direction direction,
struct cs_snip **snip) {
if (guard->status < 0) {
if (guard->status < 0 || guard->cs->header->nr_snips == 0) {
return false;
}

struct cs_snip *start = guard->cs->snips;
struct cs_snip *oldest = guard->cs->snips;
struct cs_snip *newest = oldest + (guard->cs->header->nr_snips - 1);
struct cs_snip *stop = direction == CS_ITER_NEWEST_FIRST ? oldest : newest;

// cppcheck-suppress [constVariablePointer,unmatchedSuppression]
// TODO: False positive? Report upstream
struct cs_snip *end = start + guard->cs->header->nr_snips;

if (*snip) {
if (!*snip) {
*snip = direction == CS_ITER_NEWEST_FIRST ? newest : oldest;
return true;
} else if (*snip != stop) {
*snip = *snip + (direction == CS_ITER_NEWEST_FIRST ? -1 : 1);
} else {
*snip = direction == CS_ITER_NEWEST_FIRST ? end - 1 : start;
return true;
}

return *snip >= start && *snip < end;
return false;
}

/**
Expand Down

0 comments on commit 0960029

Please sign in to comment.