Skip to content

Commit c7ed718

Browse files
committed
macro: handle overflow in ALIGN_TO() somewhat reasonably
The helper call rounds up to next multiple of specified boundary. If one passes a very large value as first argument, then there might not be a next multiple. So far we ignored that. Let's handle this now and return SIZE_MAX in this case, as special indicator that we reached the end. Of course, IRL this should not happen. With this new change we at least do something somewhat reasonable, leaving it to the caller to handle it further.
1 parent eeed637 commit c7ed718

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/basic/macro.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,20 @@
146146
#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p)))
147147

148148
static inline size_t ALIGN_TO(size_t l, size_t ali) {
149+
/* Check that alignment is exponent of 2 */
150+
#if SIZE_MAX == UINT_MAX
151+
assert(__builtin_popcount(ali) == 1);
152+
#elif SIZE_MAX == ULONG_MAX
153+
assert(__builtin_popcountl(ali) == 1);
154+
#elif SIZE_MAX == ULONGLONG_MAX
155+
assert(__builtin_popcountll(ali) == 1);
156+
#else
157+
#error "Unexpected size_t"
158+
#endif
159+
160+
if (l > SIZE_MAX - (ali - 1))
161+
return SIZE_MAX; /* indicate overflow */
162+
149163
return ((l + ali - 1) & ~(ali - 1));
150164
}
151165

src/test/test-macro.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,38 @@ static void test_foreach_pointer(void) {
295295
assert(k == 11);
296296
}
297297

298+
static void test_align_to(void) {
299+
log_info("/* %s */", __func__);
300+
301+
assert_se(ALIGN_TO(0, 1) == 0);
302+
assert_se(ALIGN_TO(1, 1) == 1);
303+
assert_se(ALIGN_TO(2, 1) == 2);
304+
assert_se(ALIGN_TO(3, 1) == 3);
305+
assert_se(ALIGN_TO(4, 1) == 4);
306+
assert_se(ALIGN_TO(SIZE_MAX-1, 1) == SIZE_MAX-1);
307+
assert_se(ALIGN_TO(SIZE_MAX, 1) == SIZE_MAX);
308+
309+
assert_se(ALIGN_TO(0, 2) == 0);
310+
assert_se(ALIGN_TO(1, 2) == 2);
311+
assert_se(ALIGN_TO(2, 2) == 2);
312+
assert_se(ALIGN_TO(3, 2) == 4);
313+
assert_se(ALIGN_TO(4, 2) == 4);
314+
assert_se(ALIGN_TO(SIZE_MAX-3, 2) == SIZE_MAX-3);
315+
assert_se(ALIGN_TO(SIZE_MAX-2, 2) == SIZE_MAX-1);
316+
assert_se(ALIGN_TO(SIZE_MAX-1, 2) == SIZE_MAX-1);
317+
assert_se(ALIGN_TO(SIZE_MAX, 2) == SIZE_MAX); /* overflow */
318+
319+
assert_se(ALIGN_TO(0, 4) == 0);
320+
assert_se(ALIGN_TO(1, 4) == 4);
321+
assert_se(ALIGN_TO(2, 4) == 4);
322+
assert_se(ALIGN_TO(3, 4) == 4);
323+
assert_se(ALIGN_TO(4, 4) == 4);
324+
assert_se(ALIGN_TO(SIZE_MAX-3, 4) == SIZE_MAX-3);
325+
assert_se(ALIGN_TO(SIZE_MAX-2, 4) == SIZE_MAX); /* overflow */
326+
assert_se(ALIGN_TO(SIZE_MAX-1, 4) == SIZE_MAX); /* overflow */
327+
assert_se(ALIGN_TO(SIZE_MAX, 4) == SIZE_MAX); /* overflow */
328+
}
329+
298330
int main(int argc, char *argv[]) {
299331
test_setup_logging(LOG_INFO);
300332

@@ -305,6 +337,7 @@ int main(int argc, char *argv[]) {
305337
test_in_set();
306338
test_foreach_pointer();
307339
test_ptr_to_int();
340+
test_align_to();
308341

309342
return 0;
310343
}

0 commit comments

Comments
 (0)