Message ID | 20231221185929.1307116-6-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | Improve fortify support with clang | expand |
On 2023-12-21 13:59, Adhemerval Zanella wrote: > Similar to other printf-like ones. It requires to be in a different > process so we can change the orientation of stdout. > > Checked on aarch64, armhf, x86_64, and i686. > --- > debug/Makefile | 2 + > debug/tst-fortify-wide.c | 104 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 106 insertions(+) > create mode 100644 debug/tst-fortify-wide.c > > diff --git a/debug/Makefile b/debug/Makefile > index fdc250e209..ed90ef7030 100644 > --- a/debug/Makefile > +++ b/debug/Makefile > @@ -180,6 +180,7 @@ CPPFLAGS-tst-realpath-chk.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 > CPPFLAGS-tst-chk-cancel.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 > CFLAGS-tst-sprintf-fortify-rdonly.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 > CFLAGS-tst-fortify-syslog.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 > +CFLAGS-tst-fortify-wide.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 > > # _FORTIFY_SOURCE tests. > # Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and > @@ -283,6 +284,7 @@ tests = \ > tst-backtrace4 \ > tst-backtrace5 \ > tst-backtrace6 \ > + tst-fortify-wide \ > tst-longjmp_chk \ > tst-longjmp_chk2 \ > tst-realpath-chk \ > diff --git a/debug/tst-fortify-wide.c b/debug/tst-fortify-wide.c > new file mode 100644 > index 0000000000..6947d04fa6 > --- /dev/null > +++ b/debug/tst-fortify-wide.c > @@ -0,0 +1,104 @@ > +/* Fortify check for wprintf. > + Copyright (C) 2004-2023 Free Software Foundation, Inc. > + Copyright The GNU Toolchain Authors. It's a new test, so just 2023 and FSF? Looks OK otherwise. > + 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/>. */ > + > +#include <setjmp.h> > +#include <stdio.h> > +#include <wchar.h> > +#include <unistd.h> > + > +#include <support/support.h> > + > +static volatile int chk_fail_ok; > +static volatile int ret; > +static 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); > +} > + > +static const wchar_t *wstr3 = L"%ls%n%ls%n"; > +static const wchar_t *wstr4 = L"Hello, "; > +static const wchar_t *wstr5 = L"World!\n"; > +static wchar_t wbuf2[20] = L"%ls"; > + > +#define WFAIL \ > + do { wprintf (L"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; \ > + WFAIL; \ > + } > + > +static int > +do_test (void) > +{ > + set_fortify_handler (handler); > + > + int n1, n2; > + > + int orientation = fwide (stdout, 1); > + if (orientation <= 0) > + WFAIL; > + > + /* Constant literals passed directly are always ok > + (even with warnings about possible bugs from GCC). */ > + if (wprintf (L"%ls%n%ls%n", wstr4, &n1, wstr5, &n2) != 14 > + || n1 != 7 || n2 != 14) > + WFAIL; > + > + /* In this case the format string is not known at compile time, > + but resides in read-only memory, so is ok. */ > + if (wprintf (wstr3, wstr4, &n1, wstr5, &n2) != 14 > + || n1 != 7 || n2 != 14) > + WFAIL; > + > + wcpcpy (&wbuf2[3], L"%n%ls%n"); > + /* When the format string is writable and contains %n, > + with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */ > + CHK_FAIL_START > + if (wprintf (wbuf2, wstr4, &n1, wstr5, &n1) != 14) > + WFAIL; > + CHK_FAIL_END > + > + /* But if there is no %n, even writable format string > + should work. */ > + wbuf2[8] = L'\0'; > + if (wprintf (&wbuf2[5], wstr5) != 7) > + WFAIL; > + > + /* Check whether missing N$ formats are detected. */ > + CHK_FAIL_START > + wprintf (L"%3$d\n", 1, 2, 3, 4); > + CHK_FAIL_END > + > + return ret; > +} > + > +#include <support/test-driver.c>
On 21/12/23 17:08, Siddhesh Poyarekar wrote: > > > On 2023-12-21 13:59, Adhemerval Zanella wrote: >> Similar to other printf-like ones. It requires to be in a different >> process so we can change the orientation of stdout. >> >> Checked on aarch64, armhf, x86_64, and i686. >> --- >> debug/Makefile | 2 + >> debug/tst-fortify-wide.c | 104 +++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 106 insertions(+) >> create mode 100644 debug/tst-fortify-wide.c >> >> diff --git a/debug/Makefile b/debug/Makefile >> index fdc250e209..ed90ef7030 100644 >> --- a/debug/Makefile >> +++ b/debug/Makefile >> @@ -180,6 +180,7 @@ CPPFLAGS-tst-realpath-chk.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 >> CPPFLAGS-tst-chk-cancel.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 >> CFLAGS-tst-sprintf-fortify-rdonly.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 >> CFLAGS-tst-fortify-syslog.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 >> +CFLAGS-tst-fortify-wide.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 >> # _FORTIFY_SOURCE tests. >> # Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and >> @@ -283,6 +284,7 @@ tests = \ >> tst-backtrace4 \ >> tst-backtrace5 \ >> tst-backtrace6 \ >> + tst-fortify-wide \ >> tst-longjmp_chk \ >> tst-longjmp_chk2 \ >> tst-realpath-chk \ >> diff --git a/debug/tst-fortify-wide.c b/debug/tst-fortify-wide.c >> new file mode 100644 >> index 0000000000..6947d04fa6 >> --- /dev/null >> +++ b/debug/tst-fortify-wide.c >> @@ -0,0 +1,104 @@ >> +/* Fortify check for wprintf. >> + Copyright (C) 2004-2023 Free Software Foundation, Inc. >> + Copyright The GNU Toolchain Authors. > > It's a new test, so just 2023 and FSF? Looks OK otherwise. It is a new test, I will adjust it before commit it. > >> + 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/>. */ >> + >> +#include <setjmp.h> >> +#include <stdio.h> >> +#include <wchar.h> >> +#include <unistd.h> >> + >> +#include <support/support.h> >> + >> +static volatile int chk_fail_ok; >> +static volatile int ret; >> +static 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); >> +} >> + >> +static const wchar_t *wstr3 = L"%ls%n%ls%n"; >> +static const wchar_t *wstr4 = L"Hello, "; >> +static const wchar_t *wstr5 = L"World!\n"; >> +static wchar_t wbuf2[20] = L"%ls"; >> + >> +#define WFAIL \ >> + do { wprintf (L"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; \ >> + WFAIL; \ >> + } >> + >> +static int >> +do_test (void) >> +{ >> + set_fortify_handler (handler); >> + >> + int n1, n2; >> + >> + int orientation = fwide (stdout, 1); >> + if (orientation <= 0) >> + WFAIL; >> + >> + /* Constant literals passed directly are always ok >> + (even with warnings about possible bugs from GCC). */ >> + if (wprintf (L"%ls%n%ls%n", wstr4, &n1, wstr5, &n2) != 14 >> + || n1 != 7 || n2 != 14) >> + WFAIL; >> + >> + /* In this case the format string is not known at compile time, >> + but resides in read-only memory, so is ok. */ >> + if (wprintf (wstr3, wstr4, &n1, wstr5, &n2) != 14 >> + || n1 != 7 || n2 != 14) >> + WFAIL; >> + >> + wcpcpy (&wbuf2[3], L"%n%ls%n"); >> + /* When the format string is writable and contains %n, >> + with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */ >> + CHK_FAIL_START >> + if (wprintf (wbuf2, wstr4, &n1, wstr5, &n1) != 14) >> + WFAIL; >> + CHK_FAIL_END >> + >> + /* But if there is no %n, even writable format string >> + should work. */ >> + wbuf2[8] = L'\0'; >> + if (wprintf (&wbuf2[5], wstr5) != 7) >> + WFAIL; >> + >> + /* Check whether missing N$ formats are detected. */ >> + CHK_FAIL_START >> + wprintf (L"%3$d\n", 1, 2, 3, 4); >> + CHK_FAIL_END >> + >> + return ret; >> +} >> + >> +#include <support/test-driver.c>
diff --git a/debug/Makefile b/debug/Makefile index fdc250e209..ed90ef7030 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -180,6 +180,7 @@ CPPFLAGS-tst-realpath-chk.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 CPPFLAGS-tst-chk-cancel.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 CFLAGS-tst-sprintf-fortify-rdonly.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 CFLAGS-tst-fortify-syslog.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 +CFLAGS-tst-fortify-wide.c += $(no-fortify-source),-D_FORTIFY_SOURCE=2 # _FORTIFY_SOURCE tests. # Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and @@ -283,6 +284,7 @@ tests = \ tst-backtrace4 \ tst-backtrace5 \ tst-backtrace6 \ + tst-fortify-wide \ tst-longjmp_chk \ tst-longjmp_chk2 \ tst-realpath-chk \ diff --git a/debug/tst-fortify-wide.c b/debug/tst-fortify-wide.c new file mode 100644 index 0000000000..6947d04fa6 --- /dev/null +++ b/debug/tst-fortify-wide.c @@ -0,0 +1,104 @@ +/* Fortify check for wprintf. + Copyright (C) 2004-2023 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/>. */ + +#include <setjmp.h> +#include <stdio.h> +#include <wchar.h> +#include <unistd.h> + +#include <support/support.h> + +static volatile int chk_fail_ok; +static volatile int ret; +static 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); +} + +static const wchar_t *wstr3 = L"%ls%n%ls%n"; +static const wchar_t *wstr4 = L"Hello, "; +static const wchar_t *wstr5 = L"World!\n"; +static wchar_t wbuf2[20] = L"%ls"; + +#define WFAIL \ + do { wprintf (L"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; \ + WFAIL; \ + } + +static int +do_test (void) +{ + set_fortify_handler (handler); + + int n1, n2; + + int orientation = fwide (stdout, 1); + if (orientation <= 0) + WFAIL; + + /* Constant literals passed directly are always ok + (even with warnings about possible bugs from GCC). */ + if (wprintf (L"%ls%n%ls%n", wstr4, &n1, wstr5, &n2) != 14 + || n1 != 7 || n2 != 14) + WFAIL; + + /* In this case the format string is not known at compile time, + but resides in read-only memory, so is ok. */ + if (wprintf (wstr3, wstr4, &n1, wstr5, &n2) != 14 + || n1 != 7 || n2 != 14) + WFAIL; + + wcpcpy (&wbuf2[3], L"%n%ls%n"); + /* When the format string is writable and contains %n, + with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */ + CHK_FAIL_START + if (wprintf (wbuf2, wstr4, &n1, wstr5, &n1) != 14) + WFAIL; + CHK_FAIL_END + + /* But if there is no %n, even writable format string + should work. */ + wbuf2[8] = L'\0'; + if (wprintf (&wbuf2[5], wstr5) != 7) + WFAIL; + + /* Check whether missing N$ formats are detected. */ + CHK_FAIL_START + wprintf (L"%3$d\n", 1, 2, 3, 4); + CHK_FAIL_END + + return ret; +} + +#include <support/test-driver.c>