From b53d7aa88fd5a5e8a67dd71ea7332fa473595d28 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 13 Jul 2024 00:16:11 -0500 Subject: [PATCH] include: ssp: fortify This includes all of the w*() equivalents to str*()/mem*() implemented in more or less the same way. For these ones, we'll just use header-only implementations from the start to stop further cluttering the libc symbol table. Reviewed by: markj Sponsored by: Klara, Inc. Sponsored by: Stormshield Differential Revision: https://reviews.freebsd.org/D45682 --- include/ssp/Makefile | 2 +- include/ssp/wchar.h | 229 ++ include/wchar.h | 9 +- lib/libc/string/wcpcpy.c | 3 +- lib/libc/string/wcpncpy.c | 4 +- lib/libc/string/wcscat.c | 3 +- lib/libc/string/wcscpy.c | 3 +- lib/libc/string/wcslcat.c | 3 +- lib/libc/string/wcslcpy.c | 3 +- lib/libc/string/wcsncat.c | 4 +- lib/libc/string/wcsncpy.c | 4 +- lib/libc/string/wmemcpy.c | 4 +- lib/libc/string/wmemmove.c | 3 +- lib/libc/string/wmempcpy.c | 4 +- lib/libc/string/wmemset.c | 3 +- lib/libc/tests/secure/Makefile | 1 + lib/libc/tests/secure/fortify_poll_test.c | 1 + lib/libc/tests/secure/fortify_stdio_test.c | 1 + lib/libc/tests/secure/fortify_stdlib_test.c | 1 + lib/libc/tests/secure/fortify_string_test.c | 1 + lib/libc/tests/secure/fortify_strings_test.c | 1 + lib/libc/tests/secure/fortify_unistd_test.c | 1 + lib/libc/tests/secure/fortify_wchar_test.c | 1895 +++++++++++++++++ .../tests/secure/generate-fortify-tests.lua | 150 ++ 24 files changed, 2319 insertions(+), 14 deletions(-) create mode 100644 include/ssp/wchar.h create mode 100644 lib/libc/tests/secure/fortify_wchar_test.c diff --git a/include/ssp/Makefile b/include/ssp/Makefile index 2bbbc2eab705..725d82ff10e5 100644 --- a/include/ssp/Makefile +++ b/include/ssp/Makefile @@ -1,4 +1,4 @@ -INCS= poll.h ssp.h stdio.h stdlib.h string.h strings.h unistd.h +INCS= poll.h ssp.h stdio.h stdlib.h string.h strings.h unistd.h wchar.h INCSDIR= ${INCLUDEDIR}/ssp .include diff --git a/include/ssp/wchar.h b/include/ssp/wchar.h new file mode 100644 index 000000000000..48fc56f9d243 --- /dev/null +++ b/include/ssp/wchar.h @@ -0,0 +1,229 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024, Klara, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SSP_WCHAR_H_ +#define _SSP_WCHAR_H_ + +#include + +#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. + */ +__ssp_inline size_t +__ssp_wbos(void *ptr) +{ + const size_t ptrsize = __ssp_bos(ptr); + + if (ptrsize == (size_t)-1) + return (ptrsize); + + return (ptrsize / sizeof(wchar_t)); +} + +__BEGIN_DECLS +__ssp_redirect_raw_impl(wchar_t *, wmemcpy, wmemcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(src, buf, len)) + __chk_fail(); + + return (__ssp_real(wmemcpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wmempcpy, wmempcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(src, buf, len)) + __chk_fail(); + + return (__ssp_real(wmempcpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wmemmove, wmemmove, + (wchar_t *buf, const wchar_t *src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + + return (__ssp_real(wmemmove)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wmemset, wmemset, + (wchar_t *buf, wchar_t c, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + return (__ssp_real(wmemset)(buf, c, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcpcpy, wcpcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src)) +{ + const size_t slen = __ssp_wbos(buf); + const size_t len = wcslen(src); + + if (len >= slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + (void)__ssp_real(wmemcpy)(buf, src, len + 1); + return (buf + len); +} + +__ssp_redirect_raw_impl(wchar_t *, wcpncpy, wcpncpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcpncpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcscat, wcscat, + (wchar_t *__restrict buf, const wchar_t *__restrict src)) +{ + size_t slen = __ssp_wbos(buf); + wchar_t *cp; + + cp = buf; + while (*cp != L'\0') { + cp++; + if (slen-- == 0) + __chk_fail(); + } + + while (*src != L'\0') { + if (slen-- == 0) + __chk_fail(); + *cp++ = *src++; + } + + if (slen-- == 0) + __chk_fail(); + *cp = '\0'; + return (buf); +} + +__ssp_redirect_raw_impl(wchar_t *, wcscpy, wcscpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src)) +{ + const size_t slen = __ssp_wbos(buf); + size_t len = wcslen(src) + 1; + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wmemcpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcsncat, wcsncat, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len == 0) + return (buf); + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcsncat)(buf, src, len)); +} + +__ssp_redirect_raw_impl(size_t, wcslcat, wcslcat, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcslcat)(buf, src, len)); +} + +__ssp_redirect_raw_impl(wchar_t *, wcsncpy, wcsncpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcsncpy)(buf, src, len)); +} + +__ssp_redirect_raw_impl(size_t, wcslcpy, wcslcpy, + (wchar_t *__restrict buf, const wchar_t *__restrict src, size_t len)) +{ + const size_t slen = __ssp_wbos(buf); + + if (len > slen) + __chk_fail(); + if (__ssp_wchar_overlap(buf, src, len)) + __chk_fail(); + + return (__ssp_real(wcslcpy)(buf, src, len)); +} +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_WCHAR_H_ */ diff --git a/include/wchar.h b/include/wchar.h index 2f23feec8792..e4b037c9b16f 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -108,6 +108,14 @@ typedef struct __sFILE FILE; #endif struct tm; +__BEGIN_DECLS +size_t wcslen(const wchar_t *) __pure; +__END_DECLS + +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS wint_t btowc(int); wint_t fgetwc(FILE *); @@ -146,7 +154,6 @@ wchar_t *wcscpy(wchar_t * __restrict, const wchar_t * __restrict); size_t wcscspn(const wchar_t *, const wchar_t *) __pure; size_t wcsftime(wchar_t * __restrict, size_t, const wchar_t * __restrict, const struct tm * __restrict); -size_t wcslen(const wchar_t *) __pure; wchar_t *wcsncat(wchar_t * __restrict, const wchar_t * __restrict, size_t); int wcsncmp(const wchar_t *, const wchar_t *, size_t) __pure; diff --git a/lib/libc/string/wcpcpy.c b/lib/libc/string/wcpcpy.c index 2d377dab2777..2ae014b31d29 100644 --- a/lib/libc/string/wcpcpy.c +++ b/lib/libc/string/wcpcpy.c @@ -32,9 +32,10 @@ */ #include +#include wchar_t * -wcpcpy(wchar_t * __restrict to, const wchar_t * __restrict from) +__ssp_real(wcpcpy)(wchar_t * __restrict to, const wchar_t * __restrict from) { for (; (*to = *from); ++from, ++to); diff --git a/lib/libc/string/wcpncpy.c b/lib/libc/string/wcpncpy.c index 72c060842e26..e89facfeb642 100644 --- a/lib/libc/string/wcpncpy.c +++ b/lib/libc/string/wcpncpy.c @@ -27,9 +27,11 @@ */ #include +#include wchar_t * -wcpncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n) +__ssp_real(wcpncpy)(wchar_t * __restrict dst, const wchar_t * __restrict src, + size_t n) { for (; n--; dst++, src++) { diff --git a/lib/libc/string/wcscat.c b/lib/libc/string/wcscat.c index 3599e562e9b4..98e088100a87 100644 --- a/lib/libc/string/wcscat.c +++ b/lib/libc/string/wcscat.c @@ -35,9 +35,10 @@ __RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif #include +#include wchar_t * -wcscat(wchar_t * __restrict s1, const wchar_t * __restrict s2) +__ssp_real(wcscat)(wchar_t * __restrict s1, const wchar_t * __restrict s2) { wchar_t *cp; diff --git a/lib/libc/string/wcscpy.c b/lib/libc/string/wcscpy.c index 622e4201f84b..d4aed8721bb8 100644 --- a/lib/libc/string/wcscpy.c +++ b/lib/libc/string/wcscpy.c @@ -35,9 +35,10 @@ __RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif #include +#include wchar_t * -wcscpy(wchar_t * __restrict s1, const wchar_t * __restrict s2) +__ssp_real(wcscpy)(wchar_t * __restrict s1, const wchar_t * __restrict s2) { wchar_t *cp; diff --git a/lib/libc/string/wcslcat.c b/lib/libc/string/wcslcat.c index 336947e3cd23..f74ce520b6a7 100644 --- a/lib/libc/string/wcslcat.c +++ b/lib/libc/string/wcslcat.c @@ -37,6 +37,7 @@ __RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif #include #include +#include /* * Appends src to string dst of size siz (unlike wcsncat, siz is the @@ -46,7 +47,7 @@ __RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); * truncation occurred. */ size_t -wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) +__ssp_real(wcslcat)(wchar_t *dst, const wchar_t *src, size_t siz) { wchar_t *d = dst; const wchar_t *s = src; diff --git a/lib/libc/string/wcslcpy.c b/lib/libc/string/wcslcpy.c index 920425bb5efc..82269656b985 100644 --- a/lib/libc/string/wcslcpy.c +++ b/lib/libc/string/wcslcpy.c @@ -37,6 +37,7 @@ __RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif #include #include +#include /* * Copy src to string dst of size siz. At most siz-1 characters @@ -44,7 +45,7 @@ __RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); * Returns wcslen(src); if retval >= siz, truncation occurred. */ size_t -wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) +__ssp_real(wcslcpy)(wchar_t *dst, const wchar_t *src, size_t siz) { wchar_t *d = dst; const wchar_t *s = src; diff --git a/lib/libc/string/wcsncat.c b/lib/libc/string/wcsncat.c index 004391423f53..5b36fd40bb4f 100644 --- a/lib/libc/string/wcsncat.c +++ b/lib/libc/string/wcsncat.c @@ -35,9 +35,11 @@ __RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif #include +#include wchar_t * -wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n) +__ssp_real(wcsncat)(wchar_t * __restrict s1, const wchar_t * __restrict s2, + size_t n) { wchar_t *p; wchar_t *q; diff --git a/lib/libc/string/wcsncpy.c b/lib/libc/string/wcsncpy.c index a02a8292c0d1..2491dadadfa4 100644 --- a/lib/libc/string/wcsncpy.c +++ b/lib/libc/string/wcsncpy.c @@ -33,13 +33,15 @@ */ #include +#include /* * Copy src to dst, truncating or null-padding to always copy n bytes. * Return dst. */ wchar_t * -wcsncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n) +__ssp_real(wcsncpy)(wchar_t * __restrict dst, const wchar_t * __restrict src, + size_t n) { if (n != 0) { wchar_t *d = dst; diff --git a/lib/libc/string/wmemcpy.c b/lib/libc/string/wmemcpy.c index f692a25fc95b..9db16fe77a69 100644 --- a/lib/libc/string/wmemcpy.c +++ b/lib/libc/string/wmemcpy.c @@ -36,9 +36,11 @@ __RCSID("$NetBSD: wmemcpy.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif #include #include +#include wchar_t * -wmemcpy(wchar_t * __restrict d, const wchar_t * __restrict s, size_t n) +__ssp_real(wmemcpy)(wchar_t * __restrict d, const wchar_t * __restrict s, + size_t n) { return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t)); } diff --git a/lib/libc/string/wmemmove.c b/lib/libc/string/wmemmove.c index cbbdb4afdd6c..837dbe12dc7a 100644 --- a/lib/libc/string/wmemmove.c +++ b/lib/libc/string/wmemmove.c @@ -36,9 +36,10 @@ __RCSID("$NetBSD: wmemmove.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif #include #include +#include wchar_t * -wmemmove(wchar_t *d, const wchar_t *s, size_t n) +__ssp_real(wmemmove)(wchar_t *d, const wchar_t *s, size_t n) { return (wchar_t *)memmove(d, s, n * sizeof(wchar_t)); } diff --git a/lib/libc/string/wmempcpy.c b/lib/libc/string/wmempcpy.c index 6551787abf65..152bb76c7e80 100644 --- a/lib/libc/string/wmempcpy.c +++ b/lib/libc/string/wmempcpy.c @@ -30,9 +30,11 @@ #include #include +#include wchar_t * -wmempcpy(wchar_t *__restrict dst, const wchar_t *__restrict src, size_t len) +__ssp_real(wmempcpy)(wchar_t *__restrict dst, const wchar_t *__restrict src, + size_t len) { return (wmemcpy(dst, src, len) + len); } diff --git a/lib/libc/string/wmemset.c b/lib/libc/string/wmemset.c index 4276373399f9..60fb14b6a4af 100644 --- a/lib/libc/string/wmemset.c +++ b/lib/libc/string/wmemset.c @@ -35,9 +35,10 @@ __RCSID("$NetBSD: wmemset.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif #include +#include wchar_t * -wmemset(wchar_t *s, wchar_t c, size_t n) +__ssp_real(wmemset)(wchar_t *s, wchar_t c, size_t n) { size_t i; wchar_t *p; diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile index 63fe4cb96f02..27d29eabe689 100644 --- a/lib/libc/tests/secure/Makefile +++ b/lib/libc/tests/secure/Makefile @@ -8,6 +8,7 @@ FORTIFY_TCATS+= stdio FORTIFY_TCATS+= string FORTIFY_TCATS+= strings FORTIFY_TCATS+= unistd +FORTIFY_TCATS+= wchar # Manually run after updating the test generator. generate-tests: .PHONY diff --git a/lib/libc/tests/secure/fortify_poll_test.c b/lib/libc/tests/secure/fortify_poll_test.c index 9d9cb4ace35a..447ff400dc05 100644 --- a/lib/libc/tests/secure/fortify_poll_test.c +++ b/lib/libc/tests/secure/fortify_poll_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static FILE * __unused diff --git a/lib/libc/tests/secure/fortify_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c index 035d84b316e6..f399a32f3ca2 100644 --- a/lib/libc/tests/secure/fortify_stdio_test.c +++ b/lib/libc/tests/secure/fortify_stdio_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static FILE * __unused diff --git a/lib/libc/tests/secure/fortify_stdlib_test.c b/lib/libc/tests/secure/fortify_stdlib_test.c index e00983a58aa4..87e6b4b86302 100644 --- a/lib/libc/tests/secure/fortify_stdlib_test.c +++ b/lib/libc/tests/secure/fortify_stdlib_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static FILE * __unused diff --git a/lib/libc/tests/secure/fortify_string_test.c b/lib/libc/tests/secure/fortify_string_test.c index 5651d3107e91..0ba1cf0160b4 100644 --- a/lib/libc/tests/secure/fortify_string_test.c +++ b/lib/libc/tests/secure/fortify_string_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static FILE * __unused diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c index 28f5e9ec4940..a476564f1596 100644 --- a/lib/libc/tests/secure/fortify_strings_test.c +++ b/lib/libc/tests/secure/fortify_strings_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static FILE * __unused diff --git a/lib/libc/tests/secure/fortify_unistd_test.c b/lib/libc/tests/secure/fortify_unistd_test.c index dddc23596368..cfd9267d0d79 100644 --- a/lib/libc/tests/secure/fortify_unistd_test.c +++ b/lib/libc/tests/secure/fortify_unistd_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static FILE * __unused diff --git a/lib/libc/tests/secure/fortify_wchar_test.c b/lib/libc/tests/secure/fortify_wchar_test.c new file mode 100644 index 000000000000..f02e4045c8f2 --- /dev/null +++ b/lib/libc/tests/secure/fortify_wchar_test.c @@ -0,0 +1,1895 @@ +/* @generated by `generate-fortify-tests.lua "wchar"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC_WITHOUT_HEAD(wmemcpy_before_end); +ATF_TC_BODY(wmemcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemcpy_end); +ATF_TC_BODY(wmemcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemcpy_heap_before_end); +ATF_TC_BODY(wmemcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemcpy_heap_end); +ATF_TC_BODY(wmemcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemcpy_heap_after_end); +ATF_TC_BODY(wmemcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmemcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmempcpy_before_end); +ATF_TC_BODY(wmempcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmempcpy_end); +ATF_TC_BODY(wmempcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmempcpy_heap_before_end); +ATF_TC_BODY(wmempcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmempcpy_heap_end); +ATF_TC_BODY(wmempcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmempcpy_heap_after_end); +ATF_TC_BODY(wmempcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmempcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemmove_before_end); +ATF_TC_BODY(wmemmove_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemmove_end); +ATF_TC_BODY(wmemmove_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemmove_heap_before_end); +ATF_TC_BODY(wmemmove_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemmove_heap_end); +ATF_TC_BODY(wmemmove_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemmove_heap_after_end); +ATF_TC_BODY(wmemmove_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmemmove(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemset_before_end); +ATF_TC_BODY(wmemset_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemset_end); +ATF_TC_BODY(wmemset_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemset_heap_before_end); +ATF_TC_BODY(wmemset_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemset_heap_end); +ATF_TC_BODY(wmemset_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wmemset_heap_after_end); +ATF_TC_BODY(wmemset_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmemset(__stack.__buf, L'0', __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpcpy_before_end); +ATF_TC_BODY(wcpcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpcpy_end); +ATF_TC_BODY(wcpcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpcpy_heap_before_end); +ATF_TC_BODY(wcpcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpcpy_heap_end); +ATF_TC_BODY(wcpcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpcpy_heap_after_end); +ATF_TC_BODY(wcpcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpncpy_before_end); +ATF_TC_BODY(wcpncpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpncpy_end); +ATF_TC_BODY(wcpncpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpncpy_heap_before_end); +ATF_TC_BODY(wcpncpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpncpy_heap_end); +ATF_TC_BODY(wcpncpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcpncpy_heap_after_end); +ATF_TC_BODY(wcpncpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscat_before_end); +ATF_TC_BODY(wcscat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscat_end); +ATF_TC_BODY(wcscat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscat_heap_before_end); +ATF_TC_BODY(wcscat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscat_heap_end); +ATF_TC_BODY(wcscat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscat_heap_after_end); +ATF_TC_BODY(wcscat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcat_before_end); +ATF_TC_BODY(wcslcat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcat_end); +ATF_TC_BODY(wcslcat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcat_heap_before_end); +ATF_TC_BODY(wcslcat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcat_heap_end); +ATF_TC_BODY(wcslcat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcat_heap_after_end); +ATF_TC_BODY(wcslcat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncat_before_end); +ATF_TC_BODY(wcsncat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncat_end); +ATF_TC_BODY(wcsncat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncat_heap_before_end); +ATF_TC_BODY(wcsncat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncat_heap_end); +ATF_TC_BODY(wcsncat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncat_heap_after_end); +ATF_TC_BODY(wcsncat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscpy_before_end); +ATF_TC_BODY(wcscpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscpy_end); +ATF_TC_BODY(wcscpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscpy_heap_before_end); +ATF_TC_BODY(wcscpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscpy_heap_end); +ATF_TC_BODY(wcscpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcscpy_heap_after_end); +ATF_TC_BODY(wcscpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcpy_before_end); +ATF_TC_BODY(wcslcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcpy_end); +ATF_TC_BODY(wcslcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcpy_heap_before_end); +ATF_TC_BODY(wcslcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcpy_heap_end); +ATF_TC_BODY(wcslcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcslcpy_heap_after_end); +ATF_TC_BODY(wcslcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncpy_before_end); +ATF_TC_BODY(wcsncpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncpy_end); +ATF_TC_BODY(wcsncpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncpy_heap_before_end); +ATF_TC_BODY(wcsncpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncpy_heap_end); +ATF_TC_BODY(wcsncpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(wcsncpy_heap_after_end); +ATF_TC_BODY(wcsncpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, wmemcpy_before_end); + ATF_TP_ADD_TC(tp, wmemcpy_end); + ATF_TP_ADD_TC(tp, wmemcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wmemcpy_heap_end); + ATF_TP_ADD_TC(tp, wmemcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wmempcpy_before_end); + ATF_TP_ADD_TC(tp, wmempcpy_end); + ATF_TP_ADD_TC(tp, wmempcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wmempcpy_heap_end); + ATF_TP_ADD_TC(tp, wmempcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wmemmove_before_end); + ATF_TP_ADD_TC(tp, wmemmove_end); + ATF_TP_ADD_TC(tp, wmemmove_heap_before_end); + ATF_TP_ADD_TC(tp, wmemmove_heap_end); + ATF_TP_ADD_TC(tp, wmemmove_heap_after_end); + ATF_TP_ADD_TC(tp, wmemset_before_end); + ATF_TP_ADD_TC(tp, wmemset_end); + ATF_TP_ADD_TC(tp, wmemset_heap_before_end); + ATF_TP_ADD_TC(tp, wmemset_heap_end); + ATF_TP_ADD_TC(tp, wmemset_heap_after_end); + ATF_TP_ADD_TC(tp, wcpcpy_before_end); + ATF_TP_ADD_TC(tp, wcpcpy_end); + ATF_TP_ADD_TC(tp, wcpcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcpcpy_heap_end); + ATF_TP_ADD_TC(tp, wcpcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcpncpy_before_end); + ATF_TP_ADD_TC(tp, wcpncpy_end); + ATF_TP_ADD_TC(tp, wcpncpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcpncpy_heap_end); + ATF_TP_ADD_TC(tp, wcpncpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcscat_before_end); + ATF_TP_ADD_TC(tp, wcscat_end); + ATF_TP_ADD_TC(tp, wcscat_heap_before_end); + ATF_TP_ADD_TC(tp, wcscat_heap_end); + ATF_TP_ADD_TC(tp, wcscat_heap_after_end); + ATF_TP_ADD_TC(tp, wcslcat_before_end); + ATF_TP_ADD_TC(tp, wcslcat_end); + ATF_TP_ADD_TC(tp, wcslcat_heap_before_end); + ATF_TP_ADD_TC(tp, wcslcat_heap_end); + ATF_TP_ADD_TC(tp, wcslcat_heap_after_end); + ATF_TP_ADD_TC(tp, wcsncat_before_end); + ATF_TP_ADD_TC(tp, wcsncat_end); + ATF_TP_ADD_TC(tp, wcsncat_heap_before_end); + ATF_TP_ADD_TC(tp, wcsncat_heap_end); + ATF_TP_ADD_TC(tp, wcsncat_heap_after_end); + ATF_TP_ADD_TC(tp, wcscpy_before_end); + ATF_TP_ADD_TC(tp, wcscpy_end); + ATF_TP_ADD_TC(tp, wcscpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcscpy_heap_end); + ATF_TP_ADD_TC(tp, wcscpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcslcpy_before_end); + ATF_TP_ADD_TC(tp, wcslcpy_end); + ATF_TP_ADD_TC(tp, wcslcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcslcpy_heap_end); + ATF_TP_ADD_TC(tp, wcslcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcsncpy_before_end); + ATF_TP_ADD_TC(tp, wcsncpy_end); + ATF_TP_ADD_TC(tp, wcsncpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcsncpy_heap_end); + ATF_TP_ADD_TC(tp, wcsncpy_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua index b559fbded070..1807cbf477e9 100755 --- a/lib/libc/tests/secure/generate-fortify-tests.lua +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -77,6 +77,7 @@ local includes = { "strings.h", "sysexits.h", "unistd.h", + "wchar.h", "atf-c.h", } @@ -114,6 +115,13 @@ local string_init = [[ src[__len - 1] = '\0'; ]] +local wstring_stackvars = "\twchar_t src[__len];\n" +local wstring_init = [[ + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; +]] + -- Each test entry describes how to test a given function. We need to know how -- to construct the buffer, we need to know the argument set we're dealing with, -- and we need to know what we're passing to each argument. We could be passing @@ -606,6 +614,148 @@ local all_tests = { ]] }, }, + wchar = { + -- + { + func = "wmemcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\twchar_t src[__len + 10];\n", + }, + { + func = "wmempcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\twchar_t src[__len + 10];\n", + }, + { + func = "wmemmove", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\twchar_t src[__len + 10];\n", + }, + { + func = "wmemset", + buftype = "wchar_t[]", + arguments = { + "__buf", + "L'0'", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "wcpcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + uses_len = true, + }, + { + func = "wcpncpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcscat", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + uses_len = true, + }, + { + func = "wcslcat", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcsncat", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcscpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + uses_len = true, + }, + { + func = "wcslcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcsncpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + }, } local function write_test_boilerplate(fh, name, body)