Mesa (master): util: fix undefined behavior

Dylan Noblesmith nobled at kemper.freedesktop.org
Fri Apr 13 14:30:13 UTC 2012


Module: Mesa
Branch: master
Commit: ccff74971203b533bf16b46b49a9e61753f75e6c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ccff74971203b533bf16b46b49a9e61753f75e6c

Author: Dylan Noblesmith <nobled at dreamwidth.org>
Date:   Sun Apr  1 18:21:47 2012 +0000

util: fix undefined behavior

container_of() can legally return anything, even invalid addresses
that cause segfaults, when 'sample' is an uninitialized pointer.

Bug exposed by clang.

NOTE: This is a candidate for the 8.0 branch.

---

 src/gallium/auxiliary/util/u_double_list.h |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h
index 2384c36..9d1129b 100644
--- a/src/gallium/auxiliary/util/u_double_list.h
+++ b/src/gallium/auxiliary/util/u_double_list.h
@@ -105,6 +105,11 @@ static INLINE void list_delinit(struct list_head *item)
 #define LIST_IS_EMPTY(__list)                   \
     ((__list)->next == (__list))
 
+/**
+ * Cast from a pointer to a member of a struct back to the containing struct.
+ *
+ * 'sample' MUST be initialized, or else the result is undefined!
+ */
 #ifndef container_of
 #define container_of(ptr, sample, member)				\
     (void *)((char *)(ptr)						\
@@ -112,29 +117,29 @@ static INLINE void list_delinit(struct list_head *item)
 #endif
 
 #define LIST_FOR_EACH_ENTRY(pos, head, member)				\
-   for (pos = container_of((head)->next, pos, member);			\
+   for (pos = NULL, pos = container_of((head)->next, pos, member);	\
 	&pos->member != (head);						\
 	pos = container_of(pos->member.next, pos, member))
 
 #define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member)	\
-   for (pos = container_of((head)->next, pos, member),			\
+   for (pos = NULL, pos = container_of((head)->next, pos, member),	\
 	storage = container_of(pos->member.next, pos, member);	\
 	&pos->member != (head);						\
 	pos = storage, storage = container_of(storage->member.next, storage, member))
 
 #define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member)	\
-   for (pos = container_of((head)->prev, pos, member),			\
+   for (pos = NULL, pos = container_of((head)->prev, pos, member),	\
 	storage = container_of(pos->member.prev, pos, member);		\
 	&pos->member != (head);						\
 	pos = storage, storage = container_of(storage->member.prev, storage, member))
 
 #define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member)		\
-   for (pos = container_of((start), pos, member);			\
+   for (pos = NULL, pos = container_of((start), pos, member);		\
 	&pos->member != (head);						\
 	pos = container_of(pos->member.next, pos, member))
 
 #define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member)		\
-   for (pos = container_of((start), pos, member);			\
+   for (pos = NULL, pos = container_of((start), pos, member);		\
 	&pos->member != (head);						\
 	pos = container_of(pos->member.prev, pos, member))
 




More information about the mesa-commit mailing list