1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-19 22:50:17 +03:00

macro: add macro that simplifies going backwards through an array via pointers

Inspired by #22797, let's avoid some UB when iterating through arrays.
This commit is contained in:
Lennart Poettering 2022-03-21 14:23:38 +01:00 committed by Yu Watanabe
parent 4053d11006
commit 50996f04ad
2 changed files with 39 additions and 0 deletions

View File

@ -463,4 +463,20 @@ typedef struct {
assert_cc(sizeof(dummy_t) == 0);
/* A little helper for subtracting 1 off a pointer in a safe UB-free way. This is intended to be used for for
* loops that count down from a high pointer until some base. A naive loop would implement this like this:
*
* for (p = end-1; p >= base; p--)
*
* But this is not safe because p before the base is UB in C. With this macro the loop becomes this instead:
*
* for (p = PTR_SUB1(end, base); p; p = PTR_SUB1(p, base))
*
* And is free from UB! */
#define PTR_SUB1(p, base) \
({ \
typeof(p) _q = (p); \
_q && _q > (base) ? &_q[-1] : NULL; \
})
#include "log.h"

View File

@ -433,4 +433,27 @@ TEST(DECIMAL_STR_MAX) {
assert_se(DECIMAL_STR_MAX(uint64_t) == DECIMAL_STR_WIDTH(u64_longest)+1);
}
TEST(PTR_SUB1) {
static const uint64_t x[4] = { 2, 3, 4, 5 };
const uint64_t *p;
p = x + ELEMENTSOF(x)-1;
assert_se(*p == 5);
p = PTR_SUB1(p, x);
assert_se(*p == 4);
p = PTR_SUB1(p, x);
assert_se(*p == 3);
p = PTR_SUB1(p, x);
assert_se(*p == 2);
p = PTR_SUB1(p, x);
assert_se(!p);
p = PTR_SUB1(p, x);
assert_se(!p);
}
DEFINE_TEST_MAIN(LOG_INFO);