diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 13:00:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 13:00:47 +0000 |
commit | 2cb7e0aaedad73b076ea18c6900b0e86c5760d79 (patch) | |
tree | da68ca54bb79f4080079bf0828acda937593a4e1 /coccinelle | |
parent | Initial commit. (diff) | |
download | systemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.tar.xz systemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.zip |
Adding upstream version 247.3.upstream/247.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
53 files changed, 1413 insertions, 0 deletions
diff --git a/coccinelle/bool-cast.cocci b/coccinelle/bool-cast.cocci new file mode 100644 index 0000000..051ccb9 --- /dev/null +++ b/coccinelle/bool-cast.cocci @@ -0,0 +1,12 @@ +@@ +bool b; +expression y; +@@ +- b = !!(y); ++ b = y; +@@ +bool b; +expression y; +@@ +- b = !!y; ++ b = y; diff --git a/coccinelle/close-above-stdio.cocci b/coccinelle/close-above-stdio.cocci new file mode 100644 index 0000000..44b3b1c --- /dev/null +++ b/coccinelle/close-above-stdio.cocci @@ -0,0 +1,36 @@ +@@ +expression fd; +@@ +- if (fd > 2) +- safe_close(fd); ++ safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd > 2) +- fd = safe_close(fd); ++ fd = safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd >= 3) +- safe_close(fd); ++ safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd >= 3) +- fd = safe_close(fd); ++ fd = safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd > STDERR_FILENO) +- safe_close(fd); ++ safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd > STDERR_FILENO) +- fd = safe_close(fd); ++ fd = safe_close_above_stdio(fd); diff --git a/coccinelle/cmp.cocci b/coccinelle/cmp.cocci new file mode 100644 index 0000000..a34cbe5 --- /dev/null +++ b/coccinelle/cmp.cocci @@ -0,0 +1,28 @@ +@@ +expression x, y; +@@ +- if (x < y) +- return -1; +- if (x > y) +- return 1; +- return 0; ++ return CMP(x, y); +@@ +expression x, y; +@@ +- if (x < y) +- return -1; +- else if (x > y) +- return 1; +- return 0; ++ return CMP(x, y); +@@ +expression x, y; +@@ +- if (x < y) +- return -1; +- else if (x > y) +- return 1; +- else +- return 0; ++ return CMP(x, y); diff --git a/coccinelle/const-strlen.disabled b/coccinelle/const-strlen.disabled new file mode 100644 index 0000000..30a6e5a --- /dev/null +++ b/coccinelle/const-strlen.disabled @@ -0,0 +1,14 @@ +@@ +constant s; +@@ +( +#define STRLEN +& +- sizeof(s)-1 ++ STRLEN(s) +) +@@ +constant s; +@@ +- strlen(s) ++ STRLEN(s) diff --git a/coccinelle/debug-logging.cocci b/coccinelle/debug-logging.cocci new file mode 100644 index 0000000..a679dab --- /dev/null +++ b/coccinelle/debug-logging.cocci @@ -0,0 +1,16 @@ +@@ +@@ +( +#define DEBUG_LOGGING +& +- _unlikely_(log_get_max_level() >= LOG_DEBUG) ++ DEBUG_LOGGING +) +@@ +@@ +( +#define DEBUG_LOGGING +& +- log_get_max_level() >= LOG_DEBUG ++ DEBUG_LOGGING +) diff --git a/coccinelle/div-round-up.cocci b/coccinelle/div-round-up.cocci new file mode 100644 index 0000000..a0c6df9 --- /dev/null +++ b/coccinelle/div-round-up.cocci @@ -0,0 +1,20 @@ +@@ +expression x, y; +@@ +- ((x + y - 1) / y) ++ DIV_ROUND_UP(x, y) +@@ +expression x, y; +@@ +- ((x + (y - 1)) / y) ++ DIV_ROUND_UP(x, y) +@@ +expression x, y; +@@ +- (x + y - 1) / y ++ DIV_ROUND_UP(x, y) +@@ +expression x, y; +@@ +- (x + (y - 1)) / y ++ DIV_ROUND_UP(x, y) diff --git a/coccinelle/dup-fcntl.cocci b/coccinelle/dup-fcntl.cocci new file mode 100644 index 0000000..8b133b3 --- /dev/null +++ b/coccinelle/dup-fcntl.cocci @@ -0,0 +1,7 @@ +@@ +/* We want to stick with dup() in test-fd-util.c */ +position p : script:python() { p[0].file != "src/test/test-fd-util.c" }; +expression fd; +@@ +- dup@p(fd) ++ fcntl(fd, F_DUPFD, 3) diff --git a/coccinelle/empty-or-dash.cocci b/coccinelle/empty-or-dash.cocci new file mode 100644 index 0000000..bebaead --- /dev/null +++ b/coccinelle/empty-or-dash.cocci @@ -0,0 +1,5 @@ +@@ +expression s; +@@ +- (isempty(s) || streq(s, "-")) ++ empty_or_dash(s) diff --git a/coccinelle/empty-or-root.cocci b/coccinelle/empty-or-root.cocci new file mode 100644 index 0000000..bf2f614 --- /dev/null +++ b/coccinelle/empty-or-root.cocci @@ -0,0 +1,10 @@ +@@ +expression s; +@@ +- (isempty(s) || path_equal(s, "/")) ++ empty_or_root(s) +@@ +expression s; +@@ +- (!isempty(s) && !path_equal(s, "/")) ++ !empty_or_root(s) diff --git a/coccinelle/empty-to-null.cocci b/coccinelle/empty-to-null.cocci new file mode 100644 index 0000000..bc6c656 --- /dev/null +++ b/coccinelle/empty-to-null.cocci @@ -0,0 +1,8 @@ +@@ +/* Avoid running this transformation on the empty_to_null function itself */ +position p : script:python() { p[0].current_element != "empty_to_null" }; +expression s; +@@ + +- isempty@p(s) ? NULL : s ++ empty_to_null(s) diff --git a/coccinelle/empty-to-root.cocci b/coccinelle/empty-to-root.cocci new file mode 100644 index 0000000..3720497 --- /dev/null +++ b/coccinelle/empty-to-root.cocci @@ -0,0 +1,16 @@ +@@ +expression s; +@@ +- if (empty_or_root(s)) +- s = "/"; ++ s = empty_to_root(s); +@@ +expression s; +@@ +- (empty_or_root(s) ? "/" : s) ++ empty_to_root(s) +@@ +expression s; +@@ +- (s ? s : "/") ++ empty_to_root(s) diff --git a/coccinelle/enotsup.cocci b/coccinelle/enotsup.cocci new file mode 100644 index 0000000..c65734d --- /dev/null +++ b/coccinelle/enotsup.cocci @@ -0,0 +1,4 @@ +@@ +@@ +- ENOTSUP ++ EOPNOTSUPP diff --git a/coccinelle/equals-null.cocci b/coccinelle/equals-null.cocci new file mode 100644 index 0000000..3fce0f4 --- /dev/null +++ b/coccinelle/equals-null.cocci @@ -0,0 +1,29 @@ +@@ +expression e; +statement s; +@@ +if ( +( +!e +| +- e == NULL ++ !e +) + ) + {...} +else s + +@@ +expression e; +statement s; +@@ +if ( +( +e +| +- e != NULL ++ e +) + ) + {...} +else s diff --git a/coccinelle/errno-check.cocci b/coccinelle/errno-check.cocci new file mode 100644 index 0000000..709cb4a --- /dev/null +++ b/coccinelle/errno-check.cocci @@ -0,0 +1,10 @@ +@@ +constant c; +@@ +( +- errno == -c ++ errno == c +| +- errno != -c ++ errno != c +) diff --git a/coccinelle/errno.cocci b/coccinelle/errno.cocci new file mode 100644 index 0000000..c928266 --- /dev/null +++ b/coccinelle/errno.cocci @@ -0,0 +1,41 @@ +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +local idexpression r; +expression e; +@@ +- r = -e; ++ r = + log_LEVEL_errno(e, ...); +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +local idexpression r; +expression e; +@@ ++ r = + log_LEVEL_errno(e, ...); +- r = -e; +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +local idexpression r; +expression e; +@@ +- r = ++ return + log_LEVEL_errno(e, ...); +- return r; +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +expression e; +@@ ++ return + log_LEVEL_errno(e, ...); +- return -e; +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +expression list args; +expression e; +local idexpression r; +@@ +- log_LEVEL_errno(e, args); +- r = e; ++ r = log_LEVEL_errno(e, args); diff --git a/coccinelle/exit-0.cocci b/coccinelle/exit-0.cocci new file mode 100644 index 0000000..8b81600 --- /dev/null +++ b/coccinelle/exit-0.cocci @@ -0,0 +1,16 @@ +@@ +@@ +- exit(0); ++ exit(EXIT_SUCCESS); +@@ +@@ +- _exit(0); ++ _exit(EXIT_SUCCESS); +@@ +@@ +- exit(1); ++ exit(EXIT_FAILURE); +@@ +@@ +- _exit(1); ++ _exit(EXIT_FAILURE); diff --git a/coccinelle/flags-set.cocci b/coccinelle/flags-set.cocci new file mode 100644 index 0000000..f6cc8ba --- /dev/null +++ b/coccinelle/flags-set.cocci @@ -0,0 +1,22 @@ +@@ +/* Disable this transformation in cases where it doesn't make sense or + * where it makes the resulting expression more confusing + */ +position p : script:python() { + not (p[0].file == "src/shared/securebits-util.h" or + p[0].file == "src/core/manager.h" or + p[0].current_element == "log_set_max_level_realm" or + p[0].current_element == "unichar_is_valid") + }; +expression x, y; +@@ +( +- ((x@p) & (y)) == (y) ++ FLAGS_SET(x, y) +| +- (x@p & (y)) == (y) ++ FLAGS_SET(x, y) +| +- ((x@p) & y) == y ++ FLAGS_SET(x, y) +) diff --git a/coccinelle/fopen-unlocked.cocci b/coccinelle/fopen-unlocked.cocci new file mode 100644 index 0000000..7870f8c --- /dev/null +++ b/coccinelle/fopen-unlocked.cocci @@ -0,0 +1,71 @@ +@@ +expression f, path, options; +@@ +- f = fopen(path, options); +- if (!f) +- return -errno; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); ++ r = fopen_unlocked(path, options, &f); ++ if (r < 0) ++ return r; +@@ +expression f, path, options; +@@ +- f = fopen(path, options); +- if (!f) { +- if (errno == ENOENT) +- return -ESRCH; +- return -errno; +- } +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); ++ r = fopen_unlocked(path, options, &f); ++ if (r == -ENOENT) ++ return -ESRCH; ++ if (r < 0) ++ return r; +@@ +expression f, path, options; +@@ +- f = fopen(path, options); +- if (!f) +- return errno == ENOENT ? -ESRCH : -errno; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); ++ r = fopen_unlocked(path, options, &f); ++ if (r == -ENOENT) ++ return -ESRCH; ++ if (r < 0) ++ return r; +@@ +expression f, path, p; +@@ + r = fopen_temporary(path, &f, &p); + if (r < 0) + return ...; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); +@@ +expression f, g, path, p; +@@ + r = fopen_temporary_label(path, g, &f, &p); + if (r < 0) + return ...; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); +@@ +expression f, fd, options; +@@ +- f = fdopen(fd, options); ++ r = fdopen_unlocked(fd, options, &f); ++ if (r < 0) { +- if (!f) { + ... +- return -errno; ++ return r; + } +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); +@@ +expression f, buf, sz; +@@ +- f = open_memstream(&buf, &sz); ++ f = open_memstream_unlocked(&buf, &sz); + if (!f) + return ...; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); diff --git a/coccinelle/free_and_replace.cocci b/coccinelle/free_and_replace.cocci new file mode 100644 index 0000000..9dcdbf4 --- /dev/null +++ b/coccinelle/free_and_replace.cocci @@ -0,0 +1,15 @@ +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; +- return 0; ++ return free_and_replace(p, q); +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; ++ free_and_replace(p, q); diff --git a/coccinelle/hashmap_free.cocci b/coccinelle/hashmap_free.cocci new file mode 100644 index 0000000..86b9542 --- /dev/null +++ b/coccinelle/hashmap_free.cocci @@ -0,0 +1,54 @@ +@@ +expression p; +@@ +- set_free(p); +- p = NULL; ++ p = set_free(p); +@@ +expression p; +@@ +- if (p) +- set_free(p); +- p = NULL; ++ p = set_free(p); +@@ +expression p; +@@ +- if (p) { +- set_free(p); +- p = NULL; +- } ++ p = set_free(p); +@@ +expression p; +@@ +- if (p) +- set_free(p); ++ set_free(p); +@@ +expression p; +@@ +- hashmap_free(p); +- p = NULL; ++ p = hashmap_free(p); +@@ +expression p; +@@ +- if (p) +- hashmap_free(p); +- p = NULL; ++ p = hashmap_free(p); +@@ +expression p; +@@ +- if (p) { +- hashmap_free(p); +- p = NULL; +- } ++ p = hashmap_free(p); +@@ +expression p; +@@ +- if (p) +- hashmap_free(p); ++ hashmap_free(p); diff --git a/coccinelle/htonl.cocci b/coccinelle/htonl.cocci new file mode 100644 index 0000000..4e69bb7 --- /dev/null +++ b/coccinelle/htonl.cocci @@ -0,0 +1,20 @@ +@@ +expression s; +@@ +- htonl(s) ++ htobe32(s) +@@ +expression s; +@@ +- htons(s) ++ htobe16(s) +@@ +expression s; +@@ +- ntohl(s) ++ be32toh(s) +@@ +expression s; +@@ +- ntohs(s) ++ be16toh(s) diff --git a/coccinelle/in_set.cocci b/coccinelle/in_set.cocci new file mode 100644 index 0000000..1c17c7d --- /dev/null +++ b/coccinelle/in_set.cocci @@ -0,0 +1,25 @@ +/* Limit the number of expressions to 6 for performance reasons */ +@@ +expression e; +/* Exclude JsonVariant * from the transformation, as it can't work with the + * current version of the IN_SET macro */ +typedef JsonVariant; +type T != JsonVariant*; +constant T n0, n1, n2, n3, n4, n5; +@@ +( +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 ++ IN_SET(e, n0, n1, n2, n3, n4, n5) +| +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 ++ IN_SET(e, n0, n1, n2, n3, n4) +| +- e == n0 || e == n1 || e == n2 || e == n3 ++ IN_SET(e, n0, n1, n2, n3) +| +- e == n0 || e == n1 || e == n2 ++ IN_SET(e, n0, n1, n2) +| +- e == n0 || e == n1 ++ IN_SET(e, n0, n1) +) diff --git a/coccinelle/iovec-make.cocci b/coccinelle/iovec-make.cocci new file mode 100644 index 0000000..7a0d4ce --- /dev/null +++ b/coccinelle/iovec-make.cocci @@ -0,0 +1,29 @@ +@@ +expression x, y, p, l; +@@ +- x[y].iov_base = p; +- x[y].iov_len = l; +- y++; ++ x[y++] = IOVEC_MAKE(p, l); +@@ +expression x, p, l; +@@ +- x.iov_base = p; +- x.iov_len = l; ++ x = IOVEC_MAKE(p, l); +@@ +expression x, p, l; +@@ +- x->iov_base = p; +- x->iov_len = l; ++ *x = IOVEC_MAKE(p, l); +@@ +expression s; +@@ +- IOVEC_MAKE(s, strlen(s)); ++ IOVEC_MAKE_STRING(s); +@@ +expression x, y, z; +@@ +- x = (struct iovec) { .iov_base = y, .iov_len = z }; ++ x = IOVEC_MAKE(y, z); diff --git a/coccinelle/isempty.cocci b/coccinelle/isempty.cocci new file mode 100644 index 0000000..e0a9f07 --- /dev/null +++ b/coccinelle/isempty.cocci @@ -0,0 +1,42 @@ +@@ +/* Disable this transformation for the test-string-util.c */ +position p : script:python() { p[0].file != "src/test/test-string-util.c" }; +expression s; +@@ +( +- strv_length@p(s) == 0 ++ strv_isempty(s) +| +- strv_length@p(s) <= 0 ++ strv_isempty(s) +| +- strv_length@p(s) > 0 ++ !strv_isempty(s) +| +- strv_length@p(s) != 0 ++ !strv_isempty(s) +| +- strlen@p(s) == 0 ++ isempty(s) +| +- strlen@p(s) <= 0 ++ isempty(s) +| +- strlen@p(s) > 0 ++ !isempty(s) +| +- strlen@p(s) != 0 ++ !isempty(s) +| +- strlen_ptr@p(s) == 0 ++ isempty(s) +| +- strlen_ptr@p(s) <= 0 ++ isempty(s) +| +- strlen_ptr@p(s) > 0 ++ !isempty(s) +| +- strlen_ptr@p(s) != 0 ++ !isempty(s) +) diff --git a/coccinelle/log-json.cocci b/coccinelle/log-json.cocci new file mode 100644 index 0000000..3730fd6 --- /dev/null +++ b/coccinelle/log-json.cocci @@ -0,0 +1,8 @@ +@@ +expression e, v, flags; +expression list args; +@@ ++ return +- json_log(v, flags, 0, args); ++ json_log(v, flags, SYNTHETIC_ERRNO(e), args); +- return -e; diff --git a/coccinelle/macros.h b/coccinelle/macros.h new file mode 100644 index 0000000..62177f0 --- /dev/null +++ b/coccinelle/macros.h @@ -0,0 +1,231 @@ +/* Collected macros from our systemd codebase to make the cocci semantic + * parser happy. Inspired by the original cocci macros file + * /usr/lib64/coccinelle/standard.h (including the YACFE_* symbols) + */ + +// General +#define PTR_TO_PID(x) + +// src/basic/macro.h +#define _printf_(a, b) __attribute__((__format__(printf, a, b))) +#define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__))) +#define _sentinel_ __attribute__((__sentinel__)) +#define _section_(x) __attribute__((__section__(x))) +#define _used_ __attribute__((__used__)) +#define _unused_ __attribute__((__unused__)) +#define _destructor_ __attribute__((__destructor__)) +#define _pure_ __attribute__((__pure__)) +#define _const_ __attribute__((__const__)) +#define _deprecated_ __attribute__((__deprecated__)) +#define _packed_ __attribute__((__packed__)) +#define _malloc_ __attribute__((__malloc__)) +#define _weak_ __attribute__((__weak__)) +#define _likely_(x) (__builtin_expect(!!(x), 1)) +#define _unlikely_(x) (__builtin_expect(!!(x), 0)) +#define _public_ __attribute__((__visibility__("default"))) +#define _hidden_ __attribute__((__visibility__("hidden"))) +#define _weakref_(x) __attribute__((__weakref__(#x))) +#define _align_(x) __attribute__((__aligned__(x))) +#define _alignas_(x) __attribute__((__aligned__(__alignof(x)))) +#define _alignptr_ __attribute__((__aligned__(sizeof(void*)))) +#define _cleanup_(x) __attribute__((__cleanup__(x))) +#define _fallthrough_ +#define _noreturn_ __attribute__((__noreturn__)) +#define thread_local __thread + +#define ELEMENTSOF(x) \ + (__builtin_choose_expr( \ + !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ + sizeof(x)/sizeof((x)[0]), \ + VOID_0)) + +// src/basic/umask-util.h +#define _cleanup_umask_ +#define RUN_WITH_UMASK(mask) \ + for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \ + FLAGS_SET(_saved_umask_, S_IFMT); \ + _saved_umask_ &= 0777) + +// src/basic/hashmap.h +#define _IDX_ITERATOR_FIRST (UINT_MAX - 1) +#define HASHMAP_FOREACH(e, h) YACFE_ITERATOR +#define ORDERED_HASHMAP_FOREACH(e, h) YACFE_ITERATOR +#define HASHMAP_FOREACH_KEY(e, k, h) YACFE_ITERATOR +#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) YACFE_ITERATOR + +// src/basic/list.h +#define LIST_HEAD(t,name) \ + t *name +#define LIST_FIELDS(t,name) \ + t *name##_next, *name##_prev +#define LIST_HEAD_INIT(head) \ + do { \ + (head) = NULL; \ + } while (false) +#define LIST_INIT(name,item) \ + do { \ + typeof(*(item)) *_item = (item); \ + assert(_item); \ + _item->name##_prev = _item->name##_next = NULL; \ + } while (false) +#define LIST_PREPEND(name,head,item) \ + do { \ + typeof(*(head)) **_head = &(head), *_item = (item); \ + assert(_item); \ + if ((_item->name##_next = *_head)) \ + _item->name##_next->name##_prev = _item; \ + _item->name##_prev = NULL; \ + *_head = _item; \ + } while (false) +#define LIST_APPEND(name,head,item) \ + do { \ + typeof(*(head)) **_hhead = &(head), *_tail; \ + LIST_FIND_TAIL(name, *_hhead, _tail); \ + LIST_INSERT_AFTER(name, *_hhead, _tail, item); \ + } while (false) +#define LIST_REMOVE(name,head,item) \ + do { \ + typeof(*(head)) **_head = &(head), *_item = (item); \ + assert(_item); \ + if (_item->name##_next) \ + _item->name##_next->name##_prev = _item->name##_prev; \ + if (_item->name##_prev) \ + _item->name##_prev->name##_next = _item->name##_next; \ + else { \ + assert(*_head == _item); \ + *_head = _item->name##_next; \ + } \ + _item->name##_next = _item->name##_prev = NULL; \ + } while (false) +#define LIST_FIND_HEAD(name,item,head) \ + do { \ + typeof(*(item)) *_item = (item); \ + if (!_item) \ + (head) = NULL; \ + else { \ + while (_item->name##_prev) \ + _item = _item->name##_prev; \ + (head) = _item; \ + } \ + } while (false) +#define LIST_FIND_TAIL(name,item,tail) \ + do { \ + typeof(*(item)) *_item = (item); \ + if (!_item) \ + (tail) = NULL; \ + else { \ + while (_item->name##_next) \ + _item = _item->name##_next; \ + (tail) = _item; \ + } \ + } while (false) +#define LIST_INSERT_AFTER(name,head,a,b) \ + do { \ + typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ + assert(_b); \ + if (!_a) { \ + if ((_b->name##_next = *_head)) \ + _b->name##_next->name##_prev = _b; \ + _b->name##_prev = NULL; \ + *_head = _b; \ + } else { \ + if ((_b->name##_next = _a->name##_next)) \ + _b->name##_next->name##_prev = _b; \ + _b->name##_prev = _a; \ + _a->name##_next = _b; \ + } \ + } while (false) +#define LIST_INSERT_BEFORE(name,head,a,b) \ + do { \ + typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ + assert(_b); \ + if (!_a) { \ + if (!*_head) { \ + _b->name##_next = NULL; \ + _b->name##_prev = NULL; \ + *_head = _b; \ + } else { \ + typeof(*(head)) *_tail = (head); \ + while (_tail->name##_next) \ + _tail = _tail->name##_next; \ + _b->name##_next = NULL; \ + _b->name##_prev = _tail; \ + _tail->name##_next = _b; \ + } \ + } else { \ + if ((_b->name##_prev = _a->name##_prev)) \ + _b->name##_prev->name##_next = _b; \ + else \ + *_head = _b; \ + _b->name##_next = _a; \ + _a->name##_prev = _b; \ + } \ + } while (false) + +#define LIST_JUST_US(name,item) \ + (!(item)->name##_prev && !(item)->name##_next) \ +#define LIST_FOREACH(name,i,head) \ + for ((i) = (head); (i); (i) = (i)->name##_next) +#define LIST_FOREACH_SAFE(name,i,n,head) \ + for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n)) +#define LIST_FOREACH_BEFORE(name,i,p) \ + for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev) +#define LIST_FOREACH_AFTER(name,i,p) \ + for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next) +#define LIST_FOREACH_OTHERS(name,i,p) \ + for (({ \ + (i) = (p); \ + while ((i) && (i)->name##_prev) \ + (i) = (i)->name##_prev; \ + if ((i) == (p)) \ + (i) = (p)->name##_next; \ + }); \ + (i); \ + (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next) +#define LIST_LOOP_BUT_ONE(name,i,head,p) \ + for ((i) = (p)->name##_next ? (p)->name##_next : (head); \ + (i) != (p); \ + (i) = (i)->name##_next ? (i)->name##_next : (head)) + +#define LIST_IS_EMPTY(head) \ + (!(head)) +#define LIST_JOIN(name,a,b) \ + do { \ + assert(b); \ + if (!(a)) \ + (a) = (b); \ + else { \ + typeof(*(a)) *_head = (b), *_tail; \ + LIST_FIND_TAIL(name, (a), _tail); \ + _tail->name##_next = _head; \ + _head->name##_prev = _tail; \ + } \ + (b) = NULL; \ + } while (false) + +// src/basic/strv.h +#define STRV_FOREACH(s, l) YACFE_ITERATOR +#define STRV_FOREACH_BACKWARDS(s, l) YACFE_ITERATOR +#define STRV_FOREACH_PAIR(x, y, l) YACFE_ITERATOR + +// src/basic/socket-util.h +#define CMSG_BUFFER_TYPE(size) \ + union { \ + struct cmsghdr cmsghdr; \ + uint8_t buf[size]; \ + uint8_t align_check[(size) >= CMSG_SPACE(0) && \ + (size) == CMSG_ALIGN(size) ? 1 : -1]; \ + } + +// src/libsystemd/sd-device/device-util.h +#define FOREACH_DEVICE_PROPERTY(device, key, value) YACFE_ITERATOR +#define FOREACH_DEVICE_TAG(device, tag) YACFE_ITERATOR +#define FOREACH_DEVICE_CURRENT_TAG(device, tag) YACFE_ITERATOR +#define FOREACH_DEVICE_SYSATTR(device, attr) YACFE_ITERATOR +#define FOREACH_DEVICE_DEVLINK(device, devlink) YACFE_ITERATOR +#define FOREACH_DEVICE(enumerator, device) YACFE_ITERATOR +#define FOREACH_SUBSYSTEM(enumerator, device) YACFE_ITERATOR + +// src/basic/dirent-util.h +#define FOREACH_DIRENT(de, d, on_error) YACFE_ITERATOR +#define FOREACH_DIRENT_ALL(de, d, on_error) YACFE_ITERATOR diff --git a/coccinelle/malloc_multiply.cocci b/coccinelle/malloc_multiply.cocci new file mode 100644 index 0000000..3284edf --- /dev/null +++ b/coccinelle/malloc_multiply.cocci @@ -0,0 +1,20 @@ +@@ +expression q, n, m; +@@ +- q = malloc((n)*(m)) ++ q = malloc_multiply(n, m) +@@ +expression q, n, m; +@@ +- q = malloc(n*(m)) ++ q = malloc_multiply(n, m) +@@ +expression q, n, m; +@@ +- q = malloc((n)*m) ++ q = malloc_multiply(n, m) +@@ +expression q, n, m; +@@ +- q = malloc(n*m) ++ q = malloc_multiply(n, m) diff --git a/coccinelle/memzero.cocci b/coccinelle/memzero.cocci new file mode 100644 index 0000000..8198cc8 --- /dev/null +++ b/coccinelle/memzero.cocci @@ -0,0 +1,38 @@ +@@ +expression s; +@@ +- memset(&s, 0, sizeof(s)) ++ zero(s) +@@ +expression s; +@@ +- memset(s, 0, sizeof(*s)) ++ zero(*s) +@@ +expression s; +@@ +- bzero(&s, sizeof(s)) ++ zero(s) +@@ +expression s; +@@ +- bzero(s, sizeof(*s)) ++ zero(*s) +@@ +expression a, b; +@@ +( +#define memzero +& +- memset(a, 0, b) ++ memzero(a, b) +) +@@ +expression a, b; +@@ +( +#define memzero +& +- bzero(a, b) ++ memzero(a, b) +) diff --git a/coccinelle/mfree.cocci b/coccinelle/mfree.cocci new file mode 100644 index 0000000..1389cd3 --- /dev/null +++ b/coccinelle/mfree.cocci @@ -0,0 +1,6 @@ +@@ +expression p; +@@ +- free(p); +- p = NULL; ++ p = mfree(p); diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci new file mode 100644 index 0000000..15e6c7d --- /dev/null +++ b/coccinelle/mfree_return.cocci @@ -0,0 +1,8 @@ +@@ +/* Avoid running this transformation on the mfree function itself */ +position p : script:python() { p[0].current_element != "mfree" }; +expression e; +@@ +- free@p(e); +- return NULL; ++ return mfree(e); diff --git a/coccinelle/no-if-assignments.cocci b/coccinelle/no-if-assignments.cocci new file mode 100644 index 0000000..9f63e90 --- /dev/null +++ b/coccinelle/no-if-assignments.cocci @@ -0,0 +1,20 @@ +@@ +expression p, q; +identifier r; +statement s; +@@ +- if ((r = q) < p) +- s ++ r = q; ++ if (r < p) ++ s +@@ +expression p, q; +identifier r; +statement s; +@@ +- if ((r = q) >= p) +- s ++ r = q; ++ if (r >= p) ++ s diff --git a/coccinelle/not_in_set.cocci b/coccinelle/not_in_set.cocci new file mode 100644 index 0000000..3486cff --- /dev/null +++ b/coccinelle/not_in_set.cocci @@ -0,0 +1,23 @@ +/* Limit the number of expressions to 6 for performance reasons */ +@@ +expression e; +typedef JsonVariant; +type T != JsonVariant*; +constant T n0, n1, n2, n3, n4, n5; +@@ +( +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 ++ !IN_SET(e, n0, n1, n2, n3, n4, n5) +| +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 ++ !IN_SET(e, n0, n1, n2, n3, n4) +| +- e != n0 && e != n1 && e != n2 && e != n3 ++ !IN_SET(e, n0, n1, n2, n3) +| +- e != n0 && e != n1 && e != n2 ++ !IN_SET(e, n0, n1, n2) +| +- e != n0 && e != n1 ++ !IN_SET(e, n0, n1) +) diff --git a/coccinelle/o-ndelay.cocci b/coccinelle/o-ndelay.cocci new file mode 100644 index 0000000..669424a --- /dev/null +++ b/coccinelle/o-ndelay.cocci @@ -0,0 +1,4 @@ +@@ +@@ +- O_NDELAY ++ O_NONBLOCK diff --git a/coccinelle/reallocarray.cocci b/coccinelle/reallocarray.cocci new file mode 100644 index 0000000..21fe9df --- /dev/null +++ b/coccinelle/reallocarray.cocci @@ -0,0 +1,20 @@ +@@ +expression q, p, n, m; +@@ +- q = realloc(p, (n)*(m)) ++ q = reallocarray(p, n, m) +@@ +expression q, p, n, m; +@@ +- q = realloc(p, n*(m)) ++ q = reallocarray(p, n, m) +@@ +expression q, p, n, m; +@@ +- q = realloc(p, (n)*m) ++ q = reallocarray(p, n, m) +@@ +expression q, p, n, m; +@@ +- q = realloc(p, n*m) ++ q = reallocarray(p, n, m) diff --git a/coccinelle/redundant-if.cocci b/coccinelle/redundant-if.cocci new file mode 100644 index 0000000..515e36e --- /dev/null +++ b/coccinelle/redundant-if.cocci @@ -0,0 +1,54 @@ +@@ +expression r; +@@ +- if (r < 0) +- return r; +- if (r == 0) +- return 0; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r == 0) +- return 0; +- if (r < 0) +- return r; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r < 0) +- return r; +- if (r == 0) +- return r; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r == 0) +- return r; +- if (r < 0) +- return r; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r < 0) +- return r; +- if (r > 0) +- return r; ++ if (r != 0) ++ return r; +@@ +expression r; +@@ +- if (r > 0) +- return r; +- if (r < 0) +- return r; ++ if (r != 0) ++ return r; diff --git a/coccinelle/run-coccinelle.sh b/coccinelle/run-coccinelle.sh new file mode 100755 index 0000000..871547a --- /dev/null +++ b/coccinelle/run-coccinelle.sh @@ -0,0 +1,42 @@ +#!/bin/bash -e + +# Exclude following paths from the Coccinelle transformations +EXCLUDED_PATHS=( + "src/boot/efi/*" + "src/shared/linux/*" + "src/basic/linux/*" + # Symlinked to test-bus-vtable-cc.cc, which causes issues with the IN_SET macro + "src/libsystemd/sd-bus/test-bus-vtable.c" +) + +top="$(git rev-parse --show-toplevel)" +args= + +# Create an array from files tracked by git... +mapfile -t files < <(git ls-files ':/*.[ch]') +# ...and filter everything that matches patterns from EXCLUDED_PATHS +for excl in "${EXCLUDED_PATHS[@]}"; do + files=(${files[@]//$excl}) +done + +case "$1" in + -i) + args="$args --in-place" + shift + ;; +esac + +if ! parallel -h >/dev/null; then + echo 'Please install GNU parallel (package "parallel")' + exit 1 +fi + +for SCRIPT in ${@-$top/coccinelle/*.cocci}; do + echo "--x-- Processing $SCRIPT --x--" + TMPFILE=`mktemp` + echo "+ spatch --sp-file $SCRIPT $args ..." + parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \ + spatch --macro-file="$top/coccinelle/macros.h" --sp-file $SCRIPT $args ::: "${files[@]}" \ + 2>"$TMPFILE" || cat "$TMPFILE" + echo -e "--x-- Processed $SCRIPT --x--\n" +done diff --git a/coccinelle/safe_close-no-if.cocci b/coccinelle/safe_close-no-if.cocci new file mode 100644 index 0000000..81c5678 --- /dev/null +++ b/coccinelle/safe_close-no-if.cocci @@ -0,0 +1,7 @@ +@@ +expression fd; +@@ +- if (fd >= 0) { +- fd = safe_close(fd); +- } ++ fd = safe_close(fd); diff --git a/coccinelle/safe_close.cocci b/coccinelle/safe_close.cocci new file mode 100644 index 0000000..6fedd80 --- /dev/null +++ b/coccinelle/safe_close.cocci @@ -0,0 +1,18 @@ +@@ +expression fd; +@@ +- close(fd); +- fd = -1; ++ fd = safe_close(fd); +@@ +expression fd; +@@ +- close_nointr(fd); +- fd = -1; ++ fd = safe_close(fd); +@@ +expression fd; +@@ +- safe_close(fd); +- fd = -1; ++ fd = safe_close(fd); diff --git a/coccinelle/safe_closedir.cocci b/coccinelle/safe_closedir.cocci new file mode 100644 index 0000000..743ffd9 --- /dev/null +++ b/coccinelle/safe_closedir.cocci @@ -0,0 +1,27 @@ +@@ +expression p; +@@ +- if (p) { +- closedir(p); +- p = NULL; +- } ++ p = safe_closedir(p); +@@ +expression p; +@@ +- if (p) +- closedir(p); +- p = NULL; ++ p = safe_closedir(p); +@@ +expression p; +@@ +- closedir(p); +- p = NULL; ++ p = safe_closedir(p); +@@ +expression p; +@@ +- if (p) +- closedir(p); ++ safe_closedir(p); diff --git a/coccinelle/safe_fclose.cocci b/coccinelle/safe_fclose.cocci new file mode 100644 index 0000000..6961cd0 --- /dev/null +++ b/coccinelle/safe_fclose.cocci @@ -0,0 +1,27 @@ +@@ +expression p; +@@ +- if (p) { +- fclose(p); +- p = NULL; +- } ++ p = safe_fclose(p); +@@ +expression p; +@@ +- if (p) +- fclose(p); +- p = NULL; ++ p = safe_fclose(p); +@@ +expression p; +@@ +- fclose(p); +- p = NULL; ++ p = safe_fclose(p); +@@ +expression p; +@@ +- if (p) +- fclose(p); ++ safe_fclose(p); diff --git a/coccinelle/sd_event_source_disable_unref.cocci b/coccinelle/sd_event_source_disable_unref.cocci new file mode 100644 index 0000000..2763fef --- /dev/null +++ b/coccinelle/sd_event_source_disable_unref.cocci @@ -0,0 +1,36 @@ +@@ +expression p; +@@ +- if (p) { +- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF); +- p = sd_event_source_unref(p); +- } ++ p = sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- if (p) { +- sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); +- } ++ sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- if (p) { +- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); +- } ++ sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); ++ sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); ++ sd_event_source_disable_unref(p); diff --git a/coccinelle/set_ensure_put.cocci b/coccinelle/set_ensure_put.cocci new file mode 100644 index 0000000..92d7970 --- /dev/null +++ b/coccinelle/set_ensure_put.cocci @@ -0,0 +1,18 @@ +@@ +local idexpression r; +expression p, k, x; +@@ +- r = set_ensure_allocated(&p, k); +- if (r < 0) +- return ...; +- r = set_put(p, x); ++ r = set_ensure_put(&p, k, x); +@@ +local idexpression r; +expression p, k, x; +@@ +- r = set_ensure_allocated(p, k); +- if (r < 0) +- return ...; +- r = set_put(*p, x); ++ r = set_ensure_put(p, k, x); diff --git a/coccinelle/strempty.cocci b/coccinelle/strempty.cocci new file mode 100644 index 0000000..0868184 --- /dev/null +++ b/coccinelle/strempty.cocci @@ -0,0 +1,72 @@ +@@ +/* Avoid running this transformation on the strempty function itself and + * on the "make_expression" macro in src/libsystemd/sd-bus/bus-convenience.c. + * As Coccinelle's Location object doesn't support macro "detection", use + * a pretty horrifying combo of specifying a file and a special "something_else" + * position element, which is, apparently, the default value of + * "current_element" before it's set (according to the source code), thus + * matching any "top level" position, including macros. Let's hope we never + * introduce a function called "something_else"... + */ +position p : script:python() { + not (p[0].current_element == "strempty" or + (p[0].file == "src/libsystemd/sd-bus/bus-convenience.c" and + p[0].current_element == "something_else")) +}; +expression s; +@@ +( +- s@p ?: "" ++ strempty(s) +| +- s@p ? s : "" ++ strempty(s) +) + +@@ +position p : script:python() { p[0].current_element != "strempty" }; +expression s; +@@ +- if (!s@p) +- s = ""; ++ s = strempty(s); + +@@ +position p : script:python() { p[0].current_element != "strnull" }; +expression s; +@@ +( +- s@p ?: "(null)" ++ strnull(s) +| +- s@p ? s : "(null)" ++ strnull(s) +) + +@@ +position p : script:python() { p[0].current_element != "strnull" }; +expression s; +@@ +- if (!s@p) +- s = "(null)"; ++ s = strnull(s); + +@@ +position p : script:python() { p[0].current_element != "strna" }; +expression s; +@@ +( +- s@p ?: "n/a" ++ strna(s) +| +- s@p ? s : "n/a" ++ strna(s) +) + +@@ +position p : script:python() { p[0].current_element != "strna" }; +expression s; +@@ +- if (!s@p) +- s = "n/a"; ++ s = strna(s); diff --git a/coccinelle/strjoin.cocci b/coccinelle/strjoin.cocci new file mode 100644 index 0000000..46f70c4 --- /dev/null +++ b/coccinelle/strjoin.cocci @@ -0,0 +1,15 @@ +@@ +position p : script:python() { p[0].current_element != "test_strjoin" }; +expression t; +expression list args; +@@ +( +- strjoin@p(args, NULL); ++ strjoin(args); +| +- t = strjoin@p(args, NULL); ++ t = strjoin(args); +| +- return strjoin@p(args, NULL); ++ return strjoin(args); +) diff --git a/coccinelle/strjoina.cocci b/coccinelle/strjoina.cocci new file mode 100644 index 0000000..a6236eb --- /dev/null +++ b/coccinelle/strjoina.cocci @@ -0,0 +1,6 @@ +@@ +expression n, m; +expression list s; +@@ +- n = strjoina(m, s, NULL); ++ n = strjoina(m, s); diff --git a/coccinelle/strv_free.cocci b/coccinelle/strv_free.cocci new file mode 100644 index 0000000..0ad56f7 --- /dev/null +++ b/coccinelle/strv_free.cocci @@ -0,0 +1,27 @@ +@@ +expression p; +@@ +- strv_free(p); +- p = NULL; ++ p = strv_free(p); +@@ +expression p; +@@ +- if (p) +- strv_free(p); +- p = NULL; ++ p = strv_free(p); +@@ +expression p; +@@ +- if (p) { +- strv_free(p); +- p = NULL; +- } ++ p = strv_free(p); +@@ +expression p; +@@ +- if (p) +- strv_free(p); ++ strv_free(p); diff --git a/coccinelle/swap-two.cocci b/coccinelle/swap-two.cocci new file mode 100644 index 0000000..edf7d32 --- /dev/null +++ b/coccinelle/swap-two.cocci @@ -0,0 +1,7 @@ +@@ +expression x, y, z; +@@ +- z = x; +- x = y; +- y = z; ++ SWAP_TWO(x, y); diff --git a/coccinelle/synthetic-errno.cocci b/coccinelle/synthetic-errno.cocci new file mode 100644 index 0000000..650c37e --- /dev/null +++ b/coccinelle/synthetic-errno.cocci @@ -0,0 +1,48 @@ +@@ +expression e; +expression list args; +@@ +( +/* Ignore one specific case in src/shared/bootspec.c where we want to stick + * with the log_debug() + return pattern */ +log_debug("Found no default boot entry :("); +| +- log_debug(args); +- return -e; ++ return log_debug_errno(SYNTHETIC_ERRNO(e), args); +) +@@ +expression e; +expression list args; +@@ +- log_info(args); +- return -e; ++ return log_info_errno(SYNTHETIC_ERRNO(e), args); +@@ +expression e; +expression list args; +@@ +- log_notice(args); +- return -e; ++ return log_notice_errno(SYNTHETIC_ERRNO(e), args); +@@ +expression e; +expression list args; +@@ +- log_error(args); +- return -e; ++ return log_error_errno(SYNTHETIC_ERRNO(e), args); +@@ +expression e; +expression list args; +@@ +- log_emergency(args); +- return -e; ++ return log_emergency_errno(SYNTHETIC_ERRNO(e), args); +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +identifier ERRNO =~ "^E[A-Z]+$"; +expression list args; +@@ +- log_LEVEL_errno(ERRNO, args); ++ log_LEVEL_errno(SYNTHETIC_ERRNO(ERRNO), args); diff --git a/coccinelle/take-fd.cocci b/coccinelle/take-fd.cocci new file mode 100644 index 0000000..f7124e7 --- /dev/null +++ b/coccinelle/take-fd.cocci @@ -0,0 +1,21 @@ +@@ +local idexpression p; +expression q; +@@ +- p = q; +- q = -1; +- return p; ++ return TAKE_FD(q); + +/* The ideal solution would use 'local idexpression' to avoid matching errno, + * which is a global variable. However, 'idexpression' nor 'identifier' + * would match, for example, "x->fd", which is considered 'expression' in + * the SmPL grammar + */ +@@ +expression p != errno; +expression q; +@@ +- p = q; +- q = -1; ++ p = TAKE_FD(q); diff --git a/coccinelle/take-ptr.cocci b/coccinelle/take-ptr.cocci new file mode 100644 index 0000000..0cebe81 --- /dev/null +++ b/coccinelle/take-ptr.cocci @@ -0,0 +1,14 @@ +@@ +local idexpression p; +expression q; +@@ +- p = q; +- q = NULL; +- return p; ++ return TAKE_PTR(q); +@@ +expression p, q; +@@ +- p = q; +- q = NULL; ++ p = TAKE_PTR(q); diff --git a/coccinelle/while-true.cocci b/coccinelle/while-true.cocci new file mode 100644 index 0000000..c23fb11 --- /dev/null +++ b/coccinelle/while-true.cocci @@ -0,0 +1,12 @@ +@@ +statement s; +@@ +- while (true) ++ for (;;) +s +@@ +statement s; +@@ +- while (1) ++ for (;;) +s diff --git a/coccinelle/xsprintf.cocci b/coccinelle/xsprintf.cocci new file mode 100644 index 0000000..660a35e --- /dev/null +++ b/coccinelle/xsprintf.cocci @@ -0,0 +1,7 @@ +@@ +position p : script:python() { not p[0].file.startswith("man/") }; +expression e, fmt; +expression list vaargs; +@@ +- snprintf@p(e, sizeof(e), fmt, vaargs); ++ xsprintf(e, fmt, vaargs); diff --git a/coccinelle/zz-drop-braces.cocci b/coccinelle/zz-drop-braces.cocci new file mode 100644 index 0000000..34bf12f --- /dev/null +++ b/coccinelle/zz-drop-braces.cocci @@ -0,0 +1,27 @@ +@@ +position p : script:python() { p[0].file != "src/journal/lookup3.c" }; +identifier id; +expression e; +@@ +if (...) +- { +( + id@p(...); +| + e@p; +) +- } + +@@ +position p : script:python() { p[0].file != "src/journal/lookup3.c" }; +identifier id; +expression e; +@@ +if (...) +- { +( + return id@p(...); +| + return e@p; +) +- } |