diff --git a/include/ssp/ssp.h b/include/ssp/ssp.h --- a/include/ssp/ssp.h +++ b/include/ssp/ssp.h @@ -87,12 +87,19 @@ #define __ssp_redirect0(rtype, fun, args, call) \ __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos0, __len) -/* - * Take caution when using __ssp_overlap! Don't use it in contexts where we - * can end up with double-evaluation of a statement with some side-effects. - */ -#define __ssp_overlap(a, b, l) \ - (((a) <= (b) && (b) < (a) + (l)) || ((b) <= (a) && (a) < (b) + (l))) +#include + +static inline int +__ssp_overlap(const void *leftp, const void *rightp, size_t sz) +{ + __uintptr_t left = (__uintptr_t)leftp; + __uintptr_t right = (__uintptr_t)rightp; + + if (left <= right) + return (SIZE_MAX - sz < left || right < left + sz); + + return (SIZE_MAX - sz < right || left < right + sz); +} #include diff --git a/include/ssp/string.h b/include/ssp/string.h --- a/include/ssp/string.h +++ b/include/ssp/string.h @@ -125,7 +125,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap((const char *)src, (const char *)buf, len)) + if (__ssp_overlap(src, buf, len)) __chk_fail(); return (__ssp_real(mempcpy)(buf, src, len)); diff --git a/include/ssp/wchar.h b/include/ssp/wchar.h --- a/include/ssp/wchar.h +++ b/include/ssp/wchar.h @@ -31,6 +31,15 @@ #if __SSP_FORTIFY_LEVEL > 0 +static inline int +__ssp_wchar_overlap(const void *leftp, const void *rightp, size_t len) +{ + + if (len > SIZE_MAX / sizeof(wchar_t)) + return (1); + return (__ssp_overlap(leftp, rightp, len * sizeof(wchar_t))); +} + /* * __ssp_wbos for w*() calls where the size parameters are in sizeof(wchar_t) * units, so the result needs to be scaled appropriately. @@ -54,7 +63,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(src, buf, len)) + if (__ssp_wchar_overlap(src, buf, len)) __chk_fail(); return (__ssp_real(wmemcpy)(buf, src, len)); @@ -67,7 +76,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(src, buf, len)) + if (__ssp_wchar_overlap(src, buf, len)) __chk_fail(); return (__ssp_real(wmempcpy)(buf, src, len)); @@ -102,7 +111,7 @@ if (len >= slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); (void)__ssp_real(wmemcpy)(buf, src, len + 1); @@ -116,7 +125,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); return (__ssp_real(wcpncpy)(buf, src, len)); @@ -155,7 +164,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); return (__ssp_real(wmemcpy)(buf, src, len)); @@ -170,7 +179,7 @@ return (buf); if (len > slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); return (__ssp_real(wcsncat)(buf, src, len)); @@ -183,7 +192,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); return (__ssp_real(wcslcat)(buf, src, len)); @@ -196,7 +205,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); return (__ssp_real(wcsncpy)(buf, src, len)); @@ -209,7 +218,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap(buf, src, len)) + if (__ssp_wchar_overlap(buf, src, len)) __chk_fail(); return (__ssp_real(wcslcpy)(buf, src, len)); diff --git a/lib/libc/secure/memcpy_chk.c b/lib/libc/secure/memcpy_chk.c --- a/lib/libc/secure/memcpy_chk.c +++ b/lib/libc/secure/memcpy_chk.c @@ -44,7 +44,7 @@ if (len > slen) __chk_fail(); - if (__ssp_overlap((const char *)src, (const char *)dst, len)) + if (__ssp_overlap(src, dst, len)) __chk_fail(); return (memcpy(dst, src, len));