summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-08-20 18:11:14 +0200
committerLennart Poettering <lennart@poettering.net>2021-08-20 22:00:48 +0200
commitc7ed7187203ca0b348a0bb8a355b01332c446101 (patch)
tree0868c624ad647bd89280e7e168ee9053e48b4b65
parenteeed637fea380c59e90e707c684e8db32714baa4 (diff)
downloadsystemd-c7ed7187203ca0b348a0bb8a355b01332c446101.tar.gz
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.
-rw-r--r--src/basic/macro.h14
-rw-r--r--src/test/test-macro.c33
2 files changed, 47 insertions, 0 deletions
diff --git a/src/basic/macro.h b/src/basic/macro.h
index 280f302864..6977a1ddd9 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -146,6 +146,20 @@
#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p)))
static inline size_t ALIGN_TO(size_t l, size_t ali) {
+ /* Check that alignment is exponent of 2 */
+#if SIZE_MAX == UINT_MAX
+ assert(__builtin_popcount(ali) == 1);
+#elif SIZE_MAX == ULONG_MAX
+ assert(__builtin_popcountl(ali) == 1);
+#elif SIZE_MAX == ULONGLONG_MAX
+ assert(__builtin_popcountll(ali) == 1);
+#else
+#error "Unexpected size_t"
+#endif
+
+ if (l > SIZE_MAX - (ali - 1))
+ return SIZE_MAX; /* indicate overflow */
+
return ((l + ali - 1) & ~(ali - 1));
}
diff --git a/src/test/test-macro.c b/src/test/test-macro.c
index 5c0007cb5b..428f3b952a 100644
--- a/src/test/test-macro.c
+++ b/src/test/test-macro.c
@@ -295,6 +295,38 @@ static void test_foreach_pointer(void) {
assert(k == 11);
}
+static void test_align_to(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(ALIGN_TO(0, 1) == 0);
+ assert_se(ALIGN_TO(1, 1) == 1);
+ assert_se(ALIGN_TO(2, 1) == 2);
+ assert_se(ALIGN_TO(3, 1) == 3);
+ assert_se(ALIGN_TO(4, 1) == 4);
+ assert_se(ALIGN_TO(SIZE_MAX-1, 1) == SIZE_MAX-1);
+ assert_se(ALIGN_TO(SIZE_MAX, 1) == SIZE_MAX);
+
+ assert_se(ALIGN_TO(0, 2) == 0);
+ assert_se(ALIGN_TO(1, 2) == 2);
+ assert_se(ALIGN_TO(2, 2) == 2);
+ assert_se(ALIGN_TO(3, 2) == 4);
+ assert_se(ALIGN_TO(4, 2) == 4);
+ assert_se(ALIGN_TO(SIZE_MAX-3, 2) == SIZE_MAX-3);
+ assert_se(ALIGN_TO(SIZE_MAX-2, 2) == SIZE_MAX-1);
+ assert_se(ALIGN_TO(SIZE_MAX-1, 2) == SIZE_MAX-1);
+ assert_se(ALIGN_TO(SIZE_MAX, 2) == SIZE_MAX); /* overflow */
+
+ assert_se(ALIGN_TO(0, 4) == 0);
+ assert_se(ALIGN_TO(1, 4) == 4);
+ assert_se(ALIGN_TO(2, 4) == 4);
+ assert_se(ALIGN_TO(3, 4) == 4);
+ assert_se(ALIGN_TO(4, 4) == 4);
+ assert_se(ALIGN_TO(SIZE_MAX-3, 4) == SIZE_MAX-3);
+ assert_se(ALIGN_TO(SIZE_MAX-2, 4) == SIZE_MAX); /* overflow */
+ assert_se(ALIGN_TO(SIZE_MAX-1, 4) == SIZE_MAX); /* overflow */
+ assert_se(ALIGN_TO(SIZE_MAX, 4) == SIZE_MAX); /* overflow */
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
@@ -305,6 +337,7 @@ int main(int argc, char *argv[]) {
test_in_set();
test_foreach_pointer();
test_ptr_to_int();
+ test_align_to();
return 0;
}