glibc/debug/tst-fortify.c
Siddhesh Poyarekar 9bcd12d223 wcrtomb: Make behavior POSIX compliant
The GNU implementation of wcrtomb assumes that there are at least
MB_CUR_MAX bytes available in the destination buffer passed to wcrtomb
as the first argument.  This is not compatible with the POSIX
definition, which only requires enough space for the input wide
character.

This does not break much in practice because when users supply buffers
smaller than MB_CUR_MAX (e.g. in ncurses), they compute and dynamically
allocate the buffer, which results in enough spare space (thanks to
usable_size in malloc and padding in alloca) that no actual buffer
overflow occurs.  However when the code is built with _FORTIFY_SOURCE,
it runs into the hard check against MB_CUR_MAX in __wcrtomb_chk and
hence fails.  It wasn't evident until now since dynamic allocations
would result in wcrtomb not being fortified but since _FORTIFY_SOURCE=3,
that limitation is gone, resulting in such code failing.

To fix this problem, introduce an internal buffer that is MB_LEN_MAX
long and use that to perform the conversion and then copy the resultant
bytes into the destination buffer.  Also move the fortification check
into the main implementation, which checks the result after conversion
and aborts if the resultant byte count is greater than the destination
buffer size.

One complication is that applications that assume the MB_CUR_MAX
limitation to be gone may not be able to run safely on older glibcs if
they use static destination buffers smaller than MB_CUR_MAX; dynamic
allocations will always have enough spare space that no actual overruns
will occur.  One alternative to fixing this is to bump symbol version to
prevent them from running on older glibcs but that seems too strict a
constraint.  Instead, since these users will only have made this
decision on reading the manual, I have put a note in the manual warning
them about the pitfalls of having static buffers smaller than
MB_CUR_MAX and running them on older glibc.

Benchmarking:

The wcrtomb microbenchmark shows significant increases in maximum
execution time for all locales, ranging from 10x for ar_SA.UTF-8 to
1.5x-2x for nearly everything else.  The mean execution time however saw
practically no impact, with some results even being quicker, indicating
that cache locality has a much bigger role in the overhead.

Given that the additional copy uses a temporary buffer inside wcrtomb,
it's likely that a hot path will end up putting that buffer (which is
responsible for the additional overhead) in a similar place on stack,
giving the necessary cache locality to negate the overhead.  However in
situations where wcrtomb ends up getting called at wildly different
spots on the call stack (or is on different call stacks, e.g. with
threads or different execution contexts) and is still a hotspot, the
performance lag will be visible.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2022-05-13 19:15:46 +05:30

1770 lines
40 KiB
C

/* Copyright (C) 2004-2022 Free Software Foundation, Inc.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* This file tests gets. Force it to be declared. */
#include <features.h>
#undef __GLIBC_USE_DEPRECATED_GETS
#define __GLIBC_USE_DEPRECATED_GETS 1
#include <assert.h>
#include <fcntl.h>
#include <locale.h>
#include <obstack.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#ifndef _GNU_SOURCE
# define MEMPCPY memcpy
# define WMEMPCPY wmemcpy
# define MEMPCPY_RET(x) 0
# define WMEMPCPY_RET(x) 0
#else
# define MEMPCPY mempcpy
# define WMEMPCPY wmempcpy
# define MEMPCPY_RET(x) __builtin_strlen (x)
# define WMEMPCPY_RET(x) wcslen (x)
#endif
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
char *temp_filename;
static void do_prepare (void);
static int do_test (void);
#define PREPARE(argc, argv) do_prepare ()
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static void
do_prepare (void)
{
int temp_fd = create_temp_file ("tst-chk1.", &temp_filename);
if (temp_fd == -1)
{
printf ("cannot create temporary file: %m\n");
exit (1);
}
const char *strs = "abcdefgh\nABCDEFGHI\nabcdefghij\nABCDEFGHIJ";
if ((size_t) write (temp_fd, strs, strlen (strs)) != strlen (strs))
{
puts ("could not write test strings into file");
unlink (temp_filename);
exit (1);
}
}
volatile int chk_fail_ok;
volatile int ret;
jmp_buf chk_fail_buf;
static void
handler (int sig)
{
if (chk_fail_ok)
{
chk_fail_ok = 0;
longjmp (chk_fail_buf, 1);
}
else
_exit (127);
}
#if __USE_FORTIFY_LEVEL == 3
volatile size_t buf_size = 10;
#else
char buf[10];
wchar_t wbuf[10];
#define buf_size sizeof (buf)
#endif
volatile size_t l0;
volatile char *p;
volatile wchar_t *wp;
const char *str1 = "JIHGFEDCBA";
const char *str2 = "F";
const char *str3 = "%s%n%s%n";
const char *str4 = "Hello, ";
const char *str5 = "World!\n";
const wchar_t *wstr1 = L"JIHGFEDCBA";
const wchar_t *wstr2 = L"F";
const wchar_t *wstr3 = L"%s%n%s%n";
const wchar_t *wstr4 = L"Hello, ";
const wchar_t *wstr5 = L"World!\n";
char buf2[10] = "%s";
int num1 = 67;
int num2 = 987654;
#define FAIL() \
do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0)
#define CHK_FAIL_START \
chk_fail_ok = 1; \
if (! setjmp (chk_fail_buf)) \
{
#define CHK_FAIL_END \
chk_fail_ok = 0; \
FAIL (); \
}
#if __USE_FORTIFY_LEVEL >= 2 && (!defined __cplusplus || defined __va_arg_pack)
# define CHK_FAIL2_START CHK_FAIL_START
# define CHK_FAIL2_END CHK_FAIL_END
#else
# define CHK_FAIL2_START
# define CHK_FAIL2_END
#endif
static int
do_test (void)
{
#if __USE_FORTIFY_LEVEL == 3
char *buf = (char *) malloc (buf_size);
wchar_t *wbuf = (wchar_t *) malloc (buf_size * sizeof (wchar_t));
#endif
set_fortify_handler (handler);
struct A { char buf1[9]; char buf2[1]; } a;
struct wA { wchar_t buf1[9]; wchar_t buf2[1]; } wa;
printf ("Test checking routines at fortify level %d\n",
#ifdef __USE_FORTIFY_LEVEL
(int) __USE_FORTIFY_LEVEL
#else
0
#endif
);
#if defined __USE_FORTIFY_LEVEL && !defined __fortify_function
printf ("Test skipped");
if (l0 == 0)
return 0;
#endif
/* These ops can be done without runtime checking of object size. */
memcpy (buf, "abcdefghij", 10);
memmove (buf + 1, buf, 9);
if (memcmp (buf, "aabcdefghi", 10))
FAIL ();
memcpy (buf, "abcdefghij", 10);
bcopy (buf, buf + 1, 9);
if (memcmp (buf, "aabcdefghi", 10))
FAIL ();
if (MEMPCPY (buf + 5, "abcde", 5) != buf + 5 + MEMPCPY_RET ("abcde")
|| memcmp (buf, "aabcdabcde", 10))
FAIL ();
memset (buf + 8, 'j', 2);
if (memcmp (buf, "aabcdabcjj", 10))
FAIL ();
bzero (buf + 8, 2);
if (memcmp (buf, "aabcdabc\0\0", 10))
FAIL ();
explicit_bzero (buf + 6, 4);
if (memcmp (buf, "aabcda\0\0\0\0", 10))
FAIL ();
strcpy (buf + 4, "EDCBA");
if (memcmp (buf, "aabcEDCBA", 10))
FAIL ();
if (stpcpy (buf + 8, "F") != buf + 9 || memcmp (buf, "aabcEDCBF", 10))
FAIL ();
strncpy (buf + 6, "X", 4);
if (memcmp (buf, "aabcEDX\0\0", 10))
FAIL ();
if (sprintf (buf + 7, "%s", "67") != 2 || memcmp (buf, "aabcEDX67", 10))
FAIL ();
if (snprintf (buf + 7, 3, "%s", "987654") != 6
|| memcmp (buf, "aabcEDX98", 10))
FAIL ();
/* These ops need runtime checking, but shouldn't __chk_fail. */
memcpy (buf, "abcdefghij", l0 + 10);
memmove (buf + 1, buf, l0 + 9);
if (memcmp (buf, "aabcdefghi", 10))
FAIL ();
memcpy (buf, "abcdefghij", l0 + 10);
bcopy (buf, buf + 1, l0 + 9);
if (memcmp (buf, "aabcdefghi", 10))
FAIL ();
if (MEMPCPY (buf + 5, "abcde", l0 + 5) != buf + 5 + MEMPCPY_RET ("abcde")
|| memcmp (buf, "aabcdabcde", 10))
FAIL ();
memset (buf + 8, 'j', l0 + 2);
if (memcmp (buf, "aabcdabcjj", 10))
FAIL ();
bzero (buf + 8, l0 + 2);
if (memcmp (buf, "aabcdabc\0\0", 10))
FAIL ();
explicit_bzero (buf + 6, l0 + 4);
if (memcmp (buf, "aabcda\0\0\0\0", 10))
FAIL ();
strcpy (buf + 4, str1 + 5);
if (memcmp (buf, "aabcEDCBA", 10))
FAIL ();
if (stpcpy (buf + 8, str2) != buf + 9 || memcmp (buf, "aabcEDCBF", 10))
FAIL ();
strncpy (buf + 6, "X", l0 + 4);
if (memcmp (buf, "aabcEDX\0\0", 10))
FAIL ();
if (stpncpy (buf + 5, "cd", l0 + 5) != buf + 7
|| memcmp (buf, "aabcEcd\0\0", 10))
FAIL ();
if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEcd67", 10))
FAIL ();
if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEcd98", 10))
FAIL ();
buf[l0 + 8] = '\0';
strcat (buf, "A");
if (memcmp (buf, "aabcEcd9A", 10))
FAIL ();
buf[l0 + 7] = '\0';
strncat (buf, "ZYXWV", l0 + 2);
if (memcmp (buf, "aabcEcdZY", 10))
FAIL ();
/* The following tests are supposed to succeed at all fortify
levels, even though they overflow a.buf1 into a.buf2. */
memcpy (a.buf1, "abcdefghij", l0 + 10);
memmove (a.buf1 + 1, a.buf1, l0 + 9);
if (memcmp (a.buf1, "aabcdefghi", 10))
FAIL ();
memcpy (a.buf1, "abcdefghij", l0 + 10);
bcopy (a.buf1, a.buf1 + 1, l0 + 9);
if (memcmp (a.buf1, "aabcdefghi", 10))
FAIL ();
if (MEMPCPY (a.buf1 + 5, "abcde", l0 + 5)
!= a.buf1 + 5 + MEMPCPY_RET ("abcde")
|| memcmp (a.buf1, "aabcdabcde", 10))
FAIL ();
memset (a.buf1 + 8, 'j', l0 + 2);
if (memcmp (a.buf1, "aabcdabcjj", 10))
FAIL ();
bzero (a.buf1 + 8, l0 + 2);
if (memcmp (a.buf1, "aabcdabc\0\0", 10))
FAIL ();
explicit_bzero (a.buf1 + 6, l0 + 4);
if (memcmp (a.buf1, "aabcda\0\0\0\0", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL < 2
/* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
and sufficient GCC support, as the string operations overflow
from a.buf1 into a.buf2. */
strcpy (a.buf1 + 4, str1 + 5);
if (memcmp (a.buf1, "aabcEDCBA", 10))
FAIL ();
if (stpcpy (a.buf1 + 8, str2) != a.buf1 + 9
|| memcmp (a.buf1, "aabcEDCBF", 10))
FAIL ();
strncpy (a.buf1 + 6, "X", l0 + 4);
if (memcmp (a.buf1, "aabcEDX\0\0", 10))
FAIL ();
if (sprintf (a.buf1 + 7, "%d", num1) != 2
|| memcmp (a.buf1, "aabcEDX67", 10))
FAIL ();
if (snprintf (a.buf1 + 7, 3, "%d", num2) != 6
|| memcmp (a.buf1, "aabcEDX98", 10))
FAIL ();
a.buf1[l0 + 8] = '\0';
strcat (a.buf1, "A");
if (memcmp (a.buf1, "aabcEDX9A", 10))
FAIL ();
a.buf1[l0 + 7] = '\0';
strncat (a.buf1, "ZYXWV", l0 + 2);
if (memcmp (a.buf1, "aabcEDXZY", 10))
FAIL ();
#endif
#if __USE_FORTIFY_LEVEL >= 1
/* Now check if all buffer overflows are caught at runtime.
N.B. All tests involving a length parameter need to be done
twice: once with the length a compile-time constant, once without. */
CHK_FAIL_START
memcpy (buf + 1, "abcdefghij", 10);
CHK_FAIL_END
CHK_FAIL_START
memcpy (buf + 1, "abcdefghij", l0 + 10);
CHK_FAIL_END
CHK_FAIL_START
memmove (buf + 2, buf + 1, 9);
CHK_FAIL_END
CHK_FAIL_START
memmove (buf + 2, buf + 1, l0 + 9);
CHK_FAIL_END
CHK_FAIL_START
bcopy (buf + 1, buf + 2, 9);
CHK_FAIL_END
CHK_FAIL_START
bcopy (buf + 1, buf + 2, l0 + 9);
CHK_FAIL_END
#ifdef _GNU_SOURCE
CHK_FAIL_START
p = (char *) mempcpy (buf + 6, "abcde", 5);
CHK_FAIL_END
CHK_FAIL_START
p = (char *) mempcpy (buf + 6, "abcde", l0 + 5);
CHK_FAIL_END
#endif
CHK_FAIL_START
memset (buf + 9, 'j', 2);
CHK_FAIL_END
CHK_FAIL_START
memset (buf + 9, 'j', l0 + 2);
CHK_FAIL_END
CHK_FAIL_START
bzero (buf + 9, 2);
CHK_FAIL_END
CHK_FAIL_START
bzero (buf + 9, l0 + 2);
CHK_FAIL_END
CHK_FAIL_START
explicit_bzero (buf + 9, 2);
CHK_FAIL_END
CHK_FAIL_START
explicit_bzero (buf + 9, l0 + 2);
CHK_FAIL_END
CHK_FAIL_START
strcpy (buf + 5, str1 + 5);
CHK_FAIL_END
CHK_FAIL_START
p = stpcpy (buf + 9, str2);
CHK_FAIL_END
CHK_FAIL_START
strncpy (buf + 7, "X", 4);
CHK_FAIL_END
CHK_FAIL_START
strncpy (buf + 7, "X", l0 + 4);
CHK_FAIL_END
CHK_FAIL_START
stpncpy (buf + 6, "cd", 5);
CHK_FAIL_END
CHK_FAIL_START
stpncpy (buf + 6, "cd", l0 + 5);
CHK_FAIL_END
# if !defined __cplusplus || defined __va_arg_pack
CHK_FAIL_START
sprintf (buf + 8, "%d", num1);
CHK_FAIL_END
CHK_FAIL_START
snprintf (buf + 8, 3, "%d", num2);
CHK_FAIL_END
CHK_FAIL_START
snprintf (buf + 8, l0 + 3, "%d", num2);
CHK_FAIL_END
CHK_FAIL_START
swprintf (wbuf + 8, 3, L"%d", num1);
CHK_FAIL_END
CHK_FAIL_START
swprintf (wbuf + 8, l0 + 3, L"%d", num1);
CHK_FAIL_END
# endif
memcpy (buf, str1 + 2, 9);
CHK_FAIL_START
strcat (buf, "AB");
CHK_FAIL_END
memcpy (buf, str1 + 3, 8);
CHK_FAIL_START
strncat (buf, "ZYXWV", 3);
CHK_FAIL_END
memcpy (buf, str1 + 3, 8);
CHK_FAIL_START
strncat (buf, "ZYXWV", l0 + 3);
CHK_FAIL_END
CHK_FAIL_START
memcpy (a.buf1 + 1, "abcdefghij", 10);
CHK_FAIL_END
CHK_FAIL_START
memcpy (a.buf1 + 1, "abcdefghij", l0 + 10);
CHK_FAIL_END
CHK_FAIL_START
memmove (a.buf1 + 2, a.buf1 + 1, 9);
CHK_FAIL_END
CHK_FAIL_START
memmove (a.buf1 + 2, a.buf1 + 1, l0 + 9);
CHK_FAIL_END
CHK_FAIL_START
bcopy (a.buf1 + 1, a.buf1 + 2, 9);
CHK_FAIL_END
CHK_FAIL_START
bcopy (a.buf1 + 1, a.buf1 + 2, l0 + 9);
CHK_FAIL_END
#ifdef _GNU_SOURCE
CHK_FAIL_START
p = (char *) mempcpy (a.buf1 + 6, "abcde", 5);
CHK_FAIL_END
CHK_FAIL_START
p = (char *) mempcpy (a.buf1 + 6, "abcde", l0 + 5);
CHK_FAIL_END
#endif
CHK_FAIL_START
memset (a.buf1 + 9, 'j', 2);
CHK_FAIL_END
CHK_FAIL_START
memset (a.buf1 + 9, 'j', l0 + 2);
CHK_FAIL_END
CHK_FAIL_START
bzero (a.buf1 + 9, 2);
CHK_FAIL_END
CHK_FAIL_START
bzero (a.buf1 + 9, l0 + 2);
CHK_FAIL_END
CHK_FAIL_START
explicit_bzero (a.buf1 + 9, 2);
CHK_FAIL_END
CHK_FAIL_START
explicit_bzero (a.buf1 + 9, l0 + 2);
CHK_FAIL_END
# if __USE_FORTIFY_LEVEL >= 2
# define O 0
# else
# define O 1
# endif
CHK_FAIL_START
strcpy (a.buf1 + (O + 4), str1 + 5);
CHK_FAIL_END
CHK_FAIL_START
p = stpcpy (a.buf1 + (O + 8), str2);
CHK_FAIL_END
CHK_FAIL_START
strncpy (a.buf1 + (O + 6), "X", 4);
CHK_FAIL_END
CHK_FAIL_START
strncpy (a.buf1 + (O + 6), "X", l0 + 4);
CHK_FAIL_END
# if !defined __cplusplus || defined __va_arg_pack
CHK_FAIL_START
sprintf (a.buf1 + (O + 7), "%d", num1);
CHK_FAIL_END
CHK_FAIL_START
snprintf (a.buf1 + (O + 7), 3, "%d", num2);
CHK_FAIL_END
CHK_FAIL_START
snprintf (a.buf1 + (O + 7), l0 + 3, "%d", num2);
CHK_FAIL_END
# endif
memcpy (a.buf1, str1 + (3 - O), 8 + O);
CHK_FAIL_START
strcat (a.buf1, "AB");
CHK_FAIL_END
memcpy (a.buf1, str1 + (4 - O), 7 + O);
CHK_FAIL_START
strncat (a.buf1, "ZYXWV", l0 + 3);
CHK_FAIL_END
#endif
/* These ops can be done without runtime checking of object size. */
wmemcpy (wbuf, L"abcdefghij", 10);
wmemmove (wbuf + 1, wbuf, 9);
if (wmemcmp (wbuf, L"aabcdefghi", 10))
FAIL ();
if (WMEMPCPY (wbuf + 5, L"abcde", 5) != wbuf + 5 + WMEMPCPY_RET (L"abcde")
|| wmemcmp (wbuf, L"aabcdabcde", 10))
FAIL ();
wmemset (wbuf + 8, L'j', 2);
if (wmemcmp (wbuf, L"aabcdabcjj", 10))
FAIL ();
wcscpy (wbuf + 4, L"EDCBA");
if (wmemcmp (wbuf, L"aabcEDCBA", 10))
FAIL ();
if (wcpcpy (wbuf + 8, L"F") != wbuf + 9 || wmemcmp (wbuf, L"aabcEDCBF", 10))
FAIL ();
wcsncpy (wbuf + 6, L"X", 4);
if (wmemcmp (wbuf, L"aabcEDX\0\0", 10))
FAIL ();
if (swprintf (wbuf + 7, 3, L"%ls", L"987654") >= 0
|| wmemcmp (wbuf, L"aabcEDX98", 10))
FAIL ();
if (swprintf (wbuf + 7, 3, L"64") != 2
|| wmemcmp (wbuf, L"aabcEDX64", 10))
FAIL ();
/* These ops need runtime checking, but shouldn't __chk_fail. */
wmemcpy (wbuf, L"abcdefghij", l0 + 10);
wmemmove (wbuf + 1, wbuf, l0 + 9);
if (wmemcmp (wbuf, L"aabcdefghi", 10))
FAIL ();
if (WMEMPCPY (wbuf + 5, L"abcde", l0 + 5)
!= wbuf + 5 + WMEMPCPY_RET (L"abcde")
|| wmemcmp (wbuf, L"aabcdabcde", 10))
FAIL ();
wmemset (wbuf + 8, L'j', l0 + 2);
if (wmemcmp (wbuf, L"aabcdabcjj", 10))
FAIL ();
wcscpy (wbuf + 4, wstr1 + 5);
if (wmemcmp (wbuf, L"aabcEDCBA", 10))
FAIL ();
if (wcpcpy (wbuf + 8, wstr2) != wbuf + 9 || wmemcmp (wbuf, L"aabcEDCBF", 10))
FAIL ();
wcsncpy (wbuf + 6, L"X", l0 + 4);
if (wmemcmp (wbuf, L"aabcEDX\0\0", 10))
FAIL ();
if (wcpncpy (wbuf + 5, L"cd", l0 + 5) != wbuf + 7
|| wmemcmp (wbuf, L"aabcEcd\0\0", 10))
FAIL ();
if (swprintf (wbuf + 7, 3, L"%d", num2) >= 0
|| wmemcmp (wbuf, L"aabcEcd98", 10))
FAIL ();
wbuf[l0 + 8] = L'\0';
wcscat (wbuf, L"A");
if (wmemcmp (wbuf, L"aabcEcd9A", 10))
FAIL ();
wbuf[l0 + 7] = L'\0';
wcsncat (wbuf, L"ZYXWV", l0 + 2);
if (wmemcmp (wbuf, L"aabcEcdZY", 10))
FAIL ();
wmemcpy (wa.buf1, L"abcdefghij", l0 + 10);
wmemmove (wa.buf1 + 1, wa.buf1, l0 + 9);
if (wmemcmp (wa.buf1, L"aabcdefghi", 10))
FAIL ();
if (WMEMPCPY (wa.buf1 + 5, L"abcde", l0 + 5)
!= wa.buf1 + 5 + WMEMPCPY_RET (L"abcde")
|| wmemcmp (wa.buf1, L"aabcdabcde", 10))
FAIL ();
wmemset (wa.buf1 + 8, L'j', l0 + 2);
if (wmemcmp (wa.buf1, L"aabcdabcjj", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL < 2
/* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
and sufficient GCC support, as the string operations overflow
from a.buf1 into a.buf2. */
wcscpy (wa.buf1 + 4, wstr1 + 5);
if (wmemcmp (wa.buf1, L"aabcEDCBA", 10))
FAIL ();
if (wcpcpy (wa.buf1 + 8, wstr2) != wa.buf1 + 9
|| wmemcmp (wa.buf1, L"aabcEDCBF", 10))
FAIL ();
wcsncpy (wa.buf1 + 6, L"X", l0 + 4);
if (wmemcmp (wa.buf1, L"aabcEDX\0\0", 10))
FAIL ();
if (swprintf (wa.buf1 + 7, 3, L"%d", num2) >= 0
|| wmemcmp (wa.buf1, L"aabcEDX98", 10))
FAIL ();
wa.buf1[l0 + 8] = L'\0';
wcscat (wa.buf1, L"A");
if (wmemcmp (wa.buf1, L"aabcEDX9A", 10))
FAIL ();
wa.buf1[l0 + 7] = L'\0';
wcsncat (wa.buf1, L"ZYXWV", l0 + 2);
if (wmemcmp (wa.buf1, L"aabcEDXZY", 10))
FAIL ();
#endif
#if __USE_FORTIFY_LEVEL >= 1
/* Now check if all buffer overflows are caught at runtime.
N.B. All tests involving a length parameter need to be done
twice: once with the length a compile-time constant, once without. */
CHK_FAIL_START
wmemcpy (wbuf + 1, L"abcdefghij", 10);
CHK_FAIL_END
CHK_FAIL_START
wmemcpy (wbuf + 1, L"abcdefghij", l0 + 10);
CHK_FAIL_END
CHK_FAIL_START
wmemcpy (wbuf + 9, L"abcdefghij", 10);
CHK_FAIL_END
CHK_FAIL_START
wmemcpy (wbuf + 9, L"abcdefghij", l0 + 10);
CHK_FAIL_END
CHK_FAIL_START
wmemmove (wbuf + 2, wbuf + 1, 9);
CHK_FAIL_END
CHK_FAIL_START
wmemmove (wbuf + 2, wbuf + 1, l0 + 9);
CHK_FAIL_END
#ifdef _GNU_SOURCE
CHK_FAIL_START
wp = wmempcpy (wbuf + 6, L"abcde", 5);
CHK_FAIL_END
CHK_FAIL_START
wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5);
CHK_FAIL_END
#endif
CHK_FAIL_START
wmemset (wbuf + 9, L'j', 2);
CHK_FAIL_END
CHK_FAIL_START
wmemset (wbuf + 9, L'j', l0 + 2);
CHK_FAIL_END
CHK_FAIL_START
wcscpy (wbuf + 5, wstr1 + 5);
CHK_FAIL_END
CHK_FAIL_START
wp = wcpcpy (wbuf + 9, wstr2);
CHK_FAIL_END
CHK_FAIL_START
wcsncpy (wbuf + 7, L"X", 4);
CHK_FAIL_END
CHK_FAIL_START
wcsncpy (wbuf + 7, L"X", l0 + 4);
CHK_FAIL_END
CHK_FAIL_START
wcsncpy (wbuf + 9, L"XABCDEFGH", 8);
CHK_FAIL_END
CHK_FAIL_START
wcpncpy (wbuf + 9, L"XABCDEFGH", 8);
CHK_FAIL_END
CHK_FAIL_START
wcpncpy (wbuf + 6, L"cd", 5);
CHK_FAIL_END
CHK_FAIL_START
wcpncpy (wbuf + 6, L"cd", l0 + 5);
CHK_FAIL_END
wmemcpy (wbuf, wstr1 + 2, 9);
CHK_FAIL_START
wcscat (wbuf, L"AB");
CHK_FAIL_END
wmemcpy (wbuf, wstr1 + 3, 8);
CHK_FAIL_START
wcsncat (wbuf, L"ZYXWV", l0 + 3);
CHK_FAIL_END
CHK_FAIL_START
wmemcpy (wa.buf1 + 1, L"abcdefghij", 10);
CHK_FAIL_END
CHK_FAIL_START
wmemcpy (wa.buf1 + 1, L"abcdefghij", l0 + 10);
CHK_FAIL_END
CHK_FAIL_START
wmemmove (wa.buf1 + 2, wa.buf1 + 1, 9);
CHK_FAIL_END
CHK_FAIL_START
wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9);
CHK_FAIL_END
#ifdef _GNU_SOURCE
CHK_FAIL_START
wp = wmempcpy (wa.buf1 + 6, L"abcde", 5);
CHK_FAIL_END
CHK_FAIL_START
wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5);
CHK_FAIL_END
#endif
CHK_FAIL_START
wmemset (wa.buf1 + 9, L'j', 2);
CHK_FAIL_END
CHK_FAIL_START
wmemset (wa.buf1 + 9, L'j', l0 + 2);
CHK_FAIL_END
#if __USE_FORTIFY_LEVEL >= 2
# define O 0
#else
# define O 1
#endif
CHK_FAIL_START
wcscpy (wa.buf1 + (O + 4), wstr1 + 5);
CHK_FAIL_END
CHK_FAIL_START
wp = wcpcpy (wa.buf1 + (O + 8), wstr2);
CHK_FAIL_END
CHK_FAIL_START
wcsncpy (wa.buf1 + (O + 6), L"X", 4);
CHK_FAIL_END
CHK_FAIL_START
wcsncpy (wa.buf1 + (O + 6), L"X", l0 + 4);
CHK_FAIL_END
wmemcpy (wa.buf1, wstr1 + (3 - O), 8 + O);
CHK_FAIL_START
wcscat (wa.buf1, L"AB");
CHK_FAIL_END
wmemcpy (wa.buf1, wstr1 + (4 - O), 7 + O);
CHK_FAIL_START
wcsncat (wa.buf1, L"ZYXWV", l0 + 3);
CHK_FAIL_END
#endif
/* Now checks for %n protection. */
/* Constant literals passed directly are always ok
(even with warnings about possible bugs from GCC). */
int n1, n2;
if (sprintf (buf, "%s%n%s%n", str2, &n1, str2, &n2) != 2
|| n1 != 1 || n2 != 2)
FAIL ();
/* In this case the format string is not known at compile time,
but resides in read-only memory, so is ok. */
if (snprintf (buf, 4, str3, str2, &n1, str2, &n2) != 2
|| n1 != 1 || n2 != 2)
FAIL ();
strcpy (buf2 + 2, "%n%s%n");
/* When the format string is writable and contains %n,
with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */
CHK_FAIL2_START
if (sprintf (buf, buf2, str2, &n1, str2, &n1) != 2)
FAIL ();
CHK_FAIL2_END
CHK_FAIL2_START
if (snprintf (buf, 3, buf2, str2, &n1, str2, &n1) != 2)
FAIL ();
CHK_FAIL2_END
/* But if there is no %n, even writable format string
should work. */
buf2[6] = '\0';
if (sprintf (buf, buf2 + 4, str2) != 1)
FAIL ();
/* Constant literals passed directly are always ok
(even with warnings about possible bugs from GCC). */
if (printf ("%s%n%s%n", str4, &n1, str5, &n2) != 14
|| n1 != 7 || n2 != 14)
FAIL ();
/* In this case the format string is not known at compile time,
but resides in read-only memory, so is ok. */
if (printf (str3, str4, &n1, str5, &n2) != 14
|| n1 != 7 || n2 != 14)
FAIL ();
strcpy (buf2 + 2, "%n%s%n");
/* When the format string is writable and contains %n,
with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */
CHK_FAIL2_START
if (printf (buf2, str4, &n1, str5, &n1) != 14)
FAIL ();
CHK_FAIL2_END
/* But if there is no %n, even writable format string
should work. */
buf2[6] = '\0';
if (printf (buf2 + 4, str5) != 7)
FAIL ();
FILE *fp = stdout;
/* Constant literals passed directly are always ok
(even with warnings about possible bugs from GCC). */
if (fprintf (fp, "%s%n%s%n", str4, &n1, str5, &n2) != 14
|| n1 != 7 || n2 != 14)
FAIL ();
/* In this case the format string is not known at compile time,
but resides in read-only memory, so is ok. */
if (fprintf (fp, str3, str4, &n1, str5, &n2) != 14
|| n1 != 7 || n2 != 14)
FAIL ();
strcpy (buf2 + 2, "%n%s%n");
/* When the format string is writable and contains %n,
with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */
CHK_FAIL2_START
if (fprintf (fp, buf2, str4, &n1, str5, &n1) != 14)
FAIL ();
CHK_FAIL2_END
/* But if there is no %n, even writable format string
should work. */
buf2[6] = '\0';
if (fprintf (fp, buf2 + 4, str5) != 7)
FAIL ();
#ifdef _GNU_SOURCE
char *my_ptr = NULL;
strcpy (buf2 + 2, "%n%s%n");
/* When the format string is writable and contains %n,
with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */
CHK_FAIL2_START
if (asprintf (&my_ptr, buf2, str4, &n1, str5, &n1) != 14)
FAIL ();
else
free (my_ptr);
CHK_FAIL2_END
struct obstack obs;
obstack_init (&obs);
CHK_FAIL2_START
if (obstack_printf (&obs, buf2, str4, &n1, str5, &n1) != 14)
FAIL ();
CHK_FAIL2_END
obstack_free (&obs, NULL);
my_ptr = NULL;
if (asprintf (&my_ptr, "%s%n%s%n", str4, &n1, str5, &n1) != 14)
FAIL ();
else
free (my_ptr);
obstack_init (&obs);
if (obstack_printf (&obs, "%s%n%s%n", str4, &n1, str5, &n1) != 14)
FAIL ();
obstack_free (&obs, NULL);
#endif
if (freopen (temp_filename, "r", stdin) == NULL)
{
puts ("could not open temporary file");
exit (1);
}
if (gets (buf) != buf || memcmp (buf, "abcdefgh", 9))
FAIL ();
if (gets (buf) != buf || memcmp (buf, "ABCDEFGHI", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (gets (buf) != buf)
FAIL ();
CHK_FAIL_END
#endif
rewind (stdin);
if (fgets (buf, buf_size, stdin) != buf
|| memcmp (buf, "abcdefgh\n", 10))
FAIL ();
if (fgets (buf, buf_size, stdin) != buf || memcmp (buf, "ABCDEFGHI", 10))
FAIL ();
rewind (stdin);
if (fgets (buf, l0 + buf_size, stdin) != buf
|| memcmp (buf, "abcdefgh\n", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (fgets (buf, buf_size + 1, stdin) != buf)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (fgets (buf, l0 + buf_size + 1, stdin) != buf)
FAIL ();
CHK_FAIL_END
#endif
rewind (stdin);
#ifdef _GNU_SOURCE
if (fgets_unlocked (buf, buf_size, stdin) != buf
|| memcmp (buf, "abcdefgh\n", 10))
FAIL ();
if (fgets_unlocked (buf, buf_size, stdin) != buf
|| memcmp (buf, "ABCDEFGHI", 10))
FAIL ();
rewind (stdin);
if (fgets_unlocked (buf, l0 + buf_size, stdin) != buf
|| memcmp (buf, "abcdefgh\n", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (fgets_unlocked (buf, buf_size + 1, stdin) != buf)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (fgets_unlocked (buf, l0 + buf_size + 1, stdin) != buf)
FAIL ();
CHK_FAIL_END
#endif
rewind (stdin);
#endif
if (fread (buf, 1, buf_size, stdin) != buf_size
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread (buf, buf_size, 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
rewind (stdin);
if (fread (buf, l0 + 1, buf_size, stdin) != buf_size
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread (buf, buf_size, l0 + 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (fread (buf, 1, buf_size + 1, stdin) != buf_size + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (fread (buf, buf_size + 1, l0 + 1, stdin) != 1)
FAIL ();
CHK_FAIL_END
#endif
rewind (stdin);
if (fread_unlocked (buf, 1, buf_size, stdin) != buf_size
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread_unlocked (buf, buf_size, 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
rewind (stdin);
if (fread_unlocked (buf, 1, 4, stdin) != 4
|| memcmp (buf, "abcdFGHI\na", 10))
FAIL ();
if (fread_unlocked (buf, 4, 1, stdin) != 1
|| memcmp (buf, "efghFGHI\na", 10))
FAIL ();
rewind (stdin);
if (fread_unlocked (buf, l0 + 1, buf_size, stdin) != buf_size
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread_unlocked (buf, buf_size, l0 + 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (fread_unlocked (buf, 1, buf_size + 1, stdin) != buf_size + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (fread_unlocked (buf, buf_size + 1, l0 + 1, stdin) != 1)
FAIL ();
CHK_FAIL_END
#endif
lseek (fileno (stdin), 0, SEEK_SET);
if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1
|| memcmp (buf, "abcdefgh\n", 9))
FAIL ();
if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1
|| memcmp (buf, "ABCDEFGHI", 9))
FAIL ();
lseek (fileno (stdin), 0, SEEK_SET);
if (read (fileno (stdin), buf, l0 + buf_size - 1) != buf_size - 1
|| memcmp (buf, "abcdefgh\n", 9))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (read (fileno (stdin), buf, buf_size + 1) != buf_size + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (read (fileno (stdin), buf, l0 + buf_size + 1) != buf_size + 1)
FAIL ();
CHK_FAIL_END
#endif
if (pread (fileno (stdin), buf, buf_size - 1, buf_size - 2)
!= buf_size - 1
|| memcmp (buf, "\nABCDEFGH", 9))
FAIL ();
if (pread (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1
|| memcmp (buf, "abcdefgh\n", 9))
FAIL ();
if (pread (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3)
!= buf_size - 1
|| memcmp (buf, "h\nABCDEFG", 9))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (pread (fileno (stdin), buf, buf_size + 1, 2 * buf_size)
!= buf_size + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (pread (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size)
!= buf_size + 1)
FAIL ();
CHK_FAIL_END
#endif
if (pread64 (fileno (stdin), buf, buf_size - 1, buf_size - 2)
!= buf_size - 1
|| memcmp (buf, "\nABCDEFGH", 9))
FAIL ();
if (pread64 (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1
|| memcmp (buf, "abcdefgh\n", 9))
FAIL ();
if (pread64 (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3)
!= buf_size - 1
|| memcmp (buf, "h\nABCDEFG", 9))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (pread64 (fileno (stdin), buf, buf_size + 1, 2 * buf_size)
!= buf_size + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (pread64 (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size)
!= buf_size + 1)
FAIL ();
CHK_FAIL_END
#endif
if (freopen (temp_filename, "r", stdin) == NULL)
{
puts ("could not open temporary file");
exit (1);
}
if (fseek (stdin, 9 + 10 + 11, SEEK_SET))
{
puts ("could not seek in test file");
exit (1);
}
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (gets (buf) != buf)
FAIL ();
CHK_FAIL_END
#endif
/* Check whether missing N$ formats are detected. */
CHK_FAIL2_START
printf ("%3$d\n", 1, 2, 3, 4);
CHK_FAIL2_END
CHK_FAIL2_START
fprintf (stdout, "%3$d\n", 1, 2, 3, 4);
CHK_FAIL2_END
CHK_FAIL2_START
sprintf (buf, "%3$d\n", 1, 2, 3, 4);
CHK_FAIL2_END
CHK_FAIL2_START
snprintf (buf, buf_size, "%3$d\n", 1, 2, 3, 4);
CHK_FAIL2_END
int sp[2];
if (socketpair (PF_UNIX, SOCK_STREAM, 0, sp))
FAIL ();
else
{
const char *sendstr = "abcdefgh\nABCDEFGH\n0123456789\n";
if ((size_t) send (sp[0], sendstr, strlen (sendstr), 0)
!= strlen (sendstr))
FAIL ();
char recvbuf[12];
if (recv (sp[1], recvbuf, sizeof recvbuf, MSG_PEEK)
!= sizeof recvbuf
|| memcmp (recvbuf, sendstr, sizeof recvbuf) != 0)
FAIL ();
if (recv (sp[1], recvbuf + 6, l0 + sizeof recvbuf - 7, MSG_PEEK)
!= sizeof recvbuf - 7
|| memcmp (recvbuf + 6, sendstr, sizeof recvbuf - 7) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (recv (sp[1], recvbuf + 1, sizeof recvbuf, MSG_PEEK)
!= sizeof recvbuf)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (recv (sp[1], recvbuf + 4, l0 + sizeof recvbuf - 3, MSG_PEEK)
!= sizeof recvbuf - 3)
FAIL ();
CHK_FAIL_END
#endif
socklen_t sl;
struct sockaddr_un sa_un;
sl = sizeof (sa_un);
if (recvfrom (sp[1], recvbuf, sizeof recvbuf, MSG_PEEK,
(struct sockaddr *) &sa_un, &sl)
!= sizeof recvbuf
|| memcmp (recvbuf, sendstr, sizeof recvbuf) != 0)
FAIL ();
sl = sizeof (sa_un);
if (recvfrom (sp[1], recvbuf + 6, l0 + sizeof recvbuf - 7, MSG_PEEK,
(struct sockaddr *) &sa_un, &sl) != sizeof recvbuf - 7
|| memcmp (recvbuf + 6, sendstr, sizeof recvbuf - 7) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
sl = sizeof (sa_un);
if (recvfrom (sp[1], recvbuf + 1, sizeof recvbuf, MSG_PEEK,
(struct sockaddr *) &sa_un, &sl) != sizeof recvbuf)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
sl = sizeof (sa_un);
if (recvfrom (sp[1], recvbuf + 4, l0 + sizeof recvbuf - 3, MSG_PEEK,
(struct sockaddr *) &sa_un, &sl) != sizeof recvbuf - 3)
FAIL ();
CHK_FAIL_END
#endif
close (sp[0]);
close (sp[1]);
}
char fname[] = "/tmp/tst-chk1-dir-XXXXXX\0foo";
char *enddir = strchr (fname, '\0');
if (mkdtemp (fname) == NULL)
{
printf ("mkdtemp failed: %m\n");
return 1;
}
*enddir = '/';
if (symlink ("bar", fname) != 0)
FAIL ();
char readlinkbuf[4];
if (readlink (fname, readlinkbuf, 4) != 3
|| memcmp (readlinkbuf, "bar", 3) != 0)
FAIL ();
if (readlink (fname, readlinkbuf + 1, l0 + 3) != 3
|| memcmp (readlinkbuf, "bbar", 4) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (readlink (fname, readlinkbuf + 2, l0 + 3) != 3)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (readlink (fname, readlinkbuf + 3, 4) != 3)
FAIL ();
CHK_FAIL_END
#endif
int tmpfd = open ("/tmp", O_RDONLY | O_DIRECTORY);
if (tmpfd < 0)
FAIL ();
if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf, 4) != 3
|| memcmp (readlinkbuf, "bar", 3) != 0)
FAIL ();
if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf + 1,
l0 + 3) != 3
|| memcmp (readlinkbuf, "bbar", 4) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf + 2,
l0 + 3) != 3)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf + 3,
4) != 3)
FAIL ();
CHK_FAIL_END
#endif
close (tmpfd);
char *cwd1 = getcwd (NULL, 0);
if (cwd1 == NULL)
FAIL ();
char *cwd2 = getcwd (NULL, 250);
if (cwd2 == NULL)
FAIL ();
if (cwd1 && cwd2)
{
if (strcmp (cwd1, cwd2) != 0)
FAIL ();
*enddir = '\0';
if (chdir (fname))
FAIL ();
char *cwd3 = getcwd (NULL, 0);
if (cwd3 == NULL)
FAIL ();
if (strcmp (fname, cwd3) != 0)
printf ("getcwd after chdir is '%s' != '%s',"
"get{c,}wd tests skipped\n", cwd3, fname);
else
{
char getcwdbuf[sizeof fname - 3];
char *cwd4 = getcwd (getcwdbuf, sizeof getcwdbuf);
if (cwd4 != getcwdbuf
|| strcmp (getcwdbuf, fname) != 0)
FAIL ();
cwd4 = getcwd (getcwdbuf + 1, l0 + sizeof getcwdbuf - 1);
if (cwd4 != getcwdbuf + 1
|| getcwdbuf[0] != fname[0]
|| strcmp (getcwdbuf + 1, fname) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (getcwd (getcwdbuf + 2, l0 + sizeof getcwdbuf)
!= getcwdbuf + 2)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (getcwd (getcwdbuf + 2, sizeof getcwdbuf)
!= getcwdbuf + 2)
FAIL ();
CHK_FAIL_END
#endif
if (getwd (getcwdbuf) != getcwdbuf
|| strcmp (getcwdbuf, fname) != 0)
FAIL ();
if (getwd (getcwdbuf + 1) != getcwdbuf + 1
|| strcmp (getcwdbuf + 1, fname) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (getwd (getcwdbuf + 2) != getcwdbuf + 2)
FAIL ();
CHK_FAIL_END
#endif
}
if (chdir (cwd1) != 0)
FAIL ();
free (cwd3);
}
free (cwd1);
free (cwd2);
*enddir = '/';
if (unlink (fname) != 0)
FAIL ();
*enddir = '\0';
if (rmdir (fname) != 0)
FAIL ();
#if PATH_MAX > 0
char largebuf[PATH_MAX];
char *realres = realpath (".", largebuf);
if (realres != largebuf)
FAIL ();
# if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char realbuf[1];
realres = realpath (".", realbuf);
if (realres != realbuf)
FAIL ();
CHK_FAIL_END
# endif
#endif
if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
{
assert (MB_CUR_MAX <= 10);
/* First a simple test. */
char enough[10];
if (wctomb (enough, L'A') != 1)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
/* We know the wchar_t encoding is ISO 10646. So pick a
character which has a multibyte representation which does not
fit. */
CHK_FAIL_START
char smallbuf[2];
if (wctomb (smallbuf, L'\x100') != 2)
FAIL ();
CHK_FAIL_END
#endif
mbstate_t s;
memset (&s, '\0', sizeof (s));
if (wcrtomb (enough, L'D', &s) != 1 || enough[0] != 'D')
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
/* We know the wchar_t encoding is ISO 10646. So pick a
character which has a multibyte representation which does not
fit. */
CHK_FAIL_START
char smallbuf[1];
if (wcrtomb (smallbuf, L'\x100', &s) != 2)
FAIL ();
CHK_FAIL_END
/* Same input with a large enough buffer and we're good. */
char bigenoughbuf[2];
if (wcrtomb (bigenoughbuf, L'\x100', &s) != 2)
FAIL ();
#endif
wchar_t wenough[10];
memset (&s, '\0', sizeof (s));
const char *cp = "A";
if (mbsrtowcs (wenough, &cp, 10, &s) != 1
|| wcscmp (wenough, L"A") != 0)
FAIL ();
cp = "BC";
if (mbsrtowcs (wenough, &cp, l0 + 10, &s) != 2
|| wcscmp (wenough, L"BC") != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
wchar_t wsmallbuf[2];
cp = "ABC";
mbsrtowcs (wsmallbuf, &cp, 10, &s);
CHK_FAIL_END
#endif
/* Bug 29030 regresion check */
cp = "HelloWorld";
if (mbsrtowcs (NULL, &cp, (size_t)-1, &s) != 10)
FAIL ();
cp = "A";
if (mbstowcs (wenough, cp, 10) != 1
|| wcscmp (wenough, L"A") != 0)
FAIL ();
cp = "DEF";
if (mbstowcs (wenough, cp, l0 + 10) != 3
|| wcscmp (wenough, L"DEF") != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
wchar_t wsmallbuf[2];
cp = "ABC";
mbstowcs (wsmallbuf, cp, 10);
CHK_FAIL_END
#endif
memset (&s, '\0', sizeof (s));
cp = "ABC";
wcscpy (wenough, L"DEF");
if (mbsnrtowcs (wenough, &cp, 1, 10, &s) != 1
|| wcscmp (wenough, L"AEF") != 0)
FAIL ();
cp = "IJ";
if (mbsnrtowcs (wenough, &cp, 1, l0 + 10, &s) != 1
|| wcscmp (wenough, L"IEF") != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
wchar_t wsmallbuf[2];
cp = "ABC";
mbsnrtowcs (wsmallbuf, &cp, 3, 10, &s);
CHK_FAIL_END
#endif
memset (&s, '\0', sizeof (s));
const wchar_t *wcp = L"A";
if (wcsrtombs (enough, &wcp, 10, &s) != 1
|| strcmp (enough, "A") != 0)
FAIL ();
wcp = L"BC";
if (wcsrtombs (enough, &wcp, l0 + 10, &s) != 2
|| strcmp (enough, "BC") != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[2];
wcp = L"ABC";
wcsrtombs (smallbuf, &wcp, 10, &s);
CHK_FAIL_END
#endif
memset (enough, 'Z', sizeof (enough));
wcp = L"EF";
if (wcstombs (enough, wcp, 10) != 2
|| strcmp (enough, "EF") != 0)
FAIL ();
wcp = L"G";
if (wcstombs (enough, wcp, l0 + 10) != 1
|| strcmp (enough, "G") != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[2];
wcp = L"ABC";
wcstombs (smallbuf, wcp, 10);
CHK_FAIL_END
#endif
memset (&s, '\0', sizeof (s));
wcp = L"AB";
if (wcsnrtombs (enough, &wcp, 1, 10, &s) != 1
|| strcmp (enough, "A") != 0)
FAIL ();
wcp = L"BCD";
if (wcsnrtombs (enough, &wcp, 1, l0 + 10, &s) != 1
|| strcmp (enough, "B") != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[2];
wcp = L"ABC";
wcsnrtombs (smallbuf, &wcp, 3, 10, &s);
CHK_FAIL_END
#endif
}
else
{
puts ("cannot set locale");
ret = 1;
}
int fd;
#ifdef _GNU_SOURCE
fd = posix_openpt (O_RDWR);
if (fd != -1)
{
char enough[1000];
if (ptsname_r (fd, enough, sizeof (enough)) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[2];
if (ptsname_r (fd, smallbuf, sizeof (smallbuf) + 1) == 0)
FAIL ();
CHK_FAIL_END
#endif
close (fd);
}
#endif
#if PATH_MAX > 0
confstr (_CS_GNU_LIBC_VERSION, largebuf, sizeof (largebuf));
# if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[1];
confstr (_CS_GNU_LIBC_VERSION, smallbuf, sizeof (largebuf));
CHK_FAIL_END
# endif
#endif
gid_t grpslarge[5];
int ngr = getgroups (5, grpslarge);
asm volatile ("" : : "r" (ngr));
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[1];
ngr = getgroups (5, (gid_t *) smallbuf);
asm volatile ("" : : "r" (ngr));
CHK_FAIL_END
#endif
fd = open (_PATH_TTY, O_RDONLY);
if (fd != -1)
{
char enough[1000];
if (ttyname_r (fd, enough, sizeof (enough)) != 0)
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[2];
if (ttyname_r (fd, smallbuf, sizeof (smallbuf) + 1) == 0)
FAIL ();
CHK_FAIL_END
#endif
close (fd);
}
char hostnamelarge[1000];
gethostname (hostnamelarge, sizeof (hostnamelarge));
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[1];
gethostname (smallbuf, sizeof (hostnamelarge));
CHK_FAIL_END
#endif
char loginlarge[1000];
getlogin_r (loginlarge, sizeof (hostnamelarge));
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[1];
getlogin_r (smallbuf, sizeof (loginlarge));
CHK_FAIL_END
#endif
char domainnamelarge[1000];
int res = getdomainname (domainnamelarge, sizeof (domainnamelarge));
asm volatile ("" : : "r" (res));
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
char smallbuf[1];
res = getdomainname (smallbuf, sizeof (domainnamelarge));
asm volatile ("" : : "r" (res));
CHK_FAIL_END
#endif
fd_set s;
FD_ZERO (&s);
FD_SET (FD_SETSIZE - 1, &s);
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
FD_SET (FD_SETSIZE, &s);
CHK_FAIL_END
CHK_FAIL_START
FD_SET (l0 + FD_SETSIZE, &s);
CHK_FAIL_END
#endif
FD_CLR (FD_SETSIZE - 1, &s);
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
FD_CLR (FD_SETSIZE, &s);
CHK_FAIL_END
CHK_FAIL_START
FD_SET (l0 + FD_SETSIZE, &s);
CHK_FAIL_END
#endif
FD_ISSET (FD_SETSIZE - 1, &s);
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
FD_ISSET (FD_SETSIZE, &s);
CHK_FAIL_END
CHK_FAIL_START
FD_ISSET (l0 + FD_SETSIZE, &s);
CHK_FAIL_END
#endif
struct pollfd fds[1];
fds[0].fd = STDOUT_FILENO;
fds[0].events = POLLOUT;
poll (fds, 1, 0);
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
poll (fds, 2, 0);
CHK_FAIL_END
CHK_FAIL_START
poll (fds, l0 + 2, 0);
CHK_FAIL_END
#endif
#ifdef _GNU_SOURCE
ppoll (fds, 1, NULL, NULL);
# if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
ppoll (fds, 2, NULL, NULL);
CHK_FAIL_END
CHK_FAIL_START
ppoll (fds, l0 + 2, NULL, NULL);
CHK_FAIL_END
# endif
#endif
return ret;
}