diff options
| author | Jakob Kaivo <jkk@ung.org> | 2024-01-31 22:23:31 -0500 |
|---|---|---|
| committer | Jakob Kaivo <jkk@ung.org> | 2024-01-31 22:23:31 -0500 |
| commit | 473a9dae23d46a4ec1827e4d68363eea805c08dc (patch) | |
| tree | 7e7bd01cc492be6b01f3a26c747a1a79b9ef95a0 /src/stdlib/_stdlib.h | |
| parent | 656d95bc6b5a2c55c79b07a70661137ea55cb0b4 (diff) | |
check for UB in qsort() and bsearch()
Diffstat (limited to 'src/stdlib/_stdlib.h')
| -rw-r--r-- | src/stdlib/_stdlib.h | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/stdlib/_stdlib.h b/src/stdlib/_stdlib.h index 769f220b..14953e6f 100644 --- a/src/stdlib/_stdlib.h +++ b/src/stdlib/_stdlib.h @@ -5,6 +5,32 @@ #include <limits.h> #include "_safety.h" +#ifdef NEED_COMPAR +#ifdef NDEBUG +#define SAFE_COMPAR(__comp, __p1, __p2, __sz, __fn) __comp(__p1, __p2) +#else +static unsigned __hash(const void *p, size_t size) { + unsigned int h = 0; + const unsigned char *s = p; + for (size_t i = 0; i < size; i++) { + h <<= CHAR_BIT; + h |= s[i]; + } + return h; +} +static int __safe_compar(int (*compar)(const void *, const void *), const void *p1, const void *p2, size_t size, const char *fn) { + unsigned int h1 = __hash(p1, size); + unsigned int h2 = __hash(p2, size); + int ret = compar(p1, p2); + if (h1 != __hash(p1, size) || h2 != __hash(p2, size)) { + __undefined("In call to %s(): Comparison function modifies parameters", fn); + } + return ret; +} +#define SAFE_COMPAR(__comp, __p1, __p2, __sz, __fn) __safe_compar(__comp, __p1, __p2, __sz, __fn) +#endif +#endif + #define _rand(_n) \ (((_n) = (_n) * 1103515245 + 12345) ? (_n) / UINT_MAX % RAND_MAX : 0) |
