diff options
author | Adrian Moreno <amorenoz@redhat.com> | 2022-03-23 12:56:13 +0100 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2022-03-30 16:59:02 +0200 |
commit | d4566085edf50033087652f35f92b9b77cbec70f (patch) | |
tree | b44b7c6a2268e5b8f66c36c13a2eb771644569e8 /include | |
parent | 5a2940978e0411267761d483e0777296fb0ebf7f (diff) | |
download | openvswitch-d4566085edf50033087652f35f92b9b77cbec70f.tar.gz |
list: use multi-variable helpers for list loops.
Use multi-variable iteration helpers to rewrite non-safe loops.
There is an important behavior change compared with the previous
implementation: When the loop ends normally (i.e: not via "break;"), the
object pointer provided by the user is NULL. This is safer because it's
not guaranteed that it would end up pointing a valid address.
For pop iterator, set the variable to NULL when the loop ends.
Clang-analyzer has successfully picked the potential null-pointer
dereference on the code that triggered this change (bond.c) and nothing
else has been detected.
For _SAFE loops, use the LONG version for backwards compatibility.
Acked-by: Eelco Chaudron <echaudro@redhat.com>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/openvswitch/list.h | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/include/openvswitch/list.h b/include/openvswitch/list.h index 8ad5eeb32..bbd2edbd0 100644 --- a/include/openvswitch/list.h +++ b/include/openvswitch/list.h @@ -72,37 +72,48 @@ static inline bool ovs_list_is_empty(const struct ovs_list *); static inline bool ovs_list_is_singleton(const struct ovs_list *); static inline bool ovs_list_is_short(const struct ovs_list *); -#define LIST_FOR_EACH(ITER, MEMBER, LIST) \ - for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \ - &(ITER)->MEMBER != (LIST); \ - ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER)) -#define LIST_FOR_EACH_CONTINUE(ITER, MEMBER, LIST) \ - for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER); \ - &(ITER)->MEMBER != (LIST); \ - ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER)) -#define LIST_FOR_EACH_REVERSE(ITER, MEMBER, LIST) \ - for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER); \ - &(ITER)->MEMBER != (LIST); \ - ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER)) -#define LIST_FOR_EACH_REVERSE_SAFE(ITER, PREV, MEMBER, LIST) \ - for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER); \ - (&(ITER)->MEMBER != (LIST) \ - ? INIT_CONTAINER(PREV, (ITER)->MEMBER.prev, MEMBER), 1 \ - : 0); \ - (ITER) = (PREV)) -#define LIST_FOR_EACH_REVERSE_CONTINUE(ITER, MEMBER, LIST) \ - for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER); \ - &(ITER)->MEMBER != (LIST); \ - ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER)) -#define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST) \ - for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \ - (&(ITER)->MEMBER != (LIST) \ - ? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1 \ - : 0); \ - (ITER) = (NEXT)) -#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \ - while (!ovs_list_is_empty(LIST) \ - && (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1)) +#define LIST_FOR_EACH(VAR, MEMBER, LIST) \ + for (INIT_MULTIVAR(VAR, MEMBER, (LIST)->next, struct ovs_list); \ + CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST)); \ + UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->next)) + +#define LIST_FOR_EACH_CONTINUE(VAR, MEMBER, LIST) \ + for (INIT_MULTIVAR(VAR, MEMBER, VAR->MEMBER.next, struct ovs_list); \ + CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST)); \ + UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->next)) + +#define LIST_FOR_EACH_REVERSE(VAR, MEMBER, LIST) \ + for (INIT_MULTIVAR(VAR, MEMBER, (LIST)->prev, struct ovs_list); \ + CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST)); \ + UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->prev)) + +#define LIST_FOR_EACH_REVERSE_CONTINUE(VAR, MEMBER, LIST) \ + for (INIT_MULTIVAR(VAR, MEMBER, VAR->MEMBER.prev, struct ovs_list); \ + CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST)); \ + UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->prev)) + +#define LIST_FOR_EACH_REVERSE_SAFE(VAR, PREV, MEMBER, LIST) \ + for (INIT_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, (LIST)->prev, \ + struct ovs_list); \ + CONDITION_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, \ + ITER_VAR(VAR) != (LIST), \ + ITER_VAR(PREV) = ITER_VAR(VAR)->prev, \ + ITER_VAR(PREV) != (LIST)); \ + UPDATE_MULTIVAR_SAFE_LONG(VAR, PREV)) + +#define LIST_FOR_EACH_SAFE(VAR, NEXT, MEMBER, LIST) \ + for (INIT_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER, (LIST)->next, \ + struct ovs_list); \ + CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER, \ + ITER_VAR(VAR) != (LIST), \ + ITER_VAR(NEXT) = ITER_VAR(VAR)->next, \ + ITER_VAR(NEXT) != (LIST)); \ + UPDATE_MULTIVAR_SAFE_LONG(VAR, NEXT)) + +#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \ + while (!ovs_list_is_empty(LIST) ? \ + (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1) : \ + (ITER = NULL, 0)) /* Inline implementations. */ |