``` #include <assert.h> #include <stdint.h> #include <string.h> #include <sys/mman.h> #include <wchar.h> #define PAGE_SIZE 4096 static void * make_buf(uint64_t sz) { void * p = mmap(NULL, 2 * PAGE_SIZE + sz, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); assert(p != NULL); assert(!mprotect(p + PAGE_SIZE, sz, PROT_READ | PROT_WRITE)); return p + PAGE_SIZE; } size_t __wcsnlen_avx2(wchar_t const *, size_t); size_t __wcsnlen_evex(wchar_t const *, size_t); int main(int argc, char ** argv) { wchar_t * buf = (wchar_t *)make_buf(PAGE_SIZE); wchar_t * wstr = buf + (PAGE_SIZE / sizeof(wchar_t)) - 2; /* Expect wstr len == 1. */ memset(wstr, -1, sizeof(wchar_t)); memset(wstr + 1, 0, sizeof(wchar_t)); assert(__wcsnlen_evex(wstr, (1UL << 63)) == 1); assert(__wcsnlen_avx2(wstr, (1UL << 63)) == 1); } ``` Build statically so `__wcsnlen_avx2` / `__wcsnlen_evex` are defined. Output: ``` wcsnlen: wcsnlen.c:31: main: Assertion `__wcsnlen_avx2(wstr, (1UL << 63)) == 1' failed. Aborted (core dumped) ```
Created attachment 14340 [details] Fix and test cases. Fix, will post once all tests complete.
Fixed in master, 2.37, 2.36, 2.35, 2.34, and 2.33. commit b0969fa53a28b4ab2159806bf6c99a98999502ee Author: Noah Goldstein <goldstein.w.n@gmail.com> Date: Tue Sep 20 17:58:04 2022 -0700 x86: Fix wcsnlen-avx2 page cross length comparison [BZ #29591] Previous implementation was adjusting length (rsi) to match bytes (eax), but since there is no bound to length this can cause overflow. Fix is to just convert the byte-count (eax) to length by dividing by sizeof (wchar_t) before the comparison. Full check passes on x86-64 and build succeeds w/ and w/o multiarch.
Additionally fixed in in 2.32, 2.31, 2.30, 2.29, and 2.28 to resolve ifunc backports.