summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Noblesmith <nobled@dreamwidth.org>2012-04-01 18:21:47 +0000
committerDylan Noblesmith <nobled@dreamwidth.org>2012-04-29 11:22:15 +0000
commit546abd25038dc4ad9af17a0f99bae818b980436e (patch)
treeb5b6223bd360389bb41abf731f2c4b7f133ec09f
parentbcc5caf642a9beec324657becac501944ce4dc23 (diff)
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. (cherry picked from commit ccff74971203b533bf16b46b49a9e61753f75e6c)
-rw-r--r--src/gallium/auxiliary/util/u_double_list.h15
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 2384c36cb13..9d1129b185d 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))