diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2005-07-15 10:32:45 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2005-07-15 10:32:45 +0000 |
| commit | 8215c9ecf27714c7ec607aba0085383ef923777a (patch) | |
| tree | ff0127a461256dba9379940e5d33f08928aa4dcf /debug | |
| parent | f45729d8cd80b082c7724883aa9c6c858d0082f9 (diff) | |
| download | glibc-8215c9ecf27714c7ec607aba0085383ef923777a.tar.xz glibc-8215c9ecf27714c7ec607aba0085383ef923777a.zip | |
* wcsmbs/bits/wchar2.h: New file.
* include/bits/wchar2.h: New file.
* wcsmbs/wchar.h: Include <bits/wchar2.h> if fortification is
requested.
* wcsmbs/wcsncpy.c: Add __wcsncpy alias.
* string/bits/string3.h: Add fortified stpncpy definitions.
* sysdeps/generic/stpncpy_chk.c: New file.
* libio/vswprintf.c: Move _IO_wstrnfile definition to strfile.h.
Export _IO_wstrn_jumps.
* libio/strfile.h: Define _IO_wstrnfile and declare _IO_wstrn_jumps.
* include/wchar.h: Declare __wcsncpy and __vswprintf_chk.
* debug/fgetws_chk.c: New file.
* debug/fgetws_u_chk.c: New file.
* debug/fwprintf_chk.c: New file.
* debug/swprintf_chk.c: New file.
* debug/vfwprintf_chk.c: New file.
* debug/vswprintf_chk.c: New file.
* debug/vwprintf_chk.c: New file.
* debug/wcpcpy_chk.c: New file.
* debug/wcpncpy_chk.c: New file.
* debug/wcscat_chk.c: New file.
* debug/wcscpy_chk.c: New file.
* debug/wcsncat_chk.c: New file.
* debug/wcsncpy_chk.c: New file.
* debug/wmemcpy_chk.c: New file.
* debug/wmemmove_chk.c: New file.
* debug/wmempcpy_chk.c: New file.
* debug/wmemset_chk.c: New file.
* debug/wprintf_chk.c: New file.
* debug/tst-chk1.c: Add tests for new functions.
* debug/Versions: Export new functions.
* debug/Makefile (routines): Add new functions.
Diffstat (limited to 'debug')
| -rw-r--r-- | debug/Makefile | 17 | ||||
| -rw-r--r-- | debug/Versions | 5 | ||||
| -rw-r--r-- | debug/fgetws_chk.c | 54 | ||||
| -rw-r--r-- | debug/fgetws_u_chk.c | 61 | ||||
| -rw-r--r-- | debug/fwprintf_chk.c | 45 | ||||
| -rw-r--r-- | debug/swprintf_chk.c | 37 | ||||
| -rw-r--r-- | debug/tst-chk1.c | 247 | ||||
| -rw-r--r-- | debug/vfwprintf_chk.c | 42 | ||||
| -rw-r--r-- | debug/vswprintf_chk.c | 75 | ||||
| -rw-r--r-- | debug/vwprintf_chk.c | 43 | ||||
| -rw-r--r-- | debug/wcpcpy_chk.c | 45 | ||||
| -rw-r--r-- | debug/wcpncpy_chk.c | 33 | ||||
| -rw-r--r-- | debug/wcscat_chk.c | 55 | ||||
| -rw-r--r-- | debug/wcscpy_chk.c | 61 | ||||
| -rw-r--r-- | debug/wcsncat_chk.c | 96 | ||||
| -rw-r--r-- | debug/wcsncpy_chk.c | 33 | ||||
| -rw-r--r-- | debug/wmemcpy_chk.c | 30 | ||||
| -rw-r--r-- | debug/wmemmove_chk.c | 30 | ||||
| -rw-r--r-- | debug/wmempcpy_chk.c | 31 | ||||
| -rw-r--r-- | debug/wmemset_chk.c | 30 | ||||
| -rw-r--r-- | debug/wprintf_chk.c | 46 |
21 files changed, 1105 insertions, 11 deletions
diff --git a/debug/Makefile b/debug/Makefile index 51a9c9d42a..3f18359a74 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -26,13 +26,18 @@ distribute = sigcontextinfo.h register-dump.h frame.h routines = backtrace backtracesyms backtracesymsfd noophooks \ memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ - strcat_chk strcpy_chk strncat_chk strncpy_chk \ + strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ printf_chk fprintf_chk vprintf_chk vfprintf_chk \ gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ readlink_chk getwd_chk getcwd_chk realpath_chk ptsname_r_chk \ - wctomb_chk stack_chk_fail \ + wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ + wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ + wcpncpy_chk \ + swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \ + vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \ + stack_chk_fail \ $(static-only-routines) static-only-routines := warning-nop stack_chk_fail_local @@ -48,6 +53,14 @@ CFLAGS-vfprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) CFLAGS-gets_chk.c = -D_IO_MTSAFE_IO $(exceptions) CFLAGS-fgets_chk.c = -D_IO_MTSAFE_IO $(exceptions) CFLAGS-fgets_u_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-swprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-vswprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-wprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fwprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-vwprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-vfwprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fgetws_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fgetws_u_chk.c = -D_IO_MTSAFE_IO $(exceptions) CFLAGS-read_chk.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-pread_chk.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-pread64_chk.c = -fexceptions -fasynchronous-unwind-tables diff --git a/debug/Versions b/debug/Versions index 53fe6c02b0..0953c7733b 100644 --- a/debug/Versions +++ b/debug/Versions @@ -24,6 +24,11 @@ libc { __readlink_chk; __getcwd_chk; __getwd_chk; __recv_chk; __recvfrom_chk; __realpath_chk; __ptsname_r_chk; __wctomb_chk; + __stpncpy_chk; + __wcscpy_chk; __wmemcpy_chk; __wmemmove_chk; __wmempcpy_chk; __wcpcpy_chk; + __wcsncpy_chk; __wcscat_chk; __wcsncat_chk; __wmemset_chk; __wcpncpy_chk; + __swprintf_chk; __vswprintf_chk; __wprintf_chk; __fwprintf_chk; + __vwprintf_chk; __vfwprintf_chk; __fgetws_chk; __fgetws_unlocked_chk; __stack_chk_fail; } diff --git a/debug/fgetws_chk.c b/debug/fgetws_chk.c new file mode 100644 index 0000000000..d080ccb473 --- /dev/null +++ b/debug/fgetws_chk.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2001, 2005 + Free Software Foundation, Inc. + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "libioP.h" +#include <wchar.h> +#include <sys/param.h> + +wchar_t * +__fgetws_chk (wchar_t *buf, size_t size, int n, _IO_FILE *fp) +{ + _IO_size_t count; + wchar_t *result; + int old_error; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + _IO_acquire_lock (fp); + /* This is very tricky since a file descriptor may be in the + non-blocking mode. The error flag doesn't mean much in this + case. We return an error only when there is a new error. */ + old_error = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = _IO_getwline (fp, buf, MIN ((size_t) n - 1, size), L'\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || (_IO_ferror_unlocked (fp) && errno != EAGAIN)) + result = NULL; + else if (count >= size) + __chk_fail (); + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + _IO_release_lock (fp); + return result; +} diff --git a/debug/fgetws_u_chk.c b/debug/fgetws_u_chk.c new file mode 100644 index 0000000000..b6cc87b80d --- /dev/null +++ b/debug/fgetws_u_chk.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2005 Free Software Foundation, Inc. + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + As a special exception, if you link the code in this file with + files compiled with a GNU compiler to produce an executable, + that does not cause the resulting executable to be covered by + the GNU Lesser General Public License. This exception does not + however invalidate any other reasons why the executable file + might be covered by the GNU Lesser General Public License. + This exception applies to code released by its copyright holders + in files containing the exception. */ + +#include "libioP.h" +#include <wchar.h> +#include <sys/param.h> + +wchar_t * +__fgetws_unlocked_chk (wchar_t *buf, size_t size, int n, _IO_FILE *fp) +{ + _IO_size_t count; + wchar_t *result; + int old_error; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + /* This is very tricky since a file descriptor may be in the + non-blocking mode. The error flag doesn't mean much in this + case. We return an error only when there is a new error. */ + old_error = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = _IO_getwline (fp, buf, MIN ((size_t) n - 1, size), L'\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) + && errno != EAGAIN)) + result = NULL; + else if (count >= size) + __chk_fail (); + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + return result; +} diff --git a/debug/fwprintf_chk.c b/debug/fwprintf_chk.c new file mode 100644 index 0000000000..710c89f3c8 --- /dev/null +++ b/debug/fwprintf_chk.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2005 + Free Software Foundation, Inc. + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdarg.h> +#include <wchar.h> +#include "../libio/libioP.h" + + +/* Write formatted output to FP from the format string FORMAT. */ +int +__fwprintf_chk (FILE *fp, int flag, const wchar_t *format, ...) +{ + va_list ap; + int done; + + _IO_acquire_lock (fp); + if (flag > 0) + fp->_flags2 |= _IO_FLAGS2_FORTIFY; + + va_start (ap, format); + done = _IO_vfwprintf (fp, format, ap); + va_end (ap); + + if (flag > 0) + fp->_flags2 &= ~_IO_FLAGS2_FORTIFY; + _IO_release_lock (fp); + + return done; +} diff --git a/debug/swprintf_chk.c b/debug/swprintf_chk.c new file mode 100644 index 0000000000..554cbe66a3 --- /dev/null +++ b/debug/swprintf_chk.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991,1995,1997,1998,1999,2000,2003,2005 + Free Software Foundation, Inc. + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdarg.h> +#include <wchar.h> + +/* Write formatted output into S, according to the format string FORMAT. */ +/* VARARGS5 */ +int +__swprintf_chk (wchar_t *s, size_t n, int flag, size_t s_len, + const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vswprintf_chk (s, n, flag, s_len, format, arg); + va_end (arg); + + return done; +} diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c index ba50973868..a83bd843c6 100644 --- a/debug/tst-chk1.c +++ b/debug/tst-chk1.c @@ -25,9 +25,10 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <wchar.h> #include <sys/socket.h> #include <sys/un.h> -#include <unistd.h> char *temp_filename; static void do_prepare (void); @@ -72,6 +73,7 @@ handler (int sig) } char buf[10]; +wchar_t wbuf[10]; volatile size_t l0; volatile char *p; const char *str1 = "JIHGFEDCBA"; @@ -79,6 +81,11 @@ 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; @@ -123,6 +130,7 @@ do_test (void) setenv ("LIBC_FATAL_STDERR_", "1", 1); 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 @@ -138,7 +146,8 @@ do_test (void) if (memcmp (buf, "aabcdefghi", 10)) FAIL (); - if (mempcpy (buf + 5, "abcde", 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10)) + if (mempcpy (buf + 5, "abcde", 5) != buf + 10 + || memcmp (buf, "aabcdabcde", 10)) FAIL (); memset (buf + 8, 'j', 2); @@ -169,7 +178,8 @@ do_test (void) if (memcmp (buf, "aabcdefghi", 10)) FAIL (); - if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10)) + if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 + || memcmp (buf, "aabcdabcde", 10)) FAIL (); memset (buf + 8, 'j', l0 + 2); @@ -187,20 +197,24 @@ do_test (void) if (memcmp (buf, "aabcEDX\0\0", 10)) FAIL (); - if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEDX67", 10)) + if (stpncpy (buf + 5, "cd", l0 + 5) != buf + 7 + || memcmp (buf, "aabcEcd\0\0", 10)) FAIL (); - if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEDX98", 10)) + 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, "aabcEDX9A", 10)) + if (memcmp (buf, "aabcEcd9A", 10)) FAIL (); buf[l0 + 7] = '\0'; strncat (buf, "ZYXWV", l0 + 2); - if (memcmp (buf, "aabcEDXZY", 10)) + if (memcmp (buf, "aabcEcdZY", 10)) FAIL (); memcpy (a.buf1, "abcdefghij", l0 + 10); @@ -224,14 +238,16 @@ do_test (void) if (memcmp (a.buf1, "aabcEDCBA", 10)) FAIL (); - if (stpcpy (a.buf1 + 8, str2) != a.buf1 + 9 || memcmp (a.buf1, "aabcEDCBF", 10)) + 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)) + if (sprintf (a.buf1 + 7, "%d", num1) != 2 + || memcmp (a.buf1, "aabcEDX67", 10)) FAIL (); if (snprintf (a.buf1 + 7, 3, "%d", num2) != 6 @@ -282,6 +298,10 @@ do_test (void) CHK_FAIL_END CHK_FAIL_START + stpncpy (buf + 6, "cd", l0 + 5); + CHK_FAIL_END + + CHK_FAIL_START sprintf (buf + 8, "%d", num1); CHK_FAIL_END @@ -352,6 +372,215 @@ do_test (void) 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 + 10 + || 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 (); + + /* 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 + 10 + || 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 + 10 + || 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 |
