From b4677ed64e7aee1af7772750e0b18ed8271f4757 Mon Sep 17 00:00:00 2001
From: Maxim Ostapenko <m.ostapenko@samsung.com>
Date: Tue, 1 Nov 2016 16:52:13 +0300
Subject: [PATCH 6/7] Backport several testcases for ASan from upstream.

gcc/

	* asan.h (asan_intercepted_p): Handle BUILT_IN_STRCSPN,
	BUILT_IN_STRPBRK, BUILT_IN_STRSPN and BUILT_IN_STRSTR.

gcc/testsuite/

	* c-c++-common/asan/default_options.h: New file.
	* c-c++-common/asan/strcasestr-1.c: New test.
	* c-c++-common/asan/strcasestr-2.c: Likewise.
	* c-c++-common/asan/strcspn-1.c: Likewise.
	* c-c++-common/asan/strcspn-2.c: Likewise.
	* c-c++-common/asan/strpbrk-1.c: Likewise.
	* c-c++-common/asan/strpbrk-2.c: Likewise.
	* c-c++-common/asan/strspn-1.c: Likewise.
	* c-c++-common/asan/strspn-2.c: Likewise.
	* c-c++-common/asan/strstr-1.c: Likewise.
	* c-c++-common/asan/strstr-2.c: Likewise.
	* c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c: Likewise.
---
 gcc/ChangeLog                                      |  5 +++
 gcc/asan.h                                         |  4 +++
 gcc/testsuite/ChangeLog                            | 15 +++++++++
 gcc/testsuite/c-c++-common/asan/default_options.h  |  9 +++++
 .../asan/halt_on_error_suppress_equal_pcs-1.c      | 38 ++++++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strcasestr-1.c     | 32 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strcasestr-2.c     | 32 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strcspn-1.c        | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strcspn-2.c        | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strpbrk-1.c        | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strpbrk-2.c        | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strspn-1.c         | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strspn-2.c         | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strstr-1.c         | 31 ++++++++++++++++++
 gcc/testsuite/c-c++-common/asan/strstr-2.c         | 31 ++++++++++++++++++
 15 files changed, 383 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/asan/default_options.h
 create mode 100644 gcc/testsuite/c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strcasestr-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strcasestr-2.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strcspn-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strcspn-2.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strpbrk-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strpbrk-2.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strspn-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strspn-2.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strstr-1.c
 create mode 100644 gcc/testsuite/c-c++-common/asan/strstr-2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 943e21c..1da0ef9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
 2016-11-07  Maxim Ostapenko  <m.ostapenko@samsung.com>
 
+	* asan.h (asan_intercepted_p): Handle BUILT_IN_STRCSPN,
+	BUILT_IN_STRPBRK, BUILT_IN_STRSPN and BUILT_IN_STRSTR.
+
+2016-11-07  Maxim Ostapenko  <m.ostapenko@samsung.com>
+
 	* asan.h (ASAN_STACK_MAGIC_PARTIAL): Remove.
 	* asan.c (ASAN_STACK_MAGIC_PARTIAL): Replace with
 	ASAN_STACK_MAGIC_MIDDLE.
diff --git a/gcc/asan.h b/gcc/asan.h
index a259b1a..b96395b 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -102,6 +102,10 @@ asan_intercepted_p (enum built_in_function fcode)
 	 || fcode == BUILT_IN_STRNCASECMP
 	 || fcode == BUILT_IN_STRNCAT
 	 || fcode == BUILT_IN_STRNCMP
+	 || fcode == BUILT_IN_STRCSPN
+	 || fcode == BUILT_IN_STRPBRK
+	 || fcode == BUILT_IN_STRSPN
+	 || fcode == BUILT_IN_STRSTR
 	 || fcode == BUILT_IN_STRNCPY;
 }
 #endif /* TREE_ASAN */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 49fab6e..afa77a8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,20 @@
 2016-11-07  Maxim Ostapenko  <m.ostapenko@samsung.com>
 
+	* c-c++-common/asan/default_options.h: New file.
+	* c-c++-common/asan/strcasestr-1.c: New test.
+	* c-c++-common/asan/strcasestr-2.c: Likewise.
+	* c-c++-common/asan/strcspn-1.c: Likewise.
+	* c-c++-common/asan/strcspn-2.c: Likewise.
+	* c-c++-common/asan/strpbrk-1.c: Likewise.
+	* c-c++-common/asan/strpbrk-2.c: Likewise.
+	* c-c++-common/asan/strspn-1.c: Likewise.
+	* c-c++-common/asan/strspn-2.c: Likewise.
+	* c-c++-common/asan/strstr-1.c: Likewise.
+	* c-c++-common/asan/strstr-2.c: Likewise.
+	* c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c: Likewise.
+
+2016-11-07  Maxim Ostapenko  <m.ostapenko@samsung.com>
+
 	* c-c++-common/asan/null-deref-1.c: Adjust testcase.
 
 2016-10-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
diff --git a/gcc/testsuite/c-c++-common/asan/default_options.h b/gcc/testsuite/c-c++-common/asan/default_options.h
new file mode 100644
index 0000000..1e5c486
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/default_options.h
@@ -0,0 +1,9 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+const char *
+__asan_default_options ()
+{
+  /* The asan_default_options string should be defined in testcase.  */
+  return asan_default_options;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c b/gcc/testsuite/c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c
new file mode 100644
index 0000000..df44a04
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c
@@ -0,0 +1,38 @@
+/* Test suppress_equal_pcs in recovery mode.  */
+/* { dg-do run } */
+/* { dg-options "-fsanitize-recover=address" } */
+
+static const char asan_default_options[] = "halt_on_error=false:suppress_equal_pcs=true";
+#include "default_options.h"
+
+#define ACCESS_ARRAY_FIVE_ELEMENTS(array, i)                                   \
+  array[i] = i;                                                                \
+  array[i + 1] = i + 1;                                                        \
+  array[i + 2] = i + 2;                                                        \
+  array[i + 3] = i + 3;                                                        \
+  array[i + 4] = i + 4;
+
+volatile int ten = 10;
+unsigned kNumIterations = 10;
+
+int
+main (int argc, char **argv)
+{
+  char a[10];
+  char b[10];
+
+  for (int i = 0; i < kNumIterations; ++i)
+    {
+      volatile int res = a[ten + i];
+      a[i + ten] = res + 3;
+      res = a[ten + i];
+    }
+  return 0;
+}
+
+/* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */
+/* { dg-output "\[^\n\r]*WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */
+/* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */
+/* { dg-prune-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */
+/* { dg-prune-output "\[^\n\r]*WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */
+/* { dg-prune-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */
diff --git a/gcc/testsuite/c-c++-common/asan/strcasestr-1.c b/gcc/testsuite/c-c++-common/asan/strcasestr-1.c
new file mode 100644
index 0000000..a3e58df
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strcasestr-1.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifndef __cplusplus
+#define _GNU_SOURCE
+#else
+extern "C"
+#endif
+char *strcasestr (const char *haystack, const char *needle);
+
+int
+main (int argc, char **argv)
+{
+  char *r = 0;
+  char s2[] = "c";
+  char s1[4] = "abC";
+  __asan_poison_memory_region ((char *) &s1[2], 2);
+  r = strcasestr (s1, s2);
+  assert (r == s1 + 2);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strcasestr-1.(c:24)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strcasestr-2.c b/gcc/testsuite/c-c++-common/asan/strcasestr-2.c
new file mode 100644
index 0000000..f21d162
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strcasestr-2.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifndef __cplusplus
+#define _GNU_SOURCE
+#else
+extern "C"
+#endif
+char *strcasestr (const char *haystack, const char *needle);
+
+int
+main (int argc, char **argv)
+{
+  char *r = 0;
+  char s1[] = "ab";
+  char s2[4] = "cba";
+  __asan_poison_memory_region ((char *) &s2[2], 2);
+  r = strcasestr (s1, s2);
+  assert (r == 0);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strcasestr-2.(c:24)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strcspn-1.c b/gcc/testsuite/c-c++-common/asan/strcspn-1.c
new file mode 100644
index 0000000..8a95bac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strcspn-1.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+__SIZE_TYPE__
+strcspn (const char *s, const char *reject);
+
+int
+main (int argc, char **argv)
+{
+  __SIZE_TYPE__ r;
+  char s2[] = "ab";
+  char s1[4] = "caB";
+  __asan_poison_memory_region ((char *) &s1[2], 2);
+  r = strcspn (s1, s2);
+  assert (r == 1);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strcspn-1.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strcspn-2.c b/gcc/testsuite/c-c++-common/asan/strcspn-2.c
new file mode 100644
index 0000000..d605a41
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strcspn-2.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+__SIZE_TYPE__
+strcspn (const char *s, const char *reject);
+
+int
+main (int argc, char **argv)
+{
+  __SIZE_TYPE__ r;
+  char s1[] = "ab";
+  char s2[4] = "abc";
+  __asan_poison_memory_region ((char *) &s2[2], 2);
+  r = strcspn (s1, s2);
+  assert (r == 0);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strcspn-2.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strpbrk-1.c b/gcc/testsuite/c-c++-common/asan/strpbrk-1.c
new file mode 100644
index 0000000..f4c2590
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strpbrk-1.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+char *
+strpbrk (const char *s, const char *accept);
+
+int
+main (int argc, char **argv)
+{
+  char *r;
+  char s2[] = "ab";
+  char s1[4] = "cab";
+  __asan_poison_memory_region ((char *) &s1[2], 2);
+  r = strpbrk (s1, s2);
+  assert (r == s1 + 1);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strpbrk-1.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strpbrk-2.c b/gcc/testsuite/c-c++-common/asan/strpbrk-2.c
new file mode 100644
index 0000000..4558694
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strpbrk-2.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+char *
+strpbrk (const char *s, const char *accept);
+
+int
+main (int argc, char **argv)
+{
+  char *r;
+  char s1[] = "c";
+  char s2[4] = "bca";
+  __asan_poison_memory_region ((char *) &s2[2], 2);
+  r = strpbrk (s1, s2);
+  assert (r == s1);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strpbrk-2.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strspn-1.c b/gcc/testsuite/c-c++-common/asan/strspn-1.c
new file mode 100644
index 0000000..63d96ba
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strspn-1.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+__SIZE_TYPE__
+strspn (const char *s, const char *reject);
+
+int
+main (int argc, char **argv)
+{
+  __SIZE_TYPE__ r;
+  char s2[] = "ab";
+  char s1[4] = "acb";
+  __asan_poison_memory_region ((char *) &s1[2], 2);
+  r = strspn (s1, s2);
+  assert (r == 1);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strspn-1.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strspn-2.c b/gcc/testsuite/c-c++-common/asan/strspn-2.c
new file mode 100644
index 0000000..ac7a742
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strspn-2.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+__SIZE_TYPE__
+strspn (const char *s, const char *reject);
+
+int
+main (int argc, char **argv)
+{
+  size_t r;
+  char s1[] = "bbc";
+  char s2[5] = "abcd";
+  __asan_poison_memory_region ((char *) &s2[3], 2);
+  r = strspn (s1, s2);
+  assert (r >= 2);
+  return 0;
+}
+
+/* { dg-output "READ of size 5 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strspn-2.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strstr-1.c b/gcc/testsuite/c-c++-common/asan/strstr-1.c
new file mode 100644
index 0000000..2c59e53
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strstr-1.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+char *
+strstr (const char *haystack, const char *needle);
+
+int
+main (int argc, char **argv)
+{
+  char *r = 0;
+  char s2[] = "c";
+  char s1[4] = "acb";
+  __asan_poison_memory_region ((char *) &s1[2], 2);
+  r = strstr (s1, s2);
+  assert (r == s1 + 1);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strstr-1.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/strstr-2.c b/gcc/testsuite/c-c++-common/asan/strstr-2.c
new file mode 100644
index 0000000..785293c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/strstr-2.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static const char asan_default_options[] = "strict_string_checks=true";
+#include "default_options.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+char *
+strstr (const char *haystack, const char *needle);
+
+int
+main (int argc, char **argv)
+{
+  char *r = 0;
+  char s1[] = "ab";
+  char s2[4] = "cab";
+  __asan_poison_memory_region ((char *) &s2[2], 2);
+  r = strstr (s1, s2);
+  assert (r == 0);
+  return 0;
+}
+
+/* { dg-output "READ of size 4 at .* thread T0.*" } */
+/* { dg-output ".*(main)?.*strstr-2.(c:23)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
-- 
1.9.1

