diff options
author | Willy Tarreau <w@1wt.eu> | 2023-05-11 11:33:35 +0200 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2023-05-11 11:33:35 +0200 |
commit | 29dcc5e5599e2cec236dfd3b10899dc8264e2bde (patch) | |
tree | a6d726c0ed0f84729ead63eb159c33b5f0daa62f | |
parent | 0dd4fa58e6ead1a6723a6a126f9e8b0e6979d9c3 (diff) | |
download | haproxy-29dcc5e5599e2cec236dfd3b10899dc8264e2bde.tar.gz |
DEBUG: list: add DEBUG_LIST to purposely corrupt list heads after delete
LIST_DELETE doesn't affect the previous pointers of the stored element.
This can sometimes hide bugs when such a pointer is reused by accident
in a LIST_NEXT() or equivalent after having been detached for example, or
ia another LIST_DELETE is performed again, something that LIST_DEL_INIT()
is immune to. By compiling with -DDEBUG_LIST, we'll replace a freshly
detached list element with two invalid pointers that will cause a crash
in case of accidental misuse. It's not enabled by default.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | include/haproxy/list.h | 5 |
2 files changed, 6 insertions, 1 deletions
@@ -223,7 +223,7 @@ SMALL_OPTS = # DEBUG_MEM_STATS, DEBUG_DONT_SHARE_POOLS, DEBUG_FD, DEBUG_POOL_INTEGRITY, # DEBUG_NO_POOLS, DEBUG_FAIL_ALLOC, DEBUG_STRICT_ACTION=[0-3], DEBUG_HPACK, # DEBUG_AUTH, DEBUG_SPOE, DEBUG_UAF, DEBUG_THREAD, DEBUG_STRICT, DEBUG_DEV, -# DEBUG_TASK, DEBUG_MEMORY_POOLS, DEBUG_POOL_TRACING, DEBUG_QPACK. +# DEBUG_TASK, DEBUG_MEMORY_POOLS, DEBUG_POOL_TRACING, DEBUG_QPACK, DEBUG_LIST. DEBUG = -DDEBUG_STRICT -DDEBUG_MEMORY_POOLS #### Trace options diff --git a/include/haproxy/list.h b/include/haproxy/list.h index dc4f7e0e1..368e6d76b 100644 --- a/include/haproxy/list.h +++ b/include/haproxy/list.h @@ -72,7 +72,12 @@ } while (0) /* removes an element from a list and returns it */ +#if defined(DEBUG_LIST) +/* purposely corrupt the detached element to detect use-after-delete */ +#define LIST_DELETE(el) ({ typeof(el) __ret = (el); (el)->n->p = (el)->p; (el)->p->n = (el)->n; *(__ret) = (struct list)ILH; (__ret);}) +#else #define LIST_DELETE(el) ({ typeof(el) __ret = (el); (el)->n->p = (el)->p; (el)->p->n = (el)->n; (__ret); }) +#endif /* removes an element from a list, initializes it and returns it. * This is faster than LIST_DELETE+LIST_INIT as we avoid reloading the pointers. |