From b7d7afe10ddf599452bd80b8a840c830cd474b09 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 5 Jan 2020 09:13:25 +0100 Subject: [PATCH] tests: Avoid GCC over-optimization caused by _GL_ARG_NONNULL attributes. Reported by Jim Meyering in . * lib/stdlib.in.h (GNULIB_defined_canonicalize_file_name): New macro. (GNULIB_defined_ptsname_r): New macro. * tests/test-canonicalize.c (_GL_ARG_NONNULL): Define to empty. (main): Disable the NULL argument test if canonicalize_file_name does not come from gnulib. * tests/test-canonicalize-lgpl.c (_GL_ARG_NONNULL): Define to empty. (main): Disable the NULL argument test if canonicalize_file_name does not come from gnulib. * tests/test-ptsname_r.c (_GL_ARG_NONNULL): Define to empty. (test_errors): Disable the NULL argument test if ptsname_r does not come from gnulib. --- ChangeLog | 17 +++++++++++++++++ lib/stdlib.in.h | 7 +++++++ tests/test-canonicalize-lgpl.c | 15 ++++++++++++++- tests/test-canonicalize.c | 17 +++++++++++++++++ tests/test-ptsname_r.c | 11 +++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a69db8585d..c8a9dbfac8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2020-01-05 Bruno Haible + + tests: Avoid GCC over-optimization caused by _GL_ARG_NONNULL attributes. + Reported by Jim Meyering in + . + * lib/stdlib.in.h (GNULIB_defined_canonicalize_file_name): New macro. + (GNULIB_defined_ptsname_r): New macro. + * tests/test-canonicalize.c (_GL_ARG_NONNULL): Define to empty. + (main): Disable the NULL argument test if canonicalize_file_name does + not come from gnulib. + * tests/test-canonicalize-lgpl.c (_GL_ARG_NONNULL): Define to empty. + (main): Disable the NULL argument test if canonicalize_file_name does + not come from gnulib. + * tests/test-ptsname_r.c (_GL_ARG_NONNULL): Define to empty. + (test_errors): Disable the NULL argument test if ptsname_r does not come + from gnulib. + 2020-01-04 Jim Meyering update-copyright: reenable its always-skipped test diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index e088959b28..e96e9d9e25 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -201,6 +201,10 @@ _GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name) # endif _GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name)); # endif +# ifndef GNULIB_defined_canonicalize_file_name +# define GNULIB_defined_canonicalize_file_name \ + !@HAVE_CANONICALIZE_FILE_NAME@ || @REPLACE_CANONICALIZE_FILE_NAME@ +# endif _GL_CXXALIASWARN (canonicalize_file_name); #elif defined GNULIB_POSIXCHECK # undef canonicalize_file_name @@ -516,6 +520,9 @@ _GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); # endif _GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); # endif +# ifndef GNULIB_defined_ptsname_r +# define GNULIB_defined_ptsname_r !@HAVE_PTSNAME_R@ || @REPLACE_PTSNAME_R@ +# endif _GL_CXXALIASWARN (ptsname_r); #elif defined GNULIB_POSIXCHECK # undef ptsname_r diff --git a/tests/test-canonicalize-lgpl.c b/tests/test-canonicalize-lgpl.c index b46ad872e1..fb49b2047e 100644 --- a/tests/test-canonicalize-lgpl.c +++ b/tests/test-canonicalize-lgpl.c @@ -1,4 +1,4 @@ -/* Test of execution of program termination handlers. +/* Test of execution of file name canonicalization. Copyright (C) 2007-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -16,6 +16,11 @@ /* Written by Bruno Haible , 2007. */ +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + may "optimize" the null_ptr function, when its result gets passed to a + function that has an argument declared as _GL_ARG_NONNULL. */ +#define _GL_ARG_NONNULL(params) + #include #include @@ -66,14 +71,22 @@ main (void) ASSERT (strstr (result, "/" BASE "/tra") == result + strlen (result) - strlen ("/" BASE "/tra")); free (result); + errno = 0; result = canonicalize_file_name (""); ASSERT (result == NULL); ASSERT (errno == ENOENT); + + /* This test works only if the canonicalize_file_name implementation + comes from gnulib. If it comes from libc, we have no way to prevent + gcc from "optimizing" the null_ptr function in invalid ways. See + . */ +#if GNULIB_defined_canonicalize_file_name errno = 0; result = canonicalize_file_name (null_ptr ()); ASSERT (result == NULL); ASSERT (errno == EINVAL); +#endif } /* Check that a non-directory with trailing slash yields NULL. */ diff --git a/tests/test-canonicalize.c b/tests/test-canonicalize.c index e7138a655d..81580c53d5 100644 --- a/tests/test-canonicalize.c +++ b/tests/test-canonicalize.c @@ -16,6 +16,11 @@ /* Written by Bruno Haible , 2007. */ +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + may "optimize" the null_ptr function, when its result gets passed to a + function that has an argument declared as _GL_ARG_NONNULL. */ +#define _GL_ARG_NONNULL(params) + #include #include "canonicalize.h" @@ -62,22 +67,34 @@ main (void) == result1 + strlen (result1) - strlen ("/" BASE "/tra")); free (result1); free (result2); + errno = 0; result1 = canonicalize_file_name (""); ASSERT (result1 == NULL); ASSERT (errno == ENOENT); + errno = 0; result2 = canonicalize_filename_mode ("", CAN_EXISTING); ASSERT (result2 == NULL); ASSERT (errno == ENOENT); + + /* This test works only if the canonicalize_file_name implementation + comes from gnulib. If it comes from libc, we have no way to prevent + gcc from "optimizing" the null_ptr function in invalid ways. See + . */ +#if GNULIB_defined_canonicalize_file_name errno = 0; result1 = canonicalize_file_name (null_ptr ()); ASSERT (result1 == NULL); ASSERT (errno == EINVAL); +#endif + errno = 0; result2 = canonicalize_filename_mode (NULL, CAN_EXISTING); ASSERT (result2 == NULL); ASSERT (errno == EINVAL); + + errno = 0; result2 = canonicalize_filename_mode (".", CAN_MISSING | CAN_ALL_BUT_LAST); ASSERT (result2 == NULL); ASSERT (errno == EINVAL); diff --git a/tests/test-ptsname_r.c b/tests/test-ptsname_r.c index 19e33ea858..24be52f31a 100644 --- a/tests/test-ptsname_r.c +++ b/tests/test-ptsname_r.c @@ -14,6 +14,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + may "optimize" the null_ptr function, when its result gets passed to a + function that has an argument declared as _GL_ARG_NONNULL. */ +#define _GL_ARG_NONNULL(params) + #include #include @@ -84,9 +89,15 @@ test_errors (int fd, const char *slave) } } + /* This test works only if the ptsname_r implementation comes from gnulib. + If it comes from libc, we have no way to prevent gcc from "optimizing" + the null_ptr function in invalid ways. See + . */ +#if GNULIB_defined_ptsname_r result = ptsname_r (fd, null_ptr (), 0); ASSERT (result != 0); ASSERT (result == EINVAL); +#endif } int -- 2.39.5