testsuite: add various -Wanalyzer-null-dereference false +ve test cases
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 9 Mar 2023 21:21:02 +0000 (16:21 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 9 Mar 2023 21:21:02 +0000 (16:21 -0500)
There are various -Wanalyzer-null-dereference false +ves in bugzilla
that I've been attempting to fix.  Unfortunately I haven't made much
progress, but it seems worth at least capturing the reduced
reproducers as test cases, to make it easier to spot changes in
behavior.

gcc/testsuite/ChangeLog:
PR analyzer/102671
PR analyzer/105755
PR analyzer/108251
PR analyzer/108400
* gcc.dg/analyzer/null-deref-pr102671-1.c: New test, reduced
from Emacs.
* gcc.dg/analyzer/null-deref-pr102671-2.c: Likewise.
* gcc.dg/analyzer/null-deref-pr105755.c: Likewise.
* gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c:
New test, reduced from haproxy's src/ssl_sample.c.
* gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c:
Likewise.
* gcc.dg/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c: New
test, reduced from SoftEtherVPN's src/Cedar/WebUI.c.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c [new file with mode: 0644]

diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c
new file mode 100644 (file)
index 0000000..12a0a48
--- /dev/null
@@ -0,0 +1,167 @@
+/* { dg-additional-options "-O2 -Wno-shift-count-overflow" } */
+
+struct lisp;
+union vectorlike_header { long size; };
+struct Lisp_Symbol { void *unused; };
+extern struct Lisp_Symbol lispsym[];
+
+static _Bool
+TAGGEDP (struct lisp *a, unsigned tag)
+{
+  return ! (((unsigned) (long) a - tag) & 7);
+}
+
+static _Bool
+VECTORLIKEP (struct lisp *x)
+{
+  return TAGGEDP (x, 5);
+}
+
+static _Bool
+PSEUDOVECTOR_TYPEP (union vectorlike_header const *a, int code)
+{
+  long PSEUDOVECTOR_FLAG = 1L << 62;
+  long PVEC_TYPE_MASK = 0x3fL << 24;
+  return ((a->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))
+         == (PSEUDOVECTOR_FLAG | (code << 24)));
+}
+
+static _Bool
+PSEUDOVECTORP (struct lisp *a, int code)
+{
+  if (! VECTORLIKEP (a))
+    return 0;
+  else
+    return PSEUDOVECTOR_TYPEP ((union vectorlike_header *) ((char *) a - 5),
+                              code);
+}
+
+static struct lisp *
+builtin_lisp_symbol (int index)
+{
+  return (struct lisp *) (index * sizeof *lispsym);
+}
+
+static _Bool
+NILP (struct lisp *x)
+{
+  return x == builtin_lisp_symbol (0);
+}
+
+
+void wrong_type_argument (struct lisp *, struct lisp *);
+
+static void
+CHECK_TYPE (int ok, struct lisp *predicate, struct lisp *x)
+{
+  if (!ok)
+    wrong_type_argument (predicate, x);
+}
+
+
+struct buffer
+{
+  union vectorlike_header header;
+  struct buffer *base_buffer;
+  int window_count;
+};
+
+static _Bool
+BUFFERP (struct lisp *a)
+{
+  return PSEUDOVECTORP (a, 12);
+}
+
+static struct buffer *
+XBUFFER (struct lisp *a)
+{
+  return (struct buffer *) ((char *) a - 5);
+}
+
+
+struct window
+{
+  union vectorlike_header header;
+  struct lisp *next;
+  struct lisp *contents;
+};
+
+static _Bool
+WINDOWP (struct lisp *a)
+{
+  return PSEUDOVECTORP (a, 12);
+}
+
+static void
+CHECK_WINDOW (struct lisp *x)
+{
+  CHECK_TYPE (WINDOWP (x), builtin_lisp_symbol (1360), x);
+}
+
+static struct window *
+XWINDOW (struct lisp *a)
+{
+  return (struct window *) ((char *) a - 5);
+}
+
+static void
+wset_combination (struct window *w, _Bool horflag, struct lisp *val)
+{
+  w->contents = val;
+}
+
+extern struct lisp *selected_window;
+
+struct window *
+decode_live_window (register struct lisp *window)
+{
+  if (NILP (window))
+    return XWINDOW (selected_window);
+  CHECK_TYPE (WINDOWP (window) && BUFFERP (XWINDOW (window)->contents),
+             builtin_lisp_symbol (1351), window);
+  return XWINDOW (window);
+}
+
+struct window *
+decode_any_window (register struct lisp *window)
+{
+  struct window *w;
+  if (NILP (window))
+    return XWINDOW (selected_window);
+  CHECK_WINDOW (window);
+  w = XWINDOW (window);
+  return w;
+}
+
+static void
+adjust_window_count (struct window *w, int arg)
+{
+  if (BUFFERP (w->contents))
+    {
+      struct buffer *b = XBUFFER (w->contents);
+      if (b->base_buffer)
+       b = b->base_buffer;
+      b->window_count += arg;
+    }
+}
+
+void
+wset_buffer (struct window *w, struct lisp *val)
+{
+  adjust_window_count (w, -1);
+  w->contents = val;
+  adjust_window_count (w, 1);
+}
+
+void
+delete_all_child_windows (struct lisp *window)
+{
+  struct window *w = XWINDOW (window);
+  if (!NILP (w->next))
+    delete_all_child_windows (w->next);
+  if (WINDOWP (w->contents))
+    {
+      delete_all_child_windows (w->contents);
+      wset_combination (w, 0, builtin_lisp_symbol (0));
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-2.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-2.c
new file mode 100644 (file)
index 0000000..5108182
--- /dev/null
@@ -0,0 +1,78 @@
+/* { dg-additional-options "-O2 -Wno-shift-count-overflow" } */
+
+struct lisp;
+union vectorlike_header { long size; };
+struct Lisp_Symbol { void *unused; };
+extern struct Lisp_Symbol lispsym[];
+struct Lisp_Cons { struct lisp *cdr; };
+
+static struct Lisp_Cons *
+XCONS (struct lisp *a)
+{
+  return (struct Lisp_Cons *) ((char *) a - 3);
+}
+
+static struct lisp *
+XCDR (struct lisp *c)
+{
+  return XCONS (c)->cdr;
+}
+
+static _Bool
+TAGGEDP (struct lisp *a, unsigned tag)
+{
+  return ! (((unsigned) (long) a - tag) & 7);
+}
+
+static _Bool
+VECTORLIKEP (struct lisp *x)
+{
+  return TAGGEDP (x, 5);
+}
+
+static _Bool
+PSEUDOVECTOR_TYPEP (union vectorlike_header const *a, int code)
+{
+  long PSEUDOVECTOR_FLAG = 1L << 62;
+  long PVEC_TYPE_MASK = 0x3fL << 24;
+  return ((a->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) /* { dg-bogus "dereference of NULL 'time'" "PR analyzer/107526" { xfail *-*-* } } */
+         == (PSEUDOVECTOR_FLAG | (code << 24)));
+}
+
+static _Bool
+PSEUDOVECTORP (struct lisp *a, int code)
+{
+  if (! VECTORLIKEP (a))
+    return 0;
+  else
+    return PSEUDOVECTOR_TYPEP ((union vectorlike_header *) ((char *) a - 5),
+                              code);
+}
+
+static _Bool
+FIXNUMP (struct lisp *x)
+{
+  return ! (((unsigned) (long) x - 2) & 3);
+}
+
+static _Bool
+BIGNUMP (struct lisp *x)
+{
+  return PSEUDOVECTORP (x, 2);
+}
+
+void some_function ();
+
+static void
+decode_time_components (struct lisp *low)
+{
+  if (BIGNUMP (low))
+    some_function ();
+}
+
+_Bool
+Ftime_convert (struct lisp *time)
+{
+  decode_time_components (time ? XCDR (time) : time);
+  return BIGNUMP (time);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c
new file mode 100644 (file)
index 0000000..f6bf383
--- /dev/null
@@ -0,0 +1,193 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex -O2" } */
+
+typedef long int ptrdiff_t;
+typedef long int EMACS_INT;
+typedef long int intmax_t;
+
+enum Lisp_Type
+  {
+    Lisp_Symbol = 0,
+    Lisp_Vectorlike = 5,
+  };
+typedef struct Lisp_X *Lisp_Object;
+
+static inline EMACS_INT
+XLI (Lisp_Object o)
+{
+  return (EMACS_INT) o;
+}
+
+static inline void *
+XLP (Lisp_Object o)
+{
+  return (void *) o;
+}
+
+struct Lisp_Symbol
+{
+  Lisp_Object name;
+  Lisp_Object value;
+};
+extern struct Lisp_Symbol lispsym[1455];
+
+union vectorlike_header
+  {
+    ptrdiff_t size;
+  };
+static inline _Bool
+TAGGEDP (Lisp_Object a, enum Lisp_Type tag)
+{
+  return (! (((unsigned) XLI (a) - (unsigned) (tag)) & 7));
+}
+
+struct Lisp_Symbol_With_Pos
+{
+  union vectorlike_header header;
+  Lisp_Object sym;
+  Lisp_Object pos;
+};
+
+static inline _Bool
+PSEUDOVECTORP (Lisp_Object a, int code)
+{
+  return (TAGGEDP (a, Lisp_Vectorlike)
+         && ((((union vectorlike_header *)
+               ((char *) XLP ((a)) - Lisp_Vectorlike))->size
+              & 0x400000003f000000)
+             == (0x4000000000000000 | (code << 24))));
+}
+
+static inline _Bool
+BARE_SYMBOL_P (Lisp_Object x)
+{
+  return TAGGEDP (x, Lisp_Symbol);
+}
+
+static inline _Bool
+SYMBOL_WITH_POS_P (Lisp_Object x)
+{
+  return PSEUDOVECTORP (x, 6);
+}
+
+static inline struct Lisp_Symbol_With_Pos *
+XSYMBOL_WITH_POS (Lisp_Object a)
+{
+  return (struct Lisp_Symbol_With_Pos *) ((char *) XLP (a) - Lisp_Vectorlike);
+}
+
+static inline Lisp_Object
+make_lisp_symbol (struct Lisp_Symbol *sym)
+{
+  return (Lisp_Object) ((char *) sym - (char *) lispsym);
+}
+
+static inline Lisp_Object
+builtin_lisp_symbol (int index)
+{
+  return make_lisp_symbol (&lispsym[index]);
+}
+
+static inline _Bool
+BASE_EQ (Lisp_Object x, Lisp_Object y)
+{
+  return XLI (x) == XLI (y);
+}
+
+extern _Bool symbols_with_pos_enabled;
+
+static inline _Bool
+EQ (Lisp_Object x, Lisp_Object y)
+{
+  return (XLI (x) == XLI (y)
+         || (symbols_with_pos_enabled
+             && (SYMBOL_WITH_POS_P (x)
+                 ? (BARE_SYMBOL_P (y)
+                    ? XLI (XSYMBOL_WITH_POS(x)->sym) == XLI (y)
+                    : (SYMBOL_WITH_POS_P(y)
+                       && (XLI (XSYMBOL_WITH_POS(x)->sym)
+                           == XLI (XSYMBOL_WITH_POS(y)->sym))))
+                 : (SYMBOL_WITH_POS_P (y) && BARE_SYMBOL_P (x)
+                    && (XLI (x) == XLI ((XSYMBOL_WITH_POS (y))->sym))))));
+}
+
+static inline _Bool
+NILP (Lisp_Object x)
+{
+  return BASE_EQ (x, builtin_lisp_symbol (0));
+}
+
+static inline _Bool
+ASCII_CHAR_P (intmax_t c)
+{
+  return 0 <= c && c < 0x80;
+}
+
+struct Lisp_Char_Table
+  {
+    union vectorlike_header header;
+    Lisp_Object defalt;
+    Lisp_Object parent;
+    Lisp_Object ascii;
+};
+
+extern Lisp_Object char_table_ref (Lisp_Object, int);
+
+static inline _Bool
+CHAR_TABLE_P (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, 28);
+}
+
+static inline struct Lisp_Char_Table *
+XCHAR_TABLE (Lisp_Object a)
+{
+  return (struct Lisp_Char_Table *) ((char *) XLP (a) - Lisp_Vectorlike);
+}
+
+struct Lisp_Sub_Char_Table
+{
+  union vectorlike_header header;
+  Lisp_Object contents[];
+};
+
+static inline _Bool
+SUB_CHAR_TABLE_P (Lisp_Object a)
+{
+  return PSEUDOVECTORP (a, 29);
+}
+
+static inline struct Lisp_Sub_Char_Table *
+XSUB_CHAR_TABLE (Lisp_Object a)
+{
+  return (struct Lisp_Sub_Char_Table *) ((char *) XLP (a) - Lisp_Vectorlike);
+}
+
+static inline Lisp_Object
+CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx)
+{
+  for (struct Lisp_Char_Table *tbl = XCHAR_TABLE (ct); ;
+       tbl = XCHAR_TABLE (tbl->parent))
+    {
+      Lisp_Object val = (! SUB_CHAR_TABLE_P (tbl->ascii) ? tbl->ascii
+                        : XSUB_CHAR_TABLE (tbl->ascii)->contents[idx]);
+      if (NILP (val))
+       val = tbl->defalt;
+      if (!NILP (val) || NILP (tbl->parent))
+       return val;
+    }
+}
+
+static inline Lisp_Object
+CHAR_TABLE_REF (Lisp_Object ct, int idx)
+{
+  return (ASCII_CHAR_P (idx)
+         ? CHAR_TABLE_REF_ASCII (ct, idx)
+         : char_table_ref (ct, idx));
+}
+
+_Bool
+word_boundary_p (Lisp_Object char_script_table, int c1, int c2)
+{
+  return EQ (CHAR_TABLE_REF (char_script_table, c1),
+            CHAR_TABLE_REF (char_script_table, c2));
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c
new file mode 100644 (file)
index 0000000..2a9c715
--- /dev/null
@@ -0,0 +1,98 @@
+/* Reduced from haproxy's src/ssl_sample.c  */
+
+/* { dg-additional-options "-O2" } */
+
+union sample_value {
+  long long int sint;
+  /* [...snip...]  */
+};
+
+struct sample_data {
+ int type;
+ union sample_value u;
+};
+
+enum {
+  /* [...snip...]  */
+ SMP_T_BOOL,
+  /* [...snip...]  */
+};
+struct sample {
+ unsigned int flags;
+ struct sample_data data;
+  /* [...snip...]  */
+ struct session *sess;
+ struct stream *strm;
+  /* [...snip...]  */
+};
+struct arg {
+  /* [...snip...]  */
+};
+enum obj_type {
+ OBJ_TYPE_NONE = 0,
+  /* [...snip...]  */
+ OBJ_TYPE_CONN,
+  /* [...snip...]  */
+ OBJ_TYPE_CHECK,
+ OBJ_TYPE_ENTRIES
+};
+enum {
+  /* [...snip...]  */
+ CO_FL_EARLY_SSL_HS = 0x00004000,
+ CO_FL_EARLY_DATA = 0x00008000,
+  /* [...snip...]  */
+ CO_FL_SSL_WAIT_HS = 0x08000000,
+  /* [...snip...]  */
+};
+struct connection {
+ enum obj_type obj_type;
+ unsigned char err_code;
+  /* [...snip...]  */
+ unsigned int flags;
+  /* [...snip...]  */
+};
+
+static inline enum obj_type obj_type(const enum obj_type *t)
+{
+ if (!t || *t >= OBJ_TYPE_ENTRIES)
+  return OBJ_TYPE_NONE;
+ return *t;
+}
+static inline struct connection *__objt_conn(enum obj_type *t)
+{
+ return ((struct connection *)(((void *)(t)) - ((long)&((struct connection *)0)->obj_type)));
+}
+static inline struct connection *objt_conn(enum obj_type *t)
+{
+ if (!t || *t != OBJ_TYPE_CONN)
+   return ((void *)0);
+ return __objt_conn(t);
+}
+struct session {
+  /* [...snip...]  */
+ enum obj_type *origin;
+  /* [...snip...]  */
+};
+typedef struct ssl_st SSL;
+SSL *ssl_sock_get_ssl_object(struct connection *conn);
+
+/*****************************************************************************/
+
+int
+smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+ SSL *ssl;
+ struct connection *conn;
+
+ conn = objt_conn(smp->sess->origin);
+ ssl = ssl_sock_get_ssl_object(conn);
+ if (!ssl)
+  return 0;
+
+ smp->flags = 0;
+ smp->data.type = SMP_T_BOOL;
+ smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) && /* { dg-bogus "dereference of NULL" "PR analyzer/108251" { xfail *-*-*} } */
+     (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
+
+ return 1;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c
new file mode 100644 (file)
index 0000000..d83af19
--- /dev/null
@@ -0,0 +1,96 @@
+/* Reduced from haproxy's src/ssl_sample.c  */
+
+union sample_value {
+  long long int sint;
+  /* [...snip...]  */
+};
+
+struct sample_data {
+ int type;
+ union sample_value u;
+};
+
+enum {
+  /* [...snip...]  */
+ SMP_T_BOOL,
+  /* [...snip...]  */
+};
+struct sample {
+ unsigned int flags;
+ struct sample_data data;
+  /* [...snip...]  */
+ struct session *sess;
+ struct stream *strm;
+  /* [...snip...]  */
+};
+struct arg {
+  /* [...snip...]  */
+};
+enum obj_type {
+ OBJ_TYPE_NONE = 0,
+  /* [...snip...]  */
+ OBJ_TYPE_CONN,
+  /* [...snip...]  */
+ OBJ_TYPE_CHECK,
+ OBJ_TYPE_ENTRIES
+};
+enum {
+  /* [...snip...]  */
+ CO_FL_EARLY_SSL_HS = 0x00004000,
+ CO_FL_EARLY_DATA = 0x00008000,
+  /* [...snip...]  */
+ CO_FL_SSL_WAIT_HS = 0x08000000,
+  /* [...snip...]  */
+};
+struct connection {
+ enum obj_type obj_type;
+ unsigned char err_code;
+  /* [...snip...]  */
+ unsigned int flags;
+  /* [...snip...]  */
+};
+
+static inline enum obj_type obj_type(const enum obj_type *t)
+{
+ if (!t || *t >= OBJ_TYPE_ENTRIES)
+  return OBJ_TYPE_NONE;
+ return *t;
+}
+static inline struct connection *__objt_conn(enum obj_type *t)
+{
+ return ((struct connection *)(((void *)(t)) - ((long)&((struct connection *)0)->obj_type)));
+}
+static inline struct connection *objt_conn(enum obj_type *t)
+{
+ if (!t || *t != OBJ_TYPE_CONN)
+   return ((void *)0);
+ return __objt_conn(t);
+}
+struct session {
+  /* [...snip...]  */
+ enum obj_type *origin;
+  /* [...snip...]  */
+};
+typedef struct ssl_st SSL;
+SSL *ssl_sock_get_ssl_object(struct connection *conn);
+
+/*****************************************************************************/
+
+int
+smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+ SSL *ssl;
+ struct connection *conn;
+
+ conn = objt_conn(smp->sess->origin);
+ ssl = ssl_sock_get_ssl_object(conn);
+ if (!ssl)
+  return 0;
+
+ smp->flags = 0;
+ smp->data.type = SMP_T_BOOL;
+ smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) && /* { dg-bogus "dereference of NULL 'conn'" "PR analyzer/108251" { xfail *-*-*} } */
+     (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
+
+ return 1;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c
new file mode 100644 (file)
index 0000000..1e4613c
--- /dev/null
@@ -0,0 +1,77 @@
+/* Reduced from SoftEtherVPN's src/Cedar/WebUI.c.   */
+
+#define NULL ((void *)0)
+typedef int (COMPARE)(void *p1, void *p2);
+typedef unsigned int UINT;
+typedef unsigned long int UINT64;
+typedef struct LIST LIST;
+typedef struct STRMAP_ENTRY STRMAP_ENTRY;
+typedef struct WEBUI
+{
+       /* [...snip...] */
+       LIST *Contexts;
+} WEBUI;
+
+typedef struct WU_CONTEXT
+{
+       /* [...snip...] */
+       UINT64 ExpireDate;
+} WU_CONTEXT;
+
+struct LIST
+{
+       /* [...snip...] */
+       UINT num_item, num_reserved;
+       void **p;
+       /* [...snip...] */
+};
+
+#define        LIST_DATA(o, i)         (((o) != NULL) ? ((o)->p[(i)]) : NULL)
+#define        LIST_NUM(o)                     (((o) != NULL) ? (o)->num_item : 0)
+
+
+struct STRMAP_ENTRY
+{
+       char *Name;
+       void *Value;
+};
+
+void Free(void *addr);
+void Add(LIST *o, void *p);
+_Bool Delete(LIST *o, void *p);
+void LockList(LIST *o);
+void UnlockList(LIST *o);
+void ReleaseList(LIST *o);
+LIST *NewList(COMPARE *cmp);
+UINT64 Tick64();
+void WuFreeContext(WU_CONTEXT *context);
+
+void WuExpireSessionKey(WEBUI *wu)
+{
+       LIST *Expired = NewList(NULL);
+       UINT i;
+
+       LockList(wu->Contexts);
+
+       for(i=0; i<LIST_NUM(wu->Contexts); i++)
+       {
+               STRMAP_ENTRY *entry = (STRMAP_ENTRY*)LIST_DATA(wu->Contexts, i);
+               WU_CONTEXT *context = (WU_CONTEXT*)entry->Value; /* { dg-bogus "dereference of NULL 'entry'" "PR analyzer/108400" { xfail *-*-* } } */
+               if(context->ExpireDate < Tick64())
+               {
+                       Add(Expired, entry);
+               }
+       }
+
+       for(i=0; i<LIST_NUM(Expired); i++)
+       {
+               STRMAP_ENTRY *entry = LIST_DATA(Expired, i);
+               Delete(wu->Contexts, entry);
+               Free(entry->Name);
+               WuFreeContext(entry->Value);
+               Free(entry);
+       }
+       ReleaseList(Expired);
+
+       UnlockList(wu->Contexts);
+}