diff mbox series

[v1,1/3] String: tst-memset-overflow.c Add test for overflow case.

Message ID 20210607071025.449866-1-goldstein.w.n@gmail.com
State New
Headers show
Series [v1,1/3] String: tst-memset-overflow.c Add test for overflow case. | expand

Commit Message

Noah Goldstein June 7, 2021, 7:10 a.m. UTC
The following commit:

author	Noah Goldstein <goldstein.w.n@gmail.com>
Thu, 20 May 2021 17:13:51 +0000 (13:13 -0400)
commit	6abf27980a947f9b6e514d6b33b83059d39566ae

added a bug to memset so that if destination +
length overflowed memset would return early rather than throw a
Segmentation Fault as is expected behavior:

This commit adds a new test file: tst-memset-overflow.c that is
expected to Segmentation Fault if that bug is not present

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
---
Currently the test will "FAIL" which is expected. I am unsure,
however, how to get the test to "PASS" while also inducing
Segmentation Faults.
 string/Makefile              |   2 +-
 string/tst-memset-overflow.c | 156 +++++++++++++++++++++++++++++++++++
 2 files changed, 157 insertions(+), 1 deletion(-)
 create mode 100644 string/tst-memset-overflow.c

Comments

Joseph Myers June 7, 2021, 7:44 p.m. UTC | #1
On Mon, 7 Jun 2021, Noah Goldstein via Libc-alpha wrote:

> Currently the test will "FAIL" which is expected. I am unsure,
> however, how to get the test to "PASS" while also inducing
> Segmentation Faults.

You can try defining EXPECTED_SIGNAL to SIGSEGV, though it wouldn't 
surprise me if problems arise on some platforms (even if the string 
function implementations are logically correct for this case).
Siddhesh Poyarekar June 8, 2021, 5:15 a.m. UTC | #2
On 6/7/21 12:40 PM, Noah Goldstein via Libc-alpha wrote:
> The following commit:
> 
> author	Noah Goldstein <goldstein.w.n@gmail.com>
> Thu, 20 May 2021 17:13:51 +0000 (13:13 -0400)
> commit	6abf27980a947f9b6e514d6b33b83059d39566ae
> 
> added a bug to memset so that if destination +
> length overflowed memset would return early rather than throw a
> Segmentation Fault as is expected behavior:
> 
> This commit adds a new test file: tst-memset-overflow.c that is
> expected to Segmentation Fault if that bug is not present

Similar to the memcmp patch, this is undefined behaviour, it doesn't 
make sense to add a test for this or to explicitly modify memset to 
guarantee a segfault if it has a performance impact.

Patch 2/3 looks like it could be included on its own since the new tests 
don't seem to test undefined behaviour.

Siddhesh
diff mbox series

Patch

diff --git a/string/Makefile b/string/Makefile
index f0fce2a0b8..fd701a76e5 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -63,7 +63,7 @@  tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strtok_r bug-strcoll2 tst-cmp tst-xbzero-opt	\
 		   test-endian-types test-endian-file-scope		\
 		   test-endian-sign-conversion tst-memmove-overflow	\
-		   test-sig_np
+		   tst-memset-overflow test-sig_np
 
 # Both tests require the .mo translation files generated by msgfmt.
 tests-translation := tst-strsignal					\
diff --git a/string/tst-memset-overflow.c b/string/tst-memset-overflow.c
new file mode 100644
index 0000000000..5a2d49407b
--- /dev/null
+++ b/string/tst-memset-overflow.c
@@ -0,0 +1,156 @@ 
+/* Test memset functions.
+   Copyright (C) 1999-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   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/>.  */
+
+#define TEST_MAIN
+#ifdef TEST_BZERO
+# ifdef TEST_EXPLICIT_BZERO
+#  define TEST_NAME "explicit_bzero"
+# else
+#  define TEST_NAME "bzero"
+# endif
+#else
+# ifndef WIDE
+#  define TEST_NAME "memset"
+# else
+#  define TEST_NAME "wmemset"
+# endif /* WIDE */
+#endif /* !TEST_BZERO */
+#define MIN_PAGE_SIZE 131072
+#include "test-string.h"
+
+#ifndef WIDE
+# define MEMSET memset
+# define CHAR char
+# define UCHAR unsigned char
+# define SIMPLE_MEMSET simple_memset
+# define MEMCMP memcmp
+# define BIG_CHAR CHAR_MAX
+#else
+# include <wchar.h>
+# define MEMSET wmemset
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define SIMPLE_MEMSET simple_wmemset
+# define MEMCMP wmemcmp
+# define BIG_CHAR WCHAR_MAX
+#endif /* WIDE */
+
+CHAR *SIMPLE_MEMSET (CHAR *, int, size_t);
+
+#ifdef TEST_BZERO
+typedef void (*proto_t) (char *, size_t);
+void simple_bzero (char *, size_t);
+void builtin_bzero (char *, size_t);
+
+IMPL (simple_bzero, 0)
+IMPL (builtin_bzero, 0)
+#ifdef TEST_EXPLICIT_BZERO
+IMPL (explicit_bzero, 1)
+#else
+IMPL (bzero, 1)
+#endif
+
+void
+simple_bzero (char *s, size_t n)
+{
+  SIMPLE_MEMSET (s, 0, n);
+}
+
+void
+builtin_bzero (char *s, size_t n)
+{
+  __builtin_bzero (s, n);
+}
+#else
+typedef CHAR *(*proto_t) (CHAR *, int, size_t);
+
+IMPL (SIMPLE_MEMSET, 0)
+# ifndef WIDE
+char *builtin_memset (char *, int, size_t);
+IMPL (builtin_memset, 0)
+# endif /* !WIDE */
+IMPL (MEMSET, 1)
+
+# ifndef WIDE
+char *
+builtin_memset (char *s, int c, size_t n)
+{
+  return __builtin_memset (s, c, n);
+}
+# endif /* !WIDE */
+#endif /* !TEST_BZERO */
+
+CHAR *
+inhibit_loop_to_libcall
+SIMPLE_MEMSET (CHAR *s, int c, size_t n)
+{
+  CHAR *r = s, *end = s + n;
+  while (r != end)
+    *r++ = c;
+  return s;
+}
+
+int
+test_main (void)
+{
+  size_t i, len;
+  const size_t one = 1;
+
+  test_init ();
+
+  printf ("%24s", "");
+  FOR_EACH_IMPL (impl, 0)
+    printf ("\t%s", impl->name);
+  putchar ('\n');
+
+  for (i = 1; i <= 2; ++i)
+    {
+      len = one << (8 * sizeof(size_t) - i);
+      FOR_EACH_IMPL (impl, 0)
+        {
+#ifdef TEST_BZERO
+          CALL (impl, (CHAR *) (buf1), len);
+#else
+          CALL (impl, (CHAR *) (buf1), 0, len);
+#endif
+          printf ("Should have thrown Segmentation Fault For (%p, %zu) %s",
+              buf1, len, impl->name);
+          ret = 1;
+        }
+    }
+  len = 0;
+  for (i = 8 * sizeof(size_t); i != 0; --i)
+    {
+      len |= (one << i);
+      FOR_EACH_IMPL (impl, 0)
+        {
+#ifdef TEST_BZERO
+          CALL (impl, (CHAR *) (buf1), len);
+#else
+          CALL (impl, (CHAR *) (buf1), 0, len);
+#endif
+          printf ("Should have thrown Segmentation Fault For (%p, %zu) %s",
+              buf1, len, impl->name);
+          ret = 1;
+        }
+    }
+  return ret;
+}
+
+#include <support/test-driver.c>