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.
This commit is contained in:
Willy Tarreau 2023-05-11 11:33:35 +02:00
parent 0dd4fa58e6
commit 29dcc5e559
2 changed files with 6 additions and 1 deletions

View File

@ -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

View File

@ -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.