Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/tests/lib/libc/misc Import micro-UBSan ATF tests



details:   https://anonhg.NetBSD.org/src/rev/04a23b9606b6
branches:  trunk
changeset: 991857:04a23b9606b6
user:      kamil <kamil%NetBSD.org@localhost>
date:      Fri Aug 03 04:18:40 2018 +0000

description:
Import micro-UBSan ATF tests

These tests are used only when a distribution is built without MKSANITIZER
and without MKLIBCSANITIZER. They build the ubsan.c micro-implementation
in userland as a standalone library (a .c file linked into tests).

The code generation part emits symbols that are handled by uUBSan.

Tested with Clang amd64 + i386 and GCC amd64 + i386.

There are two sets of tests: C code generation and C++ code generation.

There are various little differences that are handled with proper ifdefs.

Clang 7svn has significantly more checks for Undefined Behavior than GCC
5.x. Some of the tests are or might be amd64 and/or i386 specific and are
marked with proper ifdefs and comments according to the compiler
documentation.

diffstat:

 tests/lib/libc/misc/Makefile      |   28 +
 tests/lib/libc/misc/t_ubsan.c     |  913 ++++++++++++++++++++++++++++++++++++++
 tests/lib/libc/misc/t_ubsanxx.cpp |   29 +
 3 files changed, 970 insertions(+), 0 deletions(-)

diffs (truncated from 982 to 300 lines):

diff -r 8d1bbc42e0f2 -r 04a23b9606b6 tests/lib/libc/misc/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/lib/libc/misc/Makefile      Fri Aug 03 04:18:40 2018 +0000
@@ -0,0 +1,28 @@
+# $NetBSD: Makefile,v 1.1 2018/08/03 04:18:40 kamil Exp $
+
+.include <bsd.own.mk>
+
+TESTSDIR=      ${TESTSBASE}/lib/libc/misc
+
+TESTS_C+=      t_ubsan
+TESTS_CXX+=    t_ubsanxx
+
+.PATH:         ${NETBSDSRCDIR}/common/lib/libc/misc
+SRCS.t_ubsan=  t_ubsan.c ubsan.c
+SRCS.t_ubsanxx=        t_ubsanxx.cpp ubsan.c
+
+.if ${MKSANITIZER:Uno} != "yes" && ${MKLIBCSANITIZER:Uno} != "yes"
+# These tests are designed to be used against micro-UBSan only.
+# micro-UBSan is used in these tests as a standalone libary only.
+CPPFLAGS+=             -DENABLE_TESTS
+UBSAN_FLAGS=           -fsanitize=undefined
+UBSAN_FLAGS+=          ${${ACTIVE_CC} == "clang" :? -fsanitize=integer :}
+UBSAN_FLAGS+=          ${${ACTIVE_CC} == "clang" :? -fsanitize=nullability :}
+CFLAGS+=               ${UBSAN_FLAGS}
+CXXFLAGS+=             ${UBSAN_FLAGS}
+CWARNFLAGS+=           -Wno-return-type -Wno-strict-aliasing
+CWARNFLAGS.clang+=     -Wno-incompatible-pointer-types-discards-qualifiers
+CWARNFLAGS.clang+=     -Wno-nullability-completeness 
+.endif
+
+.include <bsd.test.mk>
diff -r 8d1bbc42e0f2 -r 04a23b9606b6 tests/lib/libc/misc/t_ubsan.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/lib/libc/misc/t_ubsan.c     Fri Aug 03 04:18:40 2018 +0000
@@ -0,0 +1,913 @@
+/*     $NetBSD: t_ubsan.c,v 1.1 2018/08/03 04:18:40 kamil Exp $        */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__COPYRIGHT("@(#) Copyright (c) 2018\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_ubsan.c,v 1.1 2018/08/03 04:18:40 kamil Exp $");
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <limits.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+#include <atf-c++.hpp>
+#define UBSAN_TC(a)                    ATF_TEST_CASE(a)
+#define UBSAN_TC_HEAD(a, b)            ATF_TEST_CASE_HEAD(a)
+#define UBSAN_TC_BODY(a, b)            ATF_TEST_CASE_BODY(a)
+#define UBSAN_CASES(a)                 ATF_INIT_TEST_CASES(a)
+#define UBSAN_TEST_CASE(a, b)          ATF_ADD_TEST_CASE(a, b)
+#define UBSAN_MD_VAR(a, b, c)          set_md_var(b, c)
+#define REINTERPRET_CAST(__dt, __st)   reinterpret_cast<__dt>(__st)
+#define STATIC_CAST(__dt, __st)                static_cast<__dt>(__st)
+#else
+#include <atf-c.h>
+#define UBSAN_TC(a)                    ATF_TC(a)
+#define UBSAN_TC_HEAD(a, b)            ATF_TC_HEAD(a, b)
+#define UBSAN_TC_BODY(a, b)            ATF_TC_BODY(a, b)
+#define UBSAN_CASES(a)                 ATF_TP_ADD_TCS(a)
+#define UBSAN_TEST_CASE(a, b)          ATF_TP_ADD_TC(a, b)
+#define UBSAN_MD_VAR(a, b, c)          atf_tc_set_md_var(a, b, c)
+#define REINTERPRET_CAST(__dt, __st)   ((__dt)(__st))
+#define STATIC_CAST(__dt, __st)                ((__dt)(__st))
+#endif
+
+#ifdef ENABLE_TESTS
+static void
+test_case(void (*fun)(void), const char *string)
+{
+       int filedes[2];
+       pid_t pid;
+       FILE *fp;
+       size_t len;
+       char *buffer;
+       int status;
+
+       /*
+        * Spawn a subprocess that triggers the issue.
+        * A child process either exits or is signaled with a crash signal.
+        */
+       ATF_REQUIRE_EQ(pipe(filedes), 0);
+       pid = fork();
+       ATF_REQUIRE(pid != -1);
+       if (pid == 0) {
+               ATF_REQUIRE(dup2(filedes[1], STDERR_FILENO) != -1);
+               ATF_REQUIRE(close(filedes[0]) == 0);
+               ATF_REQUIRE(close(filedes[1]) == 0);
+
+               (*fun)();
+       }
+
+       ATF_REQUIRE(close(filedes[1]) == 0);
+
+       fp = fdopen(filedes[0], "r");
+       ATF_REQUIRE(fp != NULL);
+
+       buffer = fgetln(fp, &len);
+       ATF_REQUIRE(buffer != 0);
+       ATF_REQUIRE(!ferror(fp));
+       ATF_REQUIRE(strstr(buffer, string) != NULL);
+       ATF_REQUIRE(wait(&status) == pid);
+       ATF_REQUIRE(!WIFEXITED(status));
+       ATF_REQUIRE(WIFSIGNALED(status));
+       ATF_REQUIRE(!WIFSTOPPED(status));
+       ATF_REQUIRE(!WIFCONTINUED(status));
+}
+
+UBSAN_TC(add_overflow_signed);
+UBSAN_TC_HEAD(add_overflow_signed, tc)
+{
+        UBSAN_MD_VAR(tc, "descr",
+           "Checks -fsanitize=signed-integer-overflow");
+}
+
+static void
+test_add_overflow_signed(void)
+{
+       volatile int a = INT_MAX;
+       volatile int b = atoi("1");
+
+       raise((a + b) ? SIGSEGV : SIGBUS);
+}
+
+UBSAN_TC_BODY(add_overflow_signed, tc)
+{
+
+       test_case(test_add_overflow_signed, " signed integer overflow: ");
+}
+
+#ifdef __clang__
+UBSAN_TC(add_overflow_unsigned);
+UBSAN_TC_HEAD(add_overflow_unsigned, tc)
+{
+        UBSAN_MD_VAR(tc, "descr",
+           "Checks -fsanitize=unsigned-integer-overflow");
+}
+
+static void
+test_add_overflow_unsigned(void)
+{
+       volatile unsigned int a = UINT_MAX;
+       volatile unsigned int b = atoi("1");
+
+       raise((a + b) ? SIGSEGV : SIGBUS);
+}
+
+UBSAN_TC_BODY(add_overflow_unsigned, tc)
+{
+
+       test_case(test_add_overflow_unsigned, " unsigned integer overflow: ");
+}
+#endif
+
+UBSAN_TC(builtin_unreachable);
+UBSAN_TC_HEAD(builtin_unreachable, tc)
+{
+        UBSAN_MD_VAR(tc, "descr",
+           "Checks -fsanitize=unreachable");
+}
+
+static void
+test_builtin_unreachable(void)
+{
+       volatile int a = atoi("1");
+       volatile int b = atoi("1");
+
+       if (a == b) {
+               __builtin_unreachable();
+       }
+       // This shall not be reached
+       raise(SIGSEGV);
+}
+
+UBSAN_TC_BODY(builtin_unreachable, tc)
+{
+
+       test_case(test_builtin_unreachable, " calling __builtin_unreachable()");
+}
+
+UBSAN_TC(divrem_overflow_signed_div);
+UBSAN_TC_HEAD(divrem_overflow_signed_div, tc)
+{
+        UBSAN_MD_VAR(tc, "descr",
+           "Checks -fsanitize=signed-integer-overflow");
+}
+
+static void
+test_divrem_overflow_signed_div(void)
+{
+       volatile int a = INT_MIN;
+       volatile int b = atoi("-1");
+
+       raise((a / b) ? SIGSEGV : SIGBUS); // SIGFPE will be triggered before exiting
+}
+
+UBSAN_TC_BODY(divrem_overflow_signed_div, tc)
+{
+
+       test_case(test_divrem_overflow_signed_div, " signed integer overflow: ");
+}
+
+UBSAN_TC(divrem_overflow_signed_mod);
+UBSAN_TC_HEAD(divrem_overflow_signed_mod, tc)
+{
+        UBSAN_MD_VAR(tc, "descr",
+           "Checks -fsanitize=signed-integer-overflow");
+}
+
+static void
+test_divrem_overflow_signed_mod(void)
+{
+       volatile int a = INT_MIN;
+       volatile int b = atoi("-1");
+
+       raise((a % b) ? SIGSEGV : SIGBUS);
+}
+
+UBSAN_TC_BODY(divrem_overflow_signed_mod, tc)
+{
+
+       test_case(test_divrem_overflow_signed_mod, " signed integer overflow: ");
+}
+
+#if defined(__cplusplus) && defined(__clang__) && defined(__x86_64__)
+UBSAN_TC(function_type_mismatch);
+UBSAN_TC_HEAD(function_type_mismatch, tc)
+{
+        UBSAN_MD_VAR(tc, "descr",
+           "Checks -fsanitize=function");
+}
+
+static int
+fun_type_mismatch(void)
+{
+
+       return 0;
+}
+
+static void
+test_function_type_mismatch(void)
+{
+
+       raise(reinterpret_cast<int(*)(int)>
+           (reinterpret_cast<uintptr_t>(fun_type_mismatch))(1) ? SIGSEGV : SIGBUS);
+}
+
+UBSAN_TC_BODY(function_type_mismatch, tc)
+{
+
+       test_case(test_function_type_mismatch, " call to function ");
+}
+#endif
+
+#ifdef __clang__
+#define INVALID_BUILTIN(type)                          \
+UBSAN_TC(invalid_builtin_##type);                      \
+UBSAN_TC_HEAD(invalid_builtin_##type, tc)              \
+{                                                      \
+        UBSAN_MD_VAR(tc, "descr",                      \
+           "Checks -fsanitize=builtin");               \
+}                                                      \
+                                                       \
+static void                                            \



Home | Main Index | Thread Index | Old Index