提交 5bcc3aa7 编写于 作者: M maweiye

Add native test cases

Signed-off-by: Nmaweiye <maweiye@huawei.com>
上级 8ca9d67d
CMAKE_MINIMUM_REQUIRED(VERSION 3.15)
project(arm-neon-test)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/output)
enable_language(C CXX ASM)
set(BUILD_FLAGS
-mfloat-abi=hard
-march=armv7a)
function(NEON_TEST WITH_FP16)
add_executable(arm-neon-fp16 src/arm-neon-fp16.cpp)
if(WITH_FP16)
list(APPEND BUILD_FLAGS -mfpu=neon-fp16)
else()
list(APPEND BUILD_FLAGS -mfpu=neon)
endif()
target_compile_options(arm-neon-fp16 PUBLIC "${BUILD_FLAGS}")
endfunction()
function(ASM_TEST)
add_library(asm-test OBJECT src/asm-test.s)
target_compile_options(asm-test PUBLIC "${BUILD_FLAGS}")
endfunction()
NEON_TEST(ON)
# NEON_TEST(OFF)
ASM_TEST()
\ No newline at end of file
#!/usr/bin/env python3
import os
import sys
import shutil
arg_path=os.path.join(os.path.abspath(os.path.dirname(os.getcwd())),'script')
sys.path.append(arg_path)
from config_args import linux_args
def build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
os.mkdir("build")
os.chdir("build")
build_cmd = "cmake -G 'Ninja' " + (" ".join(linux_args))+ " .."
print(build_cmd)
os.system(build_cmd)
os.system("ninja -f build.ninja")
# os.chdir(os.path.abspath(os.path.dirname(os.getcwd())))
# if os.path.exists("build") and os.path.isdir("build"):
# shutil.rmtree("build")
if __name__ == '__main__':
build()
#include <arm_neon.h>
uint32x2_t test_vadd_u32(uint32x2_t a, uint32x2_t b) {
return vadd_u32(a,b);
}
float16x8_t test_vld1q_f16(float16_t const *a) {
return vld1q_f16(a);
}
int main(){}
\ No newline at end of file
LDRD r4,[r8,#28]
blx r0
\ No newline at end of file
cmake_minimum_required(VERSION 3.5)
# project name
project (asan_test)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../exe)
# Add executable
file(GLOB TESTCASES src/*.cpp)
foreach(srcfile ${TESTCASES})
get_filename_component(testname ${srcfile} NAME_WE)
add_executable( ${testname} ${srcfile})
endforeach(add_subdirectory(src/init-order))
add_subdirectory(src/init-order)
#!/usr/bin/python
import os
import subprocess
import sys
import shutil
pre_dir = os.path.abspath(os.path.dirname(os.getcwd()))
config_dir = os.path.join(os.path.dirname(pre_dir),'script')
sys.path.append(config_dir)
from config_args import linux_args
# Add asan compile options
asan_flags = [ "-DCMAKE_CXX_FLAGS=-fsanitize=address" ]
build_args=[]
build_args.extend(linux_args)
build_args.extend(asan_flags)
def rm_build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
def build_linux():
rm_build()
os.mkdir("build")
# os.chdir("build")
build_cmd = "cmake " + (" ".join(build_args))+ " .."
print(build_cmd)
res1 = subprocess.Popen(build_cmd,cwd='build',shell=True).wait()
# print(res1)
res2 = subprocess.Popen('make',cwd='build',shell=True).wait()
# print(res2)
rm_build()
if __name__ == '__main__':
build_linux()
//CHECK: AddressSanitizer:Global-buffer-overflow
int array[100];
int main(int argc, char *argv[]) {
return array[100];
}
\ No newline at end of file
// BUILD: clang -fsanitize=address %s -o %t
// CHECK: AddressSanitizer:Heap-buffer-overflow
int main(int argc, char *argv[])
{
int *array = new int[100];
int res = array[100];
delete[] array;
return res;
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.5)
add_executable(IO-a a.cpp b.cpp)
add_executable(IO-b b.cpp a.cpp)
\ No newline at end of file
// BUILD: clang -fsanitize=address a.cpp b.cpp -o IO-a
// BUILD: clang -fsanitize=address b.cpp a.cpp -o IO-b (noexpect)
// ASAN_OPTIONS=check_initialization_order=true IO-a
// ASAN_OPTIONS=check_initialization_order=true IO-b (noexpect)
// CHECK: AddressSanitizer: Initialization-order-fiasco
#include <cstdio>
extern int extern_global;
int __attribute__((noinline)) read_extern_global()
{
return extern_global;
}
int x = read_extern_global() + 1;
int main()
{
printf("%d\n", x);
return 0;
}
// BUILD: clang -fsanitize=address a.cpp b.cpp -o IO-a
// BUILD: clang -fsanitize=address b.cpp a.cpp -o IO-b (noexpect)
// ASAN_OPTIONS=check_initialization_order=true IO-b
// CHECK: AddressSanitizer: initialization-order-fiasco
int foo() { return 42; }
int extern_global = foo();
\ No newline at end of file
// BUILD: clang -fsanitize=address %s -o %t
// CHECK: AddressSanitizer:Memory-leaks
#include <cstdlib>
void* p;
int main(int argc, char *argv[]) {
p = malloc(7);
p = 0;
return 0;
}
\ No newline at end of file
// Tests trace pc guard coverage collection.
// REQUIRES: has_sancovcc,stable-runtime
// UNSUPPORTED: ubsan,i386-darwin
// XFAIL: tsan,powerpc64,s390x,mips
// XFAIL: android && asan
// RUN: DIR=%t_workdir
// RUN: rm -rf $DIR
// RUN: mkdir -p $DIR
// RUN: cd $DIR
// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -o %t
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov %t 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
// RUN: %env_tool_opts=coverage=0 %t 2>&1 | FileCheck --check-prefix=CHECK-NOCOV %s
// RUN: rm -rf $DIR
// Make some room to stabilize line numbers
#include <stdio.h>
int foo() {
fprintf(stderr, "foo\n");
return 1;
}
int main() {
fprintf(stderr, "main\n");
foo();
foo();
}
// CHECK: main
// CHECK-NEXT: foo
// CHECK-NEXT: foo
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov: 2 PCs written
//
// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cpp:[[@LINE-16]] foo
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cpp:[[@LINE-12]] main
//
// CHECK-NOCOV-NOT: SanitizerCoverage
// BUILD: clang -fsanitize=address %s -o %t
// CHECK: AddressSanitizer:Stack-buffer-overflow
int main(int argc, char *argv[])
{
int array[100];
return array[100];
}
\ No newline at end of file
// BUILD: clang -fsanitize=address %s -o %t
// CHECK: AddressSanitizer:Use-after-free
#include <cstdlib>
volatile void *buf;
volatile char sink;
int main(int argc, char *argv[]) {
void *ptr = malloc(1);
buf = ptr;
free(ptr);
sink = *static_cast<char*>(ptr);
return 0;
}
\ No newline at end of file
// BUILD: clang -fsanitize=address %s -o %t
// ASAN_OPTIONS=detect_stack_use_after_return=true %t
// CHECK: AddressSanitizer:Use-after-return
int *ptr;
void FunctionThatEscapesLocalObject() {
int local[100];
ptr = &local[0];
}
int main(int argc, char **argv) {
FunctionThatEscapesLocalObject();
return ptr[argc];
}
\ No newline at end of file
// BUILD: clang -fsanitize=address %s -o %t
// CHECK: AddressSanitizer:Use-after-scope
volatile int *p = 0;
int main() {
{
int x = 0;
p = &x;
}
*p = 5;
return 0;
}
\ No newline at end of file
#!/bin/env python
import os
import shutil
import stat
import subprocess
target_list = [
"asan",
# "cfi", #no expection
# "fuzz", #undefined symbol, not build
"scudo",
"ubsan",
# "shadowcallstack", # __aarch64__
# "trace-pc-guard", # build_error
]
def check_out_dir():
if os.path.exists("output") and os.path.isdir("output"):
# print("Directory 'out' exist.")
shutil.rmtree("output")
else:
os.mkdir("output")
shutil.copy("runtest.sh",os.path.join(os.getcwd(),"output"))
def copy_output(tar):
print("Start copying output executable...")
tar_out = os.path.join(tar, "exe")
copy_tar_path = os.path.join("output", tar)
ret = os.path.exists(tar_out) and os.path.isdir(tar_out)
if not ret:
print(tar_out + " not exists")
else:
shutil.move(tar_out,copy_tar_path)
def start_build():
check_out_dir()
for target in target_list:
tar_dir = os.path.join(os.getcwd(), target)
build_file = os.path.join(tar_dir, "build.py")
# build_file = 'build.py'
if os.path.exists(build_file) and os.path.isfile(build_file):
if os.access(build_file, os.X_OK):
# print("[Permission Check]" + build_file + " X_OK")
p = subprocess.Popen(build_file, cwd=tar_dir).wait()
# if p == 0:
copy_output(target)
else:
print(build_file + " permission denied.")
break
else:
print(build_file + " not found.")
break
if __name__ == "__main__":
start_build()
cmake_minimum_required(VERSION 3.5)
# project name
project (asan_test)
set(EXECUTABLE_OUTPUT_PATH build/out)
# Add executable
file(GLOB TESTCASES src/*.cpp )
foreach(srcfile IN LISTS ${TESTCASES})
get_filename_component(testname ${srcfile} NAME_WE)
add_executable( ${testname} ${srcfile})
endforeach()
#!/usr/bin/python
import os
import subprocess
import sys
import shutil
pre_dir = os.path.abspath(os.path.dirname(os.getcwd()))
config_dir = os.path.join(os.path.dirname(pre_dir),'script')
sys.path.append(config_dir)
from config_args import linux_args
build_args=[]
build_args.extend(linux_args)
def rm_build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
def build_linux():
rm_build()
os.mkdir("build")
build_cmd = "cmake " + (" ".join(build_args))+ " .."
print(build_cmd)
subprocess.Popen(build_cmd,cwd='build',shell=True).wait()
subprocess.Popen('make',cwd='build',shell=True).wait()
rm_build()
if __name__ == '__main__':
build_linux()
// -mretpoline does not work yet on Darwin.
// XFAIL: darwin
// RUN: %clangxx_cfi -o %t %s
// RUN: %run %t
// RUN: %clangxx_cfi -mretpoline -o %t2 %s
// RUN: %run %t2
// Tests that the CFI mechanism does not crash the program when making various
// kinds of valid calls involving classes with various different linkages and
// types of inheritance, and both virtual and non-virtual member functions.
#include "utils.h"
struct A {
virtual void f();
void g();
};
void A::f() {}
void A::g() {}
struct A2 : A {
virtual void f();
void g();
};
void A2::f() {}
void A2::g() {}
struct B {
virtual void f() {}
void g() {}
};
struct B2 : B {
virtual void f() {}
void g() {}
};
namespace {
struct C {
virtual void f();
void g();
};
void C::f() {}
void C::g() {}
struct C2 : C {
virtual void f();
void g();
};
void C2::f() {}
void C2::g() {}
struct D {
virtual void f() {}
void g() {}
};
struct D2 : D {
virtual void f() {}
void g() {}
};
}
struct E {
virtual void f() {}
void g() {}
};
struct E2 : virtual E {
virtual void f() {}
void g() {}
};
int main() {
A *a = new A;
break_optimization(a);
a->f();
a->g();
a = new A2;
break_optimization(a);
a->f();
a->g();
B *b = new B;
break_optimization(b);
b->f();
b->g();
b = new B2;
break_optimization(b);
b->f();
b->g();
C *c = new C;
break_optimization(c);
c->f();
c->g();
c = new C2;
break_optimization(c);
c->f();
c->g();
D *d = new D;
break_optimization(d);
d->f();
d->g();
d = new D2;
break_optimization(d);
d->f();
d->g();
E *e = new E;
break_optimization(e);
e->f();
e->g();
e = new E2;
break_optimization(e);
e->f();
e->g();
}
// RUN: %clangxx_cfi %debug_info_flags -fsanitize-stats -o %t %s
// RUN: env SANITIZER_STATS_PATH=%t.stats %run %t
// RUN: sanstats %t.stats | FileCheck %s
// FIXME: We currently emit the wrong debug info under devirtualization.
// UNSUPPORTED: devirt
// FIXME: %t.stats must be transferred from device to host for this to work on Android.
// XFAIL: android
struct ABase {};
struct A : ABase {
virtual void vf() {}
void nvf() {}
};
extern "C" __attribute__((noinline)) void vcall(A *a) {
// CHECK: stats.cpp:[[@LINE+1]] {{_?}}vcall cfi-vcall 37
a->vf();
}
extern "C" __attribute__((noinline)) void nvcall(A *a) {
// CHECK: stats.cpp:[[@LINE+1]] {{_?}}nvcall cfi-nvcall 51
a->nvf();
}
extern "C" __attribute__((noinline)) A *dcast(A *a) {
// CHECK: stats.cpp:[[@LINE+1]] {{_?}}dcast cfi-derived-cast 24
return (A *)(ABase *)a;
}
extern "C" __attribute__((noinline)) A *ucast(A *a) {
// CHECK: stats.cpp:[[@LINE+1]] {{_?}}ucast cfi-unrelated-cast 81
return (A *)(char *)a;
}
extern "C" __attribute__((noinline)) void unreachable(A *a) {
// CHECK-NOT: unreachable
a->vf();
}
int main() {
A a;
for (unsigned i = 0; i != 37; ++i)
vcall(&a);
for (unsigned i = 0; i != 51; ++i)
nvcall(&a);
for (unsigned i = 0; i != 24; ++i)
dcast(&a);
for (unsigned i = 0; i != 81; ++i)
ucast(&a);
for (unsigned i = 0; i != 0; ++i)
unreachable(&a);
}
// RUN: %clangxx -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
// RUN: %clangxx_cfi_diag -g %s -o %t %ld_flags_rpath_exe
// RUN: %run %t 2>&1 | FileCheck %s
// REQUIRES: cxxabi
// UNSUPPORTED: windows-msvc
#include <stdio.h>
#include <string.h>
struct A {
virtual void f();
};
void *create_B();
#ifdef SHARED_LIB
struct B {
virtual void f();
};
void B::f() {}
void *create_B() {
return (void *)(new B());
}
#else
void A::f() {}
int main(int argc, char *argv[]) {
void *p = create_B();
// CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type
// CHECK: invalid vtable
// CHECK: check failed in {{.*}}, vtable located in {{.*}}libtarget_uninstrumented.cpp.dynamic.so
A *a = (A *)p;
memset(p, 0, sizeof(A));
// CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type
// CHECK: invalid vtable
// CHECK: check failed in {{.*}}, vtable located in (unknown)
a = (A *)p;
// CHECK: done
fprintf(stderr, "done %p\n", a);
}
#endif
// RUN: %clangxx_cfi_diag -o %t %s
// RUN: %run %t 2>&1 | FileCheck %s
// This test checks that we don't generate two type checks,
// if two virtual calls are in the same function.
// UNSUPPORTED: windows-msvc
// REQUIRES: cxxabi
// TODO(krasin): implement the optimization to not emit two type checks.
// XFAIL: *
#include <stdio.h>
class Base {
public:
virtual void Foo() {
fprintf(stderr, "Base::Foo\n");
}
virtual void Bar() {
fprintf(stderr, "Base::Bar\n");
}
};
class Derived : public Base {
public:
void Foo() override {
fprintf(stderr, "Derived::Foo\n");
}
void Bar() override {
printf("Derived::Bar\n");
}
};
__attribute__((noinline)) void print(Base* ptr) {
ptr->Foo();
// Corrupt the vtable pointer. We expect that the optimization will
// check vtable before the first vcall then store it in a local
// variable, and reuse it for the second vcall. With no optimization,
// CFI will complain about the virtual table being corrupted.
*reinterpret_cast<void**>(ptr) = 0;
ptr->Bar();
}
int main() {
Base b;
Derived d;
// CHECK: Base::Foo
// CHECK: Base::Bar
print(&b);
// CHECK: Derived::Foo
// CHECK-NOT: runtime error
// CHECK: Derived::Bar
print(&d);
return 0;
}
cmake_minimum_required(VERSION 3.5)
# project name
project (fuzz_test)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../exe)
set(CMAKE_EXE_LINKER_FLAGS -fsanitize=fuzzer)
# Add executable
file(GLOB TESTCASES src/*.cpp)
foreach(srcfile ${TESTCASES})
get_filename_component(testname ${srcfile} NAME_WE)
add_executable(${testname} ${srcfile})
# target_compile_options(${testname} PRIVATE -fsanitize=fuzzer)
endforeach()
\ No newline at end of file
#!/bin/env python
import os
import sys
import subprocess
import shutil
pre_dir = os.path.abspath(os.path.dirname(os.getcwd()))
config_dir = os.path.join(os.path.dirname(pre_dir),'script')
sys.path.append(config_dir)
from config_args import linux_args
# Add libFuzz compile options
fuzz_flags = [ "-DCMAKE_EXE_LINKER_FLAGS=-fsanitize=fuzzer" ]
build_args=[]
build_args.extend(linux_args)
# build_args.extend(fuzz_flags)
def rm_build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
def build_linux():
rm_build()
os.mkdir("build")
build_cmd = "cmake " + (" ".join(build_args))+ " .."
print(build_cmd)
subprocess.Popen(build_cmd,cwd='build',shell=True).wait()
subprocess.Popen('make',cwd='build',shell=True).wait()
rm_build()
if __name__ == '__main__':
build_linux()
\ No newline at end of file
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <iostream>
extern "C" {
__attribute__((noinline))
void FunctionC(const uint8_t *Data, size_t Size) {
if (Size > 3 && Data[3] == 'Z') {
static bool PrintedOnce = false;
if (!PrintedOnce) {
std::cout << "BINGO\n";
PrintedOnce = true;
}
}
}
__attribute__((noinline))
void FunctionB(const uint8_t *Data, size_t Size) {
if (Size > 2 && Data[2] == 'Z')
FunctionC(Data, Size);
}
__attribute__((noinline))
void FunctionA(const uint8_t *Data, size_t Size) {
if (Size > 1 && Data[1] == 'U')
FunctionB(Data, Size);
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size > 0 && Data[0] == 'F')
FunctionA(Data, Size);
return 0;
}
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <ostream>
static volatile int Sink;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
assert(Data);
if (Size > 0 && Data[0] == 'H') {
Sink = 1;
if (Size > 1 && Data[1] == 'i') {
Sink = 2;
if (Size > 2 && Data[2] == '!') {
std::cout << "BINGO; Found the target, exiting\n" << std::flush;
exit(0);
}
}
}
return 0;
}
#! /bin/sh
touch REPORT
rm REPORT
chmod +x sanitize/asan/*
num_s=0
num_f=0
num_skip=0
function skip {
echo skip
let num_skip=$num_skip+1
}
for case in `ls sanitize/asan`
do
echo [Runing test] : sanitize/asan/$case
if [ "$case" = "use-after-return" ]; then
ASAN_OPTIONS=detect_stack_use_after_return=1 sanitize/asan/$case 2>tmp
elif [ "$case" = "IO-a" ] | [ "$case" = "IO-b" ]; then
ASAN_OPTIONS=check_initialization_order=true sanitize/asan/$case 2>tmp
else
ASAN_OPTIONS='' sanitize/asan/$case 2>tmp
fi
# check result
if [ "$case" = "memory-leaks" ];then
grep -nr 'SUMMARY: ' tmp | grep "leaked in"
else
grep -nr 'SUMMARY: ' tmp | grep $case
fi
res=$?
# Specially
if [ res -ne 0 ] && [ "$case" = "IO-b" ];then
echo "$case succeeded."
let num_s=$num_s+1
elif [ res -ne 0 ];then
echo "[ERROR] asan/$case failed." | tee -a REPORT
sanitize/asan/$case >> REPORT
let num_f=$num_f+1
else
echo "$case succeeded."
let num_s=$num_s+1
fi
done
for case in `ls sanitize/scudo`
do
cat /dev/null > tmp
echo [Runing test] : sanitize/scudo/$case
if [ "$case" = "aligned-new" ];then
sanitize/scudo/$case valid 2>tmp
r1=$?
SCUDO_OPTIONS=allocator_may_return_null=1 sanitize/scudo/$case invalid 2>tmp
r2=$?
SCUDO_OPTIONS=allocator_may_return_null=0 sanitize/scudo/$case invalid 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r3=$?
let res=$r1+$r2+$r3
res2=$r1+$r2+$r3
elif [ "$case" = "alignment" ];then
sanitize/scudo/$case pointers 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
res=$?
elif [ "$case" = "dealloc-race" ];then
SCUDO_OPTIONS="QuarantineChunksUpToSize=0" sanitize/scudo/$case 2>tmp
res=$?
elif [ "$case" = "double-free" ];then
sanitize/scudo/$case malloc 2>tmp
grep -nr "ERROR: invalid chunk state" tmp >/dev/null
r1=$?
sanitize/scudo/$case new 2>tmp
grep -nr "ERROR: invalid chunk state" tmp >/dev/null
r2=$?
sanitize/scudo/$case newarray 2>tmp
grep -nr "ERROR: invalid chunk state" tmp >/dev/null
r3=$?
let res=$r1+$r2+$r3
res2=$r1+$r2+$r3
elif [ "$case" = "fsanitize" ];then
skip #build error
continue
elif [ "$case" = "interface" ];then
sanitize/scudo/$case ownership 2>tmp
r1=$?
sanitize/scudo/$case ownership-and-size 2>tmp
r2=$?
sanitize/scudo/$case heap-size 2>tmp
r3=$?
SCUDO_OPTIONS="allocator_may_return_null=1" sanitize/scudo/$case soft-limit 2>tmp
r4=$?
SCUDO_OPTIONS="allocator_may_return_null=1" sanitize/scudo/$case hard-limit 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r5=$?
let res=$r1+$r2+$r3+$r4+$r5
res2=$r1+$r2+$r3+$r4+$r5
elif [ "$case" = "memalign" ];then
skip
continue
# sanitize/scudo/$case valid 2>tmp
# sanitize/scudo/$case invalid 2>tmp
# scudo_opts=allocator_may_return_null=1 sanitize/scudo/$case invalid 2>tmp
# sanitize/scudo/$case double-free 2>tmp
# scudo_opts=DeallocationTypeMismatch=1 sanitize/scudo/$case realloc 2>tmp
# scudo_opts=DeallocationTypeMismatch=0 sanitize/scudo/$case realloc 2>tmp
elif [ "$case" = "mismatch" ];then
SCUDO_OPTIONS=DeallocationTypeMismatch=1 sanitize/scudo/$case mallocdel 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r1=$?
SCUDO_OPTIONS=DeallocationTypeMismatch=0 sanitize/scudo/$case mallocdel 2>tmp
r2=$?
SCUDO_OPTIONS=DeallocationTypeMismatch=1 sanitize/scudo/$case newfree 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r3=$?
SCUDO_OPTIONS=DeallocationTypeMismatch=0 sanitize/scudo/$case newfree 2>tmp
r4=$?
let res=$r1+$r2+$r3+$r4
res2=$r1+$r2+$r3+$r4
elif [ "$case" = "preinit" ];then
skip # UNSUPPORTED
continue
elif [ "$case" = "options" ];then
sanitize/scudo/$case 2>tmp
r1=$?
SCUDO_OPTIONS=DeallocationTypeMismatch=0 sanitize/scudo/$case 2>tmp
r2=$?
SCUDO_OPTIONS=DeallocationTypeMismatch=1 sanitize/scudo/$case 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r3=$?
let res=$r1+$r2+$r3
res2=$r1+$r2+$r3
elif [ "$case" = "preload" ];then
skip
continue
# env LD_PRELOAD=%shared_libscudo not %run %t 2>tmp | FileCheck %s
# env LD_PRELOAD=%shared_minlibscudo not %run %t 2>tmp | FileCheck %s
elif [ "$case" = "realloc" ];then
skip
continue
# sanitize/scudo/$case pointers 2>tmp
# sanitize/scudo/$case contents 2>tmp
# sanitize/scudo/$case usablesize 2>tmp
elif [ "$case" = "rss" ];then
sanitize/scudo/$case 2>tmp
r1=$?
SCUDO_OPTIONS="soft_rss_limit_mb=128" sanitize/scudo/$case 2>tmp
r2=$?
SCUDO_OPTIONS="hard_rss_limit_mb=128" sanitize/scudo/$case 2>tmp
r3=$?
SCUDO_OPTIONS="soft_rss_limit_mb=32:allocator_may_return_null=0" sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r4=$? #not
SCUDO_OPTIONS="soft_rss_limit_mb=32:allocator_may_return_null=1" sanitize/scudo/$case 2>tmp
r5=$?
SCUDO_OPTIONS="soft_rss_limit_mb=32:allocator_may_return_null=0:can_use_proc_maps_statm=0" sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r6=$? #not
SCUDO_OPTIONS="soft_rss_limit_mb=32:allocator_may_return_null=1:can_use_proc_maps_statm=0" sanitize/scudo/$case 2>tmp
r7=$?
SCUDO_OPTIONS="hard_rss_limit_mb=32:allocator_may_return_null=0" sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r8=$? #not
SCUDO_OPTIONS="hard_rss_limit_mb=32:allocator_may_return_null=1" sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r9=$? #not
SCUDO_OPTIONS="hard_rss_limit_mb=32:allocator_may_return_null=0:can_use_proc_maps_statm=0" sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r10=$? #not
SCUDO_OPTIONS="hard_rss_limit_mb=32:allocator_may_return_null=1:can_use_proc_maps_statm=0" sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r11=$? #not
let res=$r1+$r2+$r3+$r4+$r5+$r6+$r7+$r8+$r9+$r10+$r11
res2=$r1+$r2+$r3+$r4+$r5+$r6+$r7+$r8+$r9+$r10+$r11
elif [ "$case" = "sized-delete" ];then
SCUDO_OPTIONS=DeleteSizeMismatch=1 sanitize/scudo/$case gooddel 2>tmp
r1=$?
SCUDO_OPTIONS=DeleteSizeMismatch=1 sanitize/scudo/$case baddel 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r2=$?
SCUDO_OPTIONS=DeleteSizeMismatch=0 sanitize/scudo/$case baddel 2>tmp
r3=$?
SCUDO_OPTIONS=DeleteSizeMismatch=1 sanitize/scudo/$case gooddelarr 2>tmp
r4=$?
SCUDO_OPTIONS=DeleteSizeMismatch=1 sanitize/scudo/$case baddelarr 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r5=$?
SCUDO_OPTIONS=DeleteSizeMismatch=0 sanitize/scudo/$case baddelarr 2>tmp
r6=$?
let res=$r1+$r2+$r3+$r4+$r5+$r6
res2=$r1+$r2+$r3+$r4+$r5+$r6
elif [ "$case" = "sizes" ];then
SCUDO_OPTIONS=allocator_may_return_null=0 sanitize/scudo/$case malloc 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r1=$?
SCUDO_OPTIONS=allocator_may_return_null=1 sanitize/scudo/$case malloc 2>tmp
r2=$?
SCUDO_OPTIONS=allocator_may_return_null=0 sanitize/scudo/$case calloc 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r3=$?
SCUDO_OPTIONS=allocator_may_return_null=1 sanitize/scudo/$case calloc 2>tmp
r4=$?
SCUDO_OPTIONS=allocator_may_return_null=0 sanitize/scudo/$case new 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r5=$?
SCUDO_OPTIONS=allocator_may_return_null=1 sanitize/scudo/$case new 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r6=$?
SCUDO_OPTIONS=allocator_may_return_null=0 sanitize/scudo/$case new-nothrow 2>tmp #not
grep -nr 'Scudo ERROR: ' tmp >/dev/null
r7=$?
SCUDO_OPTIONS=allocator_may_return_null=1 sanitize/scudo/$case new-nothrow 2>tmp
r8=$?
sanitize/scudo/$case usable 2>tmp
r9=$?
let res=$r1+$r2+$r3+$r4+$r5+$r6+$r7+$r8+$r9
res2=$r1+$r2+$r3+$r4+$r5+$r6+$r7+$r8+$r9
else
sanitize/scudo/$case 2>tmp
grep -nr 'Scudo ERROR: ' tmp >/dev/null
res=$?
fi
if [ res -ne 0 ];then
# echo res
echo "[ERROR] scudo/$case failed." | tee -a REPORT
let num_f=$num_f+1
continue
else
echo "scudo/$case succeeded."
let num_s=$num_s+1
continue
fi
echo
done
for case in `ls sanitize/ubsan`
do
echo [Runing test] : sanitize/ubsan/$case
sanitize/ubsan/$case 2>tmp
# check result
grep -nr 'SUMMARY: UndefinedBehaviorSanitizer' tmp
res=$?
if [ res -ne 0 ];then
echo "[ERROR] ubsan/$case failed." | tee -a REPORT
sanitize/ubsan/$case >> REPORT
let num_f=$num_f+1
else
echo "ubsan/$case succeeded."
let num_s=$num_s+1
fi
done
let sum_case=$num_s+$num_f+$num_skip
echo "All:$sum_case Succeeded:$num_s Failed:$num_f Skiped:$num_skip"
if [ $num_f -eq 0 ];then
echo "No test failed, report not create."
fi
rm tmp
cmake_minimum_required(VERSION 3.5)
# project name
project (scudo_test)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../exe)
# Add executable
file(GLOB TESTCASES src/*.cpp )
foreach(srcfile ${TESTCASES})
get_filename_component(testname ${srcfile} NAME_WE)
add_executable(${testname} ${srcfile})
endforeach()
file(GLOB TESTCASES_C src/*.c )
foreach(srcfile_c ${TESTCASES_C})
get_filename_component(testname_c ${srcfile_c} NAME_WE)
add_executable(${testname_c} ${srcfile_c})
# include_directories("${PROJECT_SOURCE_DIR}/include")
endforeach()
\ No newline at end of file
#!/usr/bin/python
import os
import subprocess
import sys
import shutil
pre_dir = os.path.abspath(os.path.dirname(os.getcwd()))
config_dir = os.path.join(os.path.dirname(pre_dir),'script')
sys.path.append(config_dir)
from config_args import linux_args
# Add asan compile options
scudo_flags = [ "-DCMAKE_CXX_FLAGS=-fsanitize=scudo" ]
build_args=[]
build_args.extend(linux_args)
build_args.extend(scudo_flags)
def rm_build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
def build_linux():
rm_build()
os.mkdir("build")
build_cmd = "cmake " + (" ".join(build_args))+ " .."
print(build_cmd)
res1 = subprocess.Popen(build_cmd,cwd='build',shell=True).wait()
# print(res1)
res2 = subprocess.Popen('make',cwd='build',shell=True).wait()
# print(res2)
rm_build()
if __name__ == '__main__':
build_linux()
// RUN: %clangxx_scudo -std=c++1z -faligned-allocation %s -o %t
// RUN: %run %t valid 2>&1
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t invalid 2>&1 | FileCheck %s
// Tests that the C++17 aligned new/delete operators are working as expected.
// Currently we do not check the consistency of the alignment on deallocation,
// so this just tests that the APIs work.
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
// Define all new/delete to not depend on the version provided by the platform.
namespace std {
struct nothrow_t {};
static const nothrow_t nothrow;
enum class align_val_t : size_t {};
} // namespace std
void *operator new(size_t);
void *operator new[](size_t);
void *operator new(size_t, std::nothrow_t const &);
void *operator new[](size_t, std::nothrow_t const &);
void *operator new(size_t, std::align_val_t);
void *operator new[](size_t, std::align_val_t);
void *operator new(size_t, std::align_val_t, std::nothrow_t const &);
void *operator new[](size_t, std::align_val_t, std::nothrow_t const &);
void operator delete(void *) throw();
void operator delete[](void *) throw();
void operator delete(void *, std::nothrow_t const &);
void operator delete[](void *, std::nothrow_t const &);
void operator delete(void *, size_t) throw();
void operator delete[](void *, size_t) throw();
void operator delete(void *, std::align_val_t) throw();
void operator delete[](void *, std::align_val_t) throw();
void operator delete(void *, std::align_val_t, std::nothrow_t const &);
void operator delete[](void *, std::align_val_t, std::nothrow_t const &);
void operator delete(void *, size_t, std::align_val_t) throw();
void operator delete[](void *, size_t, std::align_val_t) throw();
template <typename T>
inline T *break_optimization(T *arg) {
__asm__ __volatile__(""
:
: "r"(arg)
: "memory");
return arg;
}
struct S12 {
int a, b, c;
};
struct alignas(128) S12_128 {
int a, b, c;
};
struct alignas(256) S12_256 {
int a, b, c;
};
struct alignas(512) S1024_512 {
char a[1024];
};
struct alignas(1024) S1024_1024 {
char a[1024];
};
int main(int argc, char **argv) {
assert(argc == 2);
if (!strcmp(argv[1], "valid")) {
// Standard use case.
delete break_optimization(new S12);
delete break_optimization(new S12_128);
delete[] break_optimization(new S12_128[4]);
delete break_optimization(new S12_256);
delete break_optimization(new S1024_512);
delete[] break_optimization(new S1024_512[4]);
delete break_optimization(new S1024_1024);
// Call directly the aligned versions of the operators.
const size_t alignment = 1U << 8;
void *p = operator new(1, static_cast<std::align_val_t>(alignment));
assert((reinterpret_cast<uintptr_t>(p) & (alignment - 1)) == 0);
operator delete(p, static_cast<std::align_val_t>(alignment));
}
if (!strcmp(argv[1], "invalid")) {
// Alignment must be a power of 2.
const size_t alignment = (1U << 8) - 1;
void *p = operator new(1, static_cast<std::align_val_t>(alignment),
std::nothrow);
// CHECK: Scudo ERROR: invalid allocation alignment
assert(!p);
}
return 0;
}
// RUN: %clang_scudo %s -o %t
// RUN: not %run %t pointers 2>&1 | FileCheck %s
// Tests that a non MinAlignment aligned pointer will trigger the associated
// error on deallocation.
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
assert(argc == 2);
if (!strcmp(argv[1], "pointers")) {
void *p = malloc(1U << 16);
assert(p);
free((void *)((uintptr_t)p | 1));
}
return 0;
}
// CHECK: ERROR: misaligned pointer when deallocating address
// RUN: %clang_scudo %s -O2 -o %t
// RUN: %env_scudo_opts="QuarantineChunksUpToSize=0" %run %t 2>&1
// This test attempts to reproduce a race condition in the deallocation path
// when bypassing the Quarantine. The old behavior was to zero-out the chunk
// header after checking its checksum, state & various other things, but that
// left a window during which 2 (or more) threads could deallocate the same
// chunk, with a net result of having said chunk present in those distinct
// thread caches.
// A passing test means all the children died with an error. The failing
// scenario involves winning a race, so repro can be scarce.
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
const int kNumThreads = 2;
pthread_t tid[kNumThreads];
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char go = 0;
// Frees the pointer passed when signaled to.
void *thread_free(void *p) {
pthread_mutex_lock(&mutex);
while (!go)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
free(p);
return 0;
}
// Allocates a chunk, and attempts to free it "simultaneously" by 2 threads.
void child(void) {
void *p = malloc(16);
for (int i = 0; i < kNumThreads; i++)
pthread_create(&tid[i], 0, thread_free, p);
pthread_mutex_lock(&mutex);
go = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
for (int i = 0; i < kNumThreads; i++)
pthread_join(tid[i], 0);
}
int main(int argc, char **argv) {
const int kChildren = 40;
pid_t pid;
for (int i = 0; i < kChildren; ++i) {
pid = fork();
if (pid < 0) {
exit(1);
} else if (pid == 0) {
child();
exit(0);
} else {
int status;
wait(&status);
// A 0 status means the child didn't die with an error. The race was won.
if (status == 0)
exit(1);
}
}
return 0;
}
// RUN: %clangxx_scudo %s -o %t
// RUN: not %run %t malloc 2>&1 | FileCheck %s
// RUN: not %run %t new 2>&1 | FileCheck %s
// RUN: not %run %t newarray 2>&1 | FileCheck %s
// Tests double-free error on pointers allocated with different allocation
// functions.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
assert(argc == 2);
if (!strcmp(argv[1], "malloc")) {
void *p = malloc(sizeof(int));
assert(p);
free(p);
free(p);
}
if (!strcmp(argv[1], "new")) {
int *p = new int;
assert(p);
delete p;
delete p;
}
if (!strcmp(argv[1], "newarray")) {
int *p = new int[8];
assert(p);
delete[] p;
delete[] p;
}
return 0;
}
// CHECK: ERROR: invalid chunk state
// RUN: %clangxx_scudo %s -lstdc++ -o %t
// RUN: %run %t ownership 2>&1
// RUN: %run %t ownership-and-size 2>&1
// RUN: %run %t heap-size 2>&1
// RUN: %env_scudo_opts="allocator_may_return_null=1" %run %t soft-limit 2>&1
// RUN: %env_scudo_opts="allocator_may_return_null=1" not %run %t hard-limit 2>&1
// Tests that the sanitizer interface functions behave appropriately.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vector>
#include <sanitizer/allocator_interface.h>
#include <sanitizer/scudo_interface.h>
int main(int argc, char **argv) {
assert(argc == 2);
if (!strcmp(argv[1], "ownership")) {
// Ensures that __sanitizer_get_ownership can be called before any other
// allocator function, and that it behaves properly on a pointer not owned
// by us.
assert(!__sanitizer_get_ownership(argv));
}
if (!strcmp(argv[1], "ownership-and-size")) {
// Tests that __sanitizer_get_ownership and __sanitizer_get_allocated_size
// behave properly on chunks allocated by the Primary and Secondary.
void *p;
std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
1 << 16, 1 << 17, 1 << 20, 1 << 24};
for (size_t size : sizes) {
p = malloc(size);
assert(p);
assert(__sanitizer_get_ownership(p));
assert(__sanitizer_get_allocated_size(p) >= size);
free(p);
}
}
if (!strcmp(argv[1], "heap-size")) {
// Ensures that __sanitizer_get_heap_size can be called before any other
// allocator function.
assert(__sanitizer_get_heap_size() >= 0);
}
if (!strcmp(argv[1], "soft-limit")) {
// Verifies that setting the soft RSS limit at runtime works as expected.
std::vector<void *> pointers;
size_t size = 1 << 19; // 512Kb
for (int i = 0; i < 5; i++) {
void *p = malloc(size);
memset(p, 0, size);
pointers.push_back(p);
}
// Set the soft RSS limit to 1Mb.
__scudo_set_rss_limit(1, 0);
usleep(20000);
// The following allocation should return NULL.
void *p = malloc(size);
assert(!p);
// Remove the soft RSS limit.
__scudo_set_rss_limit(0, 0);
// The following allocation should succeed.
p = malloc(size);
assert(p);
free(p);
while (!pointers.empty()) {
free(pointers.back());
pointers.pop_back();
}
}
if (!strcmp(argv[1], "hard-limit")) {
// Verifies that setting the hard RSS limit at runtime works as expected.
std::vector<void *> pointers;
size_t size = 1 << 19; // 512Kb
for (int i = 0; i < 5; i++) {
void *p = malloc(size);
memset(p, 0, size);
pointers.push_back(p);
}
// Set the hard RSS limit to 1Mb
__scudo_set_rss_limit(1, 1);
usleep(20000);
// The following should trigger our death.
void *p = malloc(size);
}
return 0;
}
// RUN: %clang_scudo %s -o %t
// RUN: %run %t valid 2>&1
// RUN: not %run %t invalid 2>&1 | FileCheck --check-prefix=CHECK-align %s
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
// RUN: not %run %t double-free 2>&1 | FileCheck --check-prefix=CHECK-double-free %s
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t realloc 2>&1 | FileCheck --check-prefix=CHECK-realloc %s
// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t realloc 2>&1
// Tests that the various aligned allocation functions work as intended. Also
// tests for the condition where the alignment is not a power of 2.
#include <assert.h>
#include <errno.h>
#include <malloc.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// Sometimes the headers may not have this...
void *aligned_alloc(size_t alignment, size_t size);
int main(int argc, char **argv) {
void *p = NULL;
size_t alignment = 1U << 12;
size_t size = 1U << 12;
int err;
assert(argc == 2);
if (!strcmp(argv[1], "valid")) {
posix_memalign(&p, alignment, size);
assert(p);
assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
p = aligned_alloc(alignment, size);
assert(p);
assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
// Tests various combinations of alignment and sizes
for (int i = (sizeof(void *) == 4) ? 3 : 4; i < 19; i++) {
alignment = 1U << i;
for (int j = 1; j < 33; j++) {
size = 0x800 * j;
for (int k = 0; k < 3; k++) {
p = memalign(alignment, size - (2 * sizeof(void *) * k));
assert(p);
assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
}
}
}
// For larger alignment, reduce the number of allocations to avoid running
// out of potential addresses (on 32-bit).
for (int i = 19; i <= 24; i++) {
alignment = 1U << i;
for (int k = 0; k < 3; k++) {
p = memalign(alignment, 0x1000 - (2 * sizeof(void *) * k));
assert(p);
assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
}
}
}
if (!strcmp(argv[1], "invalid")) {
// Alignment is not a power of 2.
p = memalign(alignment - 1, size);
// CHECK-align: Scudo ERROR: invalid allocation alignment
assert(!p);
// Size is not a multiple of alignment.
p = aligned_alloc(alignment, size >> 1);
assert(!p);
void *p_unchanged = (void *)0x42UL;
p = p_unchanged;
// Alignment is not a power of 2.
err = posix_memalign(&p, 3, size);
assert(p == p_unchanged);
assert(err == EINVAL);
// Alignment is a power of 2, but not a multiple of size(void *).
err = posix_memalign(&p, 2, size);
assert(p == p_unchanged);
assert(err == EINVAL);
}
if (!strcmp(argv[1], "double-free")) {
void *p = NULL;
posix_memalign(&p, 0x100, sizeof(int));
assert(p);
free(p);
free(p);
}
if (!strcmp(argv[1], "realloc")) {
// We cannot reallocate a memalign'd chunk.
void *p = memalign(16, 16);
assert(p);
p = realloc(p, 32);
free(p);
}
return 0;
}
// CHECK-double-free: ERROR: invalid chunk state
// CHECK-realloc: ERROR: allocation type mismatch when reallocating address
// RUN: %clangxx_scudo %s -o %t
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t mallocdel 2>&1
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t newfree 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t newfree 2>&1
// Tests that type mismatches between allocation and deallocation functions are
// caught when the related option is set.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
assert(argc == 2);
if (!strcmp(argv[1], "mallocdel")) {
int *p = (int *)malloc(16);
assert(p);
delete p;
}
if (!strcmp(argv[1], "newfree")) {
int *p = new int;
assert(p);
free((void *)p);
}
return 0;
}
// CHECK-dealloc: ERROR: allocation type mismatch when deallocating address
// CHECK-realloc: ERROR: allocation type mismatch when reallocating address
// RUN: %clangxx_scudo %s -o %t
// RUN: %run %t 2>&1
// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t 2>&1
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
// Tests that the options can be passed using getScudoDefaultOptions, and that
// the environment ones take precedence over them.
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
extern "C" const char *__scudo_default_options() {
return "DeallocationTypeMismatch=0"; // Defaults to true in scudo_flags.inc.
}
int main(int argc, char **argv) {
int *p = (int *)malloc(16);
assert(p);
delete p;
return 0;
}
// CHECK: ERROR: allocation type mismatch when deallocating address
// RUN: %clang_scudo %s -o %t
// RUN: %run %t 2>&1
// Verifies that calling malloc in a preinit_array function succeeds, and that
// the resulting pointer can be freed at program termination.
// On some Android versions, calling mmap() from a preinit function segfaults.
// It looks like __mmap2.S ends up calling a NULL function pointer.
// UNSUPPORTED: android
#include <assert.h>
#include <stdlib.h>
#include <string.h>
static void *global_p = NULL;
void __init(void) {
global_p = malloc(1);
if (!global_p)
exit(1);
}
void __fini(void) {
if (global_p)
free(global_p);
}
int main(int argc, char **argv) {
void *p = malloc(1);
assert(p);
free(p);
return 0;
}
__attribute__((section(".preinit_array"), used)) void (*__local_preinit)(void) = __init;
__attribute__((section(".fini_array"), used)) void (*__local_fini)(void) = __fini;
// Test that the preloaded runtime works without linking the static library.
// RUN: %clang %s -lstdc++ -o %t
// RUN: env LD_PRELOAD=%shared_libscudo not %run %t 2>&1 | FileCheck %s
// RUN: env LD_PRELOAD=%shared_minlibscudo not %run %t 2>&1 | FileCheck %s
// This way of setting LD_PRELOAD does not work with Android test runner.
// REQUIRES: !android
#include <assert.h>
int main(int argc, char *argv[]) {
int *p = new int;
assert(p);
*p = 0;
delete p;
delete p;
return 0;
}
// CHECK: ERROR: invalid chunk state
// RUN: %clangxx_scudo %s -lstdc++ -o %t
// RUN: %run %t pointers 2>&1
// RUN: %run %t contents 2>&1
// RUN: %run %t usablesize 2>&1
// Tests that our reallocation function returns the same pointer when the
// requested size can fit into the previously allocated chunk. Also tests that
// a new chunk is returned if the size is greater, and that the contents of the
// chunk are left unchanged. Finally, checks that realloc copies the usable
// size of the old chunk to the new one (as opposed to the requested size).
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <vector>
#include <sanitizer/allocator_interface.h>
int main(int argc, char **argv) {
void *p, *old_p;
// Those sizes will exercise both allocators (Primary & Secondary).
std::vector<size_t> sizes{1, 16, 1024, 32768, 1 << 16, 1 << 17, 1 << 20};
assert(argc == 2);
if (!strcmp(argv[1], "usablesize")) {
// This tests a sketchy behavior inherited from poorly written libraries
// that have become somewhat standard. When realloc'ing a chunk, the
// copied contents should span the usable size of the chunk, not the
// requested size.
size_t size = 496, usable_size;
p = nullptr;
// Make sure we get a chunk with a usable size actually larger than size.
do {
if (p)
free(p);
size += 16;
p = malloc(size);
usable_size = __sanitizer_get_allocated_size(p);
assert(usable_size >= size);
} while (usable_size == size);
for (int i = 0; i < usable_size; i++)
reinterpret_cast<char *>(p)[i] = 'A';
old_p = p;
// Make sure we get a different chunk so that the data is actually copied.
do {
size *= 2;
p = realloc(p, size);
assert(p);
} while (p == old_p);
// The contents of the new chunk must match the old one up to usable_size.
for (int i = 0; i < usable_size; i++)
assert(reinterpret_cast<char *>(p)[i] == 'A');
free(p);
} else {
for (size_t size : sizes) {
if (!strcmp(argv[1], "pointers")) {
old_p = p = realloc(nullptr, size);
assert(p);
size = __sanitizer_get_allocated_size(p);
// Our realloc implementation will return the same pointer if the size
// requested is lower than or equal to the usable size of the associated
// chunk.
p = realloc(p, size - 1);
assert(p == old_p);
p = realloc(p, size);
assert(p == old_p);
// And a new one if the size is greater.
p = realloc(p, size + 1);
assert(p != old_p);
// A size of 0 will free the chunk and return nullptr.
p = realloc(p, 0);
assert(!p);
old_p = nullptr;
}
if (!strcmp(argv[1], "contents")) {
p = realloc(nullptr, size);
assert(p);
for (int i = 0; i < size; i++)
reinterpret_cast<char *>(p)[i] = 'A';
p = realloc(p, size + 1);
// The contents of the reallocated chunk must match the original one.
for (int i = 0; i < size; i++)
assert(reinterpret_cast<char *>(p)[i] == 'A');
}
}
}
return 0;
}
// CHECK: ERROR: invalid chunk type when reallocating address
// RUN: %clang_scudo %s -o %t
// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
// RUN: %env_scudo_opts="soft_rss_limit_mb=128" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
// RUN: %env_scudo_opts="hard_rss_limit_mb=128" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit
// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=1" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull
// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit
// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=1:can_use_proc_maps_statm=0" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull
// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=1" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=1:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
// Tests that the soft and hard RSS limits work as intended. Without limit or
// with a high limit, the test should pass without any malloc returning NULL or
// the program dying.
// If a limit is specified, it should return some NULL or die depending on
// allocator_may_return_null. This should also work without statm.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static const size_t kNumAllocs = 64;
static const size_t kAllocSize = 1 << 20; // 1MB.
static void *allocs[kNumAllocs];
int main(int argc, char *argv[]) {
int returned_null = 0;
for (int i = 0; i < kNumAllocs; i++) {
// sleep for 100ms every 8 allocations, to allow the RSS check to catch up.
if (i != 0 && (i & 0x7) == 0)
usleep(100000);
allocs[i] = malloc(kAllocSize);
if (allocs[i])
memset(allocs[i], 0xff, kAllocSize); // Dirty the pages.
else
returned_null++;
}
for (int i = 0; i < kNumAllocs; i++)
free(allocs[i]);
if (returned_null == 0)
printf("All malloc calls succeeded\n");
else
printf("%d malloc calls returned NULL\n", returned_null);
return 0;
}
// CHECK-nolimit: All malloc calls succeeded
// CHECK-softlimit: soft RSS limit exhausted
// CHECK-softlimit-NOT: malloc calls
// CHECK-softlimit-returnnull: soft RSS limit exhausted
// CHECK-softlimit-returnnull: malloc calls returned NULL
// CHECK-hardlimit: hard RSS limit exhausted
// CHECK-hardlimit-NOT: malloc calls
// RUN: %clangxx_scudo -fsized-deallocation %s -o %t
// RUN: %env_scudo_opts=DeleteSizeMismatch=1 %run %t gooddel 2>&1
// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddel 2>&1 | FileCheck %s
// RUN: %env_scudo_opts=DeleteSizeMismatch=0 %run %t baddel 2>&1
// RUN: %env_scudo_opts=DeleteSizeMismatch=1 %run %t gooddelarr 2>&1
// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddelarr 2>&1 | FileCheck %s
// RUN: %env_scudo_opts=DeleteSizeMismatch=0 %run %t baddelarr 2>&1
// Ensures that the sized delete operator errors out when the appropriate
// option is passed and the sizes do not match between allocation and
// deallocation functions.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <new>
int main(int argc, char **argv) {
assert(argc == 2);
if (!strcmp(argv[1], "gooddel")) {
long long *p = new long long;
operator delete(p, sizeof(long long));
}
if (!strcmp(argv[1], "baddel")) {
long long *p = new long long;
operator delete(p, 2);
}
if (!strcmp(argv[1], "gooddelarr")) {
char *p = new char[64];
operator delete[](p, 64);
}
if (!strcmp(argv[1], "baddelarr")) {
char *p = new char[63];
operator delete[](p, 64);
}
return 0;
}
// CHECK: ERROR: invalid sized delete when deallocating address
// RUN: %clangxx_scudo %s -lstdc++ -o %t
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-max
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t malloc 2>&1
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-calloc
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t calloc 2>&1
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-max
// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-oom
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-max
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1
// RUN: %run %t usable 2>&1
// Tests for various edge cases related to sizes, notably the maximum size the
// allocator can allocate. Tests that an integer overflow in the parameters of
// calloc is caught.
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <limits>
#include <new>
#include <sanitizer/allocator_interface.h>
int main(int argc, char **argv) {
assert(argc == 2);
#if __LP64__ || defined(_WIN64)
static const size_t kMaxAllowedMallocSize = 1ULL << 40;
static const size_t kChunkHeaderSize = 16;
#else
static const size_t kMaxAllowedMallocSize = 2UL << 30;
static const size_t kChunkHeaderSize = 8;
#endif
if (!strcmp(argv[1], "malloc")) {
void *p = malloc(kMaxAllowedMallocSize);
assert(!p);
p = malloc(kMaxAllowedMallocSize - kChunkHeaderSize);
assert(!p);
} else if (!strcmp(argv[1], "calloc")) {
// Trigger an overflow in calloc.
size_t size = std::numeric_limits<size_t>::max();
void *p = calloc((size / 0x1000) + 1, 0x1000);
assert(!p);
} else if (!strcmp(argv[1], "new")) {
void *p = operator new(kMaxAllowedMallocSize);
assert(!p);
} else if (!strcmp(argv[1], "new-nothrow")) {
void *p = operator new(kMaxAllowedMallocSize, std::nothrow);
assert(!p);
} else if (!strcmp(argv[1], "usable")) {
// Playing with the actual usable size of a chunk.
void *p = malloc(1007);
assert(p);
size_t size = __sanitizer_get_allocated_size(p);
assert(size >= 1007);
memset(p, 'A', size);
p = realloc(p, 2014);
assert(p);
size = __sanitizer_get_allocated_size(p);
assert(size >= 2014);
memset(p, 'B', size);
free(p);
} else {
assert(0);
}
return 0;
}
// CHECK-max: {{Scudo ERROR: requested allocation size .* exceeds maximum supported size}}
// CHECK-oom: Scudo ERROR: allocator is out of memory
// CHECK-calloc: Scudo ERROR: calloc parameters overflow
// RUN: %clang_scudo %s -o %t
// RUN: %run %t 2>&1
#include <locale.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
// Some of glibc's own thread local data is destroyed after a user's thread
// local destructors are called, via __libc_thread_freeres. This might involve
// calling free, as is the case for strerror_thread_freeres.
// If there is no prior heap operation in the thread, this free would end up
// initializing some thread specific data that would never be destroyed
// properly, while still being deallocated when the TLS goes away. As a result,
// a program could SEGV, usually in
// __sanitizer::AllocatorGlobalStats::Unregister, where one of the doubly
// linked list links would refer to a now unmapped memory area.
// This test reproduces those circumstances. Success means executing without
// a segmentation fault.
const int kNumThreads = 16;
pthread_t tid[kNumThreads];
void *thread_func(void *arg) {
uintptr_t i = (uintptr_t)arg;
if ((i & 1) == 0)
free(malloc(16));
// Calling strerror_l allows for strerror_thread_freeres to be called.
strerror_l(0, LC_GLOBAL_LOCALE);
return 0;
}
int main(int argc, char **argv) {
for (uintptr_t j = 0; j < 8; j++) {
for (uintptr_t i = 0; i < kNumThreads; i++)
pthread_create(&tid[i], 0, thread_func, (void *)i);
for (uintptr_t i = 0; i < kNumThreads; i++)
pthread_join(tid[i], 0);
}
return 0;
}
cmake_minimum_required(VERSION 3.5)
# project name
project (asan_test)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../exe)
# Add executable
file(GLOB TESTCASES src/*.cpp)
foreach(srcfile ${TESTCASES})
get_filename_component(testname ${srcfile} NAME_WE)
add_executable( ${testname} ${srcfile})
endforeach(add_subdirectory(src/init-order))
#!/usr/bin/python
import os
import subprocess
import sys
import shutil
pre_dir = os.path.abspath(os.path.dirname(os.getcwd()))
config_dir = os.path.join(os.path.dirname(pre_dir),'script')
sys.path.append(config_dir)
from config_args import linux_args
# Add asan compile options
asan_flags = [ "-DCMAKE_CXX_FLAGS=-fsanitize-coverage=trace-pc-guard,indirect-calls" ]
build_args=[]
build_args.extend(linux_args)
build_args.extend(asan_flags)
def rm_build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
def build_linux():
rm_build()
os.mkdir("build")
build_cmd = "cmake " + (" ".join(build_args))+ " .."
print(build_cmd)
res1 = subprocess.Popen(build_cmd,cwd='build',shell=True).wait()
# print(res1)
res2 = subprocess.Popen('make',cwd='build',shell=True).wait()
# print(res2)
rm_build()
if __name__ == '__main__':
build_linux()
// trace-pc-guard-example.cc
void foo() { }
int main(int argc, char **argv) {
if (argc > 1) foo();
}
// Tests trace pc guard coverage collection.
//
// REQUIRES: x86_64-linux
// XFAIL: tsan
//
// RUN: DIR=%t_workdir
// RUN: rm -rf $DIR
// RUN: mkdir -p $DIR
// RUN: cd $DIR
// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -o %t
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
// RUN: rm -rf $DIR
#include <stdio.h>
int foo() {
fprintf(stderr, "foo\n");
return 1;
}
int main() {
fprintf(stderr, "main\n");
foo();
foo();
}
// CHECK: main
// CHECK: SanitizerCoverage: ./sanitizer_coverage_symbolize.{{.*}}.sancov: 2 PCs written
// Tests trace pc guard coverage collection.
// REQUIRES: has_sancovcc,stable-runtime
// UNSUPPORTED: ubsan
// XFAIL: tsan,darwin,powerpc64,s390x,mips
// XFAIL: android && asan
// RUN: DIR=%t_workdir
// RUN: CLANG_ARGS="-O0 -fsanitize-coverage=trace-pc-guard"
// RUN: rm -rf $DIR
// RUN: mkdir -p $DIR
// RUN: cd $DIR
// RUN: %clangxx -DSHARED1 $CLANG_ARGS -shared %s -o %t_1.so -fPIC
// RUN: %clangxx -DSHARED2 $CLANG_ARGS -shared %s -o %t_2.so -fPIC
// RUN: %clangxx -DMAIN $CLANG_ARGS %s -o %t %t_1.so %t_2.so
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov \
// RUN: %t %t_1.so %t_2.so 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
// RUN: rm -rf $DIR
#include <stdio.h>
extern "C" {
int bar();
int baz();
}
#ifdef MAIN
int foo() {
fprintf(stderr, "foo\n");
return 1;
}
int main() {
fprintf(stderr, "main\n");
foo();
bar();
baz();
}
#endif // MAIN
extern "C" {
#ifdef SHARED1
int bar() {
fprintf(stderr, "bar\n");
return 1;
}
#endif
#ifdef SHARED2
int baz() {
fprintf(stderr, "baz\n");
return 1;
}
#endif
} // extern "C"
// CHECK: main
// CHECK-NEXT: foo
// CHECK-NEXT: bar
// CHECK-NEXT: baz
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov: 2 PCs written
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov: 1 PCs written
// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov: 1 PCs written
//
// CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found.
// CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found.
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cpp:[[@LINE-42]] foo
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cpp:[[@LINE-38]] main
// Tests trace pc guard coverage collection.
//
// REQUIRES: has_sancovcc,stable-runtime,x86_64-linux
//
// RUN: DIR=%t_workdir
// RUN: CLANG_ARGS="-O0 -fsanitize-coverage=trace-pc-guard"
// RUN: rm -rf $DIR
// RUN: mkdir -p $DIR
// RUN: cd $DIR
// RUN: %clangxx -DSHARED1 $CLANG_ARGS -shared %s -o %t_1.so -fPIC
// RUN: %clangxx -DSTATIC1 $CLANG_ARGS %s -c -o %t_2.o
// RUN: %clangxx -DMAIN $CLANG_ARGS %s -o %t %t_1.so %t_2.o
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
// RUN: rm -rf $DIR
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
extern "C" {
int bar();
int baz();
}
#ifdef MAIN
extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
fprintf(stderr, "__sanitizer_cov_trace_pc_guard_init\n");
}
extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { }
int foo() {
fprintf(stderr, "foo\n");
return 1;
}
int main() {
fprintf(stderr, "main\n");
foo();
bar();
baz();
}
#endif // MAIN
extern "C" {
#ifdef SHARED1
int bar() {
fprintf(stderr, "bar\n");
return 1;
}
#endif
#ifdef STATIC1
int baz() {
fprintf(stderr, "baz\n");
return 1;
}
#endif
} // extern "C"
// Init is called once per DSO.
// CHECK: __sanitizer_cov_trace_pc_guard_init
// CHECK-NEXT: __sanitizer_cov_trace_pc_guard_init
// CHECK-NEXT: main
// CHECK-NEXT: foo
// CHECK-NEXT: bar
// CHECK-NEXT: baz
// Tests trace pc guard coverage collection.
// REQUIRES: has_sancovcc,stable-runtime
// UNSUPPORTED: ubsan,i386-darwin
// XFAIL: tsan,powerpc64,s390x,mips
// XFAIL: android && asan
// RUN: DIR=%t_workdir
// RUN: rm -rf $DIR
// RUN: mkdir -p $DIR
// RUN: cd $DIR
// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -o %t
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov %t 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
// RUN: %env_tool_opts=coverage=0 %t 2>&1 | FileCheck --check-prefix=CHECK-NOCOV %s
// RUN: rm -rf $DIR
// Make some room to stabilize line numbers
#include <stdio.h>
int foo() {
fprintf(stderr, "foo\n");
return 1;
}
int main() {
fprintf(stderr, "main\n");
foo();
foo();
}
// CHECK: main
// CHECK-NEXT: foo
// CHECK-NEXT: foo
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov: 2 PCs written
//
// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cpp:[[@LINE-16]] foo
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cpp:[[@LINE-12]] main
//
// CHECK-NOCOV-NOT: SanitizerCoverage
// trace-pc-guard-cb.cc
#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
// This callback is inserted by the compiler as a module constructor
// into every DSO. 'start' and 'stop' correspond to the
// beginning and end of the section with the guards for the entire
// binary (executable or DSO). The callback will be called at least
// once per DSO and may be called multiple times with the same parameters.
extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
// This callback is inserted by the compiler on every edge in the
// control flow (some optimizations apply).
// Typically, the compiler will emit the code like this:
// if(*guard)
// __sanitizer_cov_trace_pc_guard(guard);
// But for large functions it will emit a simple call:
// __sanitizer_cov_trace_pc_guard(guard);
extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
if (!*guard) return; // Duplicate the guard check.
// If you set *guard to 0 this code will not be called again for this edge.
// Now you can get the PC and do whatever you want:
// store it somewhere or symbolize it and print right away.
// The values of `*guard` are as you set them in
// __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
// and use them to dereference an array or a bit vector.
void *PC = __builtin_return_address(0);
char PcDescr[1024];
// This function is a part of the sanitizer run-time.
// To use it, link with AddressSanitizer or other sanitizer.
__sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
}
int main(){}
\ No newline at end of file
// trace-pc-guard-example.cc
void foo() { }
int main(int argc, char **argv) {
if (argc > 1) foo();
}
cmake_minimum_required(VERSION 3.5)
# project name
project (ubsan_test)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../exe)
# Add executable
file(GLOB TESTCASES src/*.cpp)
foreach(srcfile ${TESTCASES})
get_filename_component(testname ${srcfile} NAME_WE)
set(CMAKE_CXX_FLAGS "-fsanitize=undefined")
if (${testname} STREQUAL "add-overflow")
add_executable(add-overflow-32 ${srcfile})
target_compile_definitions(add-overflow-32 PRIVATE ADD_I32)
add_executable(add-overflow-64 ${srcfile})
target_compile_definitions(add-overflow-64 PRIVATE ADD_I64)
add_executable(add-overflow-128 ${srcfile})
target_compile_definitions(add-overflow-128 PRIVATE ADD_I128)
elseif(${testname} STREQUAL "div-zero")
add_executable(div-zero-0 ${srcfile})
target_compile_definitions(div-zero-0 PRIVATE DIVIDEND=0)
add_executable(div-zero-1U ${srcfile})
target_compile_definitions(div-zero-1U PRIVATE DIVIDEND=1U)
add_executable(div-zero-123 ${srcfile})
target_compile_definitions(div-zero-123 PRIVATE "DIVIDEND=intmax(123)")
add_executable(div-zero-1-5 ${srcfile})
target_compile_options(div-zero-1-5 PRIVATE -fsanitize=float-divide-by-zero)
target_compile_definitions(div-zero-1-5 PRIVATE DIVIDEND=1.5)
elseif(${testname} STREQUAL "shift")
set(UBSAN_SHIFT_FLAG "-fno-sanitize-recover=shift")
set(CMAKE_CXX_FLAGS "")
# LSH_OVERFLOW
# CHECK-LSH_OVERFLOW: shift.cpp:[[@LINE+1]]:5: runtime error: left shift of negative value -2147483648
add_executable(shift-lsh-overflow ${srcfile})
target_compile_options(shift-lsh-overflow PRIVATE -fsanitize=shift ${UBSAN_SHIFT_FLAG} "-DLSH_OVERFLOW" "-DOP=<<")
add_executable(shift-lsh-overflow-1 ${srcfile})
target_compile_options(shift-lsh-overflow-1 PRIVATE -fsanitize=shift-base ${UBSAN_SHIFT_FLAG} "-DLSH_OVERFLOW" "-DOP=<<")
add_executable(shift-lsh-overflow-2 ${srcfile})
target_compile_options(shift-lsh-overflow-2 PRIVATE -fsanitize=shift-exponent ${UBSAN_SHIFT_FLAG} "-DLSH_OVERFLOW" "-DOP=<<")
# TOO_LOW
# CHECK-TOO_LOW: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent -3 is negative
add_executable(shift-too-low ${srcfile})
target_compile_options(shift-too-low PRIVATE ${UBSAN_SHIFT_FLAG} "-DTOO_LOW" "-DOP=<<")
# TOO_HIGH
# CHECK-TOO_HIGH: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent 32 is too large for 32-bit type 'int'
add_executable(shift-high ${srcfile})
target_compile_options(shift-high PRIVATE ${UBSAN_SHIFT_FLAG} "-DTOO_HIGH" "-DOP=>>")
#end
elseif(${testname} STREQUAL "uadd-overflow")
add_executable(uadd-overflow-32 ${srcfile})
target_compile_definitions(uadd-overflow-32 PRIVATE ADD_I32)
add_executable(uadd-overflow-64 ${srcfile})
target_compile_definitions(add-overflow-64 PRIVATE ADD_I64)
add_executable(uadd-overflow-128 ${srcfile})
target_compile_definitions(uadd-overflow-128 PRIVATE ADD_I128)
elseif(${testname} STREQUAL "cast-overflow")
# ld.lld: error: undefined symbol: __sync_val_compare_and_swap_1
continue()
elseif(${testname} STREQUAL "unreachable")
# undefined symbol: returns_unexpectedly
continue()
else()
add_executable(${testname} ${srcfile})
endif()
endforeach()
file(GLOB CASES_C src/*.c)
foreach(src_c ${CASES_C})
get_filename_component(name_c ${src_c} NAME_WE)
set(CMAKE_CXX_FLAGS "-fsanitize=undefined")
if(${name_c} STREQUAL "vla")
# did not work as expected
add_executable(vla ${src_c})
target_compile_options(shift-lsh-overflow-1 PRIVATE -fsanitize=vla-bound -O3)
endif()
endforeach()
\ No newline at end of file
#!/usr/bin/python
import os
import sys
import subprocess
import shutil
pre_dir = os.path.abspath(os.path.dirname(os.getcwd()))
config_dir = os.path.join(os.path.dirname(pre_dir),'script')
sys.path.append(config_dir)
from config_args import linux_args
# Add ubsan compile options
ubsan_flags = []
build_args=[]
build_args.extend(linux_args)
build_args.extend(ubsan_flags)
def rm_build():
if os.path.exists("build") and os.path.isdir("build"):
shutil.rmtree("build")
while True:
if not os.path.exists("build"):
break
def build_linux():
rm_build()
os.mkdir("build")
build_cmd = "cmake " + (" ".join(build_args))+ " .."
print(build_cmd)
res1 = subprocess.Popen(build_cmd,cwd='build',shell=True).wait()
# print(res1)
res2 = subprocess.Popen('make',cwd='build',shell=True).wait()
# print(res2)
rm_build()
if __name__ == '__main__':
build_linux()
// RUN: %clangxx -DADD_I32 -fsanitize=signed-integer-overflow %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I32
// RUN: %clangxx -DADD_I64 -fsanitize=signed-integer-overflow %s -o %t2 && %run %t2 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I64
// RUN: %clangxx -DADD_I128 -fsanitize=signed-integer-overflow %s -o %t3 && %run %t3 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I128
#include <stdint.h>
#include <stdio.h>
int main() {
// These promote to 'int'.
(void)(int8_t(0x7f) + int8_t(0x7f));
(void)(int16_t(0x3fff) + int16_t(0x4000));
#ifdef ADD_I32
int32_t k = 0x12345678;
k += 0x789abcde;
// CHECK-ADD_I32: add-overflow.cpp:[[@LINE-1]]:5: runtime error: signed integer overflow: 305419896 + 2023406814 cannot be represented in type 'int'
#endif
#ifdef ADD_I64
(void)(int64_t(8000000000000000000ll) + int64_t(2000000000000000000ll));
// CHECK-ADD_I64: 8000000000000000000 + 2000000000000000000 cannot be represented in type '{{long( long)?}}'
#endif
#ifdef ADD_I128
# if defined(__SIZEOF_INT128__) && !defined(_WIN32)
(void)((__int128_t(1) << 126) + (__int128_t(1) << 126));
# else
puts("__int128 not supported");
# endif
// CHECK-ADD_I128: {{0x40000000000000000000000000000000 \+ 0x40000000000000000000000000000000 cannot be represented in type '__int128'|__int128 not supported}}
#endif
}
// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:"
#include <stdlib.h>
typedef char *__attribute__((align_value(0x8000))) aligned_char;
struct ac_struct {
aligned_char a;
};
char *load_from_ac_struct(struct ac_struct *x) {
return x->a;
}
int main(int argc, char* argv[]) {
char *ptr = (char *)malloc(2);
struct ac_struct x;
x.a = ptr + 1; // FIXME: it is weird that this does not also have an assumption.
load_from_ac_struct(&x);
// CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-9]]:13: runtime error: assumption of 32768 byte alignment for pointer of type 'aligned_char' (aka 'char *') failed
// CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-17]]:30: note: alignment assumption was specified here
// CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte
free(ptr);
return 0;
}
// RUN: %clangxx -fsanitize=bool %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %env_ubsan_opts=print_summary=1:report_error_type=1 not %run %t 2>&1 | FileCheck %s --check-prefix=SUMMARY
unsigned char NotABool = 123;
int main(int argc, char **argv) {
bool *p = (bool*)&NotABool;
// CHECK: bool.cpp:[[@LINE+1]]:10: runtime error: load of value 123, which is not a valid value for type 'bool'
return *p;
// SUMMARY: SUMMARY: {{.*}}Sanitizer: invalid-bool-load {{.*}}bool.cpp:[[@LINE-1]]
}
// RUN: %clangxx -fsanitize=bounds %s -O3 -o %t
// RUN: %run %t 0 0 0
// RUN: %run %t 1 2 3
// RUN: %expect_crash %run %t 2 0 0 2>&1 | FileCheck %s --check-prefix=CHECK-A-2
// RUN: %run %t 0 3 0 2>&1 | FileCheck %s --check-prefix=CHECK-B-3
// RUN: %run %t 0 0 4 2>&1 | FileCheck %s --check-prefix=CHECK-C-4
int get_int(int *const p __attribute__((pass_object_size(0))), int i) {
// CHECK-A-2: bounds.cpp:[[@LINE+1]]:10: runtime error: index 2 out of bounds for type 'int *'
return p[i];
}
int get_double(double *const p __attribute__((pass_object_size(0))), int i) {
// CHECK-A-2: bounds.cpp:[[@LINE+1]]:10: runtime error: index 2 out of bounds for type 'double *'
return p[i];
}
int main(int argc, char **argv) {
int bar[2];
get_int(bar, argv[1][0] - '0');
double baz[2];
get_double(baz, argv[1][0] - '0');
int arr[2][3][4] = {};
return arr[argv[1][0] - '0'][argv[2][0] - '0'][argv[3][0] - '0'];
// CHECK-A-2: bounds.cpp:[[@LINE-1]]:10: runtime error: index 2 out of bounds for type 'int[2][3][4]'
// CHECK-B-3: bounds.cpp:[[@LINE-2]]:10: runtime error: index 3 out of bounds for type 'int[3][4]'
// CHECK-C-4: bounds.cpp:[[@LINE-3]]:10: runtime error: index 4 out of bounds for type 'int[4]'
}
// RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t
// RUN: %run %t _
// RUN: %env_ubsan_opts=print_summary=1:report_error_type=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
// RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
// RUN: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
// RUN: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
// RUN: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
// RUN: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// FIXME: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
// FIXME: not %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
// RUN: not %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9
// This test assumes float and double are IEEE-754 single- and double-precision.
#if defined(__APPLE__)
# include <machine/endian.h>
# define BYTE_ORDER __DARWIN_BYTE_ORDER
# define BIG_ENDIAN __DARWIN_BIG_ENDIAN
# define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
#elif defined(__FreeBSD__) || defined(__NetBSD__)
# include <sys/endian.h>
# ifndef BYTE_ORDER
# define BYTE_ORDER _BYTE_ORDER
# endif
# ifndef BIG_ENDIAN
# define BIG_ENDIAN _BIG_ENDIAN
# endif
# ifndef LITTLE_ENDIAN
# define LITTLE_ENDIAN _LITTLE_ENDIAN
# endif
#elif defined(__sun__) && defined(__svr4__)
// Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h.
# include <sys/types.h>
# define BIG_ENDIAN 4321
# define LITTLE_ENDIAN 1234
# if defined(_BIG_ENDIAN)
# define BYTE_ORDER BIG_ENDIAN
# else
# define BYTE_ORDER LITTLE_ENDIAN
# endif
#elif defined(_WIN32)
# define BYTE_ORDER 0
# define BIG_ENDIAN 1
# define LITTLE_ENDIAN 0
#else
# include <endian.h>
# define BYTE_ORDER __BYTE_ORDER
# define BIG_ENDIAN __BIG_ENDIAN
# define LITTLE_ENDIAN __LITTLE_ENDIAN
#endif // __APPLE__
#include <stdint.h>
#include <stdio.h>
#include <string.h>
float Inf;
float NaN;
int main(int argc, char **argv) {
float MaxFloatRepresentableAsInt = 0x7fffff80;
(int)MaxFloatRepresentableAsInt; // ok
(int)-MaxFloatRepresentableAsInt; // ok
float MinFloatRepresentableAsInt = -0x7fffffff - 1;
(int)MinFloatRepresentableAsInt; // ok
float MaxFloatRepresentableAsUInt = 0xffffff00u;
(unsigned int)MaxFloatRepresentableAsUInt; // ok
#ifdef __SIZEOF_INT128__
unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104);
(void)(float)FloatMaxAsUInt128; // ok
#endif
float NearlyMinusOne = -0.99999;
unsigned Zero = NearlyMinusOne; // ok
// Build a '+Inf'.
#if BYTE_ORDER == LITTLE_ENDIAN
unsigned char InfVal[] = { 0x00, 0x00, 0x80, 0x7f };
#else
unsigned char InfVal[] = { 0x7f, 0x80, 0x00, 0x00 };
#endif
float Inf;
memcpy(&Inf, InfVal, 4);
// Build a 'NaN'.
#if BYTE_ORDER == LITTLE_ENDIAN
unsigned char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f };
#else
unsigned char NaNVal[] = { 0x7f, 0x80, 0x00, 0x01 };
#endif
float NaN;
memcpy(&NaN, NaNVal, 4);
double DblInf = (double)Inf; // ok
switch (argv[1][0]) {
// FIXME: Produce a source location for these checks and test for it here.
// Floating point -> integer overflow.
case '0': {
// Note that values between 0x7ffffe00 and 0x80000000 may or may not
// successfully round-trip, depending on the rounding mode.
// CHECK-0: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: 2.14748{{.*}} is outside the range of representable values of type 'int'
static int test_int = MaxFloatRepresentableAsInt + 0x80;
// CHECK-0: SUMMARY: {{.*}}Sanitizer: float-cast-overflow {{.*}}cast-overflow.cpp:[[@LINE-1]]
return 0;
}
case '1': {
// CHECK-1: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: -2.14748{{.*}} is outside the range of representable values of type 'int'
static int test_int = MinFloatRepresentableAsInt - 0x100;
return 0;
}
case '2': {
// CHECK-2: {{.*}}cast-overflow.cpp:[[@LINE+2]]:37: runtime error: -1 is outside the range of representable values of type 'unsigned int'
volatile float f = -1.0;
volatile unsigned u = (unsigned)f;
return 0;
}
case '3': {
// CHECK-3: {{.*}}cast-overflow.cpp:[[@LINE+1]]:37: runtime error: 4.2949{{.*}} is outside the range of representable values of type 'unsigned int'
static int test_int = (unsigned)(MaxFloatRepresentableAsUInt + 0x100);
return 0;
}
case '4': {
// CHECK-4: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: {{.*}} is outside the range of representable values of type 'int'
static int test_int = Inf;
return 0;
}
case '5': {
// CHECK-5: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: {{.*}} is outside the range of representable values of type 'int'
static int test_int = NaN;
return 0;
}
// Integer -> floating point overflow.
case '6': {
// CHECK-6: cast-overflow.cpp:[[@LINE+2]]:{{27: runtime error: 3.40282e\+38 is outside the range of representable values of type 'int'| __int128 not supported}}
#if defined(__SIZEOF_INT128__) && !defined(_WIN32)
static int test_int = (float)(FloatMaxAsUInt128 + 1);
return 0;
#else
// Print the same line as the check above. That way the test is robust to
// line changes around it
printf("%s:%d: __int128 not supported", __FILE__, __LINE__ - 5);
return 0;
#endif
}
// FIXME: The backend cannot lower __fp16 operations on x86 yet.
//case '7':
// (__fp16)65504; // ok
// // CHECK-7: runtime error: 65505 is outside the range of representable values of type '__fp16'
// return (__fp16)65505;
// Floating point -> floating point overflow.
case '8':
// CHECK-8: {{.*}}cast-overflow.cpp:[[@LINE+1]]:19: runtime error: 1e+39 is outside the range of representable values of type 'float'
return (float)1e39;
case '9':
volatile long double ld = 300.0;
// CHECK-9: {{.*}}cast-overflow.cpp:[[@LINE+1]]:14: runtime error: 300 is outside the range of representable values of type 'char'
char c = ld;
return c;
}
}
// RUN: %clangxx -fsanitize=integer-divide-by-zero -DDIVIDEND=0 %s -o %t && %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -fsanitize=integer-divide-by-zero -DDIVIDEND=1U %s -o %t && %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -fsanitize=integer-divide-by-zero -DDIVIDEND='intmax(123)' %s -o %t && %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -fsanitize=float-divide-by-zero -DDIVIDEND=1.5 %s -o %t && %run %t 2>&1 | FileCheck %s
#if defined(__SIZEOF_INT128__) && !defined(_WIN32)
typedef __int128 intmax;
#else
typedef long long intmax;
#endif
int main() {
// CHECK: div-zero.cpp:[[@LINE+1]]:12: runtime error: division by zero
DIVIDEND / 0;
}
// RUN: %clangxx -fsanitize=enum %s -O3 -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-PLAIN
// RUN: %clangxx -fsanitize=enum -std=c++11 -DE="class E" %s -O3 -o %t && %run %t
// RUN: %clangxx -fsanitize=enum -std=c++11 -DE="class E : bool" %s -O3 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-BOOL
// FIXME: UBSan fails to add the correct instrumentation code for some reason on
// Windows.
// XFAIL: windows-msvc
enum E { a = 1 } e;
#undef E
int main(int argc, char **argv) {
// memset(&e, 0xff, sizeof(e));
for (unsigned char *p = (unsigned char*)&e; p != (unsigned char*)(&e + 1); ++p)
*p = 0xff;
// CHECK-PLAIN: error: load of value 4294967295, which is not a valid value for type 'enum E'
// FIXME: Support marshalling and display of enum class values.
// CHECK-BOOL: error: load of value <unknown>, which is not a valid value for type 'enum E'
return (int)e != -1;
}
// RUN: %clangxx -fsanitize=return %gmlt %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-STACKTRACE
// Error message does not exact what expected
// XFAIL: openbsd
// CHECK: missing_return.cpp:[[@LINE+1]]:5: runtime error: execution reached the end of a value-returning function without returning a value
int f() __attribute__((noinline)) {
// CHECK-STACKTRACE: #0 {{.*}}f{{.*}}missing_return.cpp:[[@LINE-1]]
}
int main(int, char **argv) {
return f();
}
// RUN: %clangxx -fsanitize=nonnull-attribute -fno-sanitize-recover=all %s -O3 -o %t
// RUN: %run %t nc
// RUN: %run %t nm
// RUN: %run %t nf
// RUN: %run %t nv
// RUN: not %run %t 0c 2>&1 | FileCheck %s --check-prefix=CTOR
// RUN: not %run %t 0m 2>&1 | FileCheck %s --check-prefix=METHOD
// RUN: not %run %t 0f 2>&1 | FileCheck %s --check-prefix=FUNC
// RUN: not %run %t 0v 2>&1 | FileCheck %s --check-prefix=VARIADIC
//
// AArch64 lacks variadic instrumentation for MSAN.
// REQUIRES: stable-runtime
class C {
int *null_;
int *nonnull_;
public:
C(int *null, __attribute__((nonnull)) int *nonnull)
: null_(null), nonnull_(nonnull) {}
int value() { return *nonnull_; }
int method(int *nonnull, int *null) __attribute__((nonnull(2))) {
return *nonnull_ + *nonnull;
}
};
__attribute__((nonnull)) int func(int *nonnull) { return *nonnull; }
#include <stdarg.h>
__attribute__((nonnull)) int variadic(int x, ...) {
va_list args;
va_start(args, x);
int *nonnull = va_arg(args, int*);
int res = *nonnull;
va_end(args);
return res;
}
int main(int argc, char *argv[]) {
int local = 0;
int *arg = (argv[1][0] == '0') ? 0x0 : &local;
switch (argv[1][1]) {
case 'c':
return C(0x0, arg).value();
// CTOR: {{.*}}nonnull-arg.cpp:[[@LINE-1]]:21: runtime error: null pointer passed as argument 2, which is declared to never be null
// CTOR-NEXT: {{.*}}nonnull-arg.cpp:19:31: note: nonnull attribute specified here
case 'm':
return C(0x0, &local).method(arg, 0x0);
// METHOD: {{.*}}nonnull-arg.cpp:[[@LINE-1]]:36: runtime error: null pointer passed as argument 1, which is declared to never be null
// METHOD-NEXT: {{.*}}nonnull-arg.cpp:22:54: note: nonnull attribute specified here
case 'f':
return func(arg);
// FUNC: {{.*}}nonnull-arg.cpp:[[@LINE-1]]:19: runtime error: null pointer passed as argument 1, which is declared to never be null
// FUNC-NEXT: {{.*}}nonnull-arg.cpp:27:16: note: nonnull attribute specified here
case 'v':
return variadic(42, arg);
// VARIADIC: {{.*}}nonnull-arg.cpp:[[@LINE-1]]:27: runtime error: null pointer passed as argument 2, which is declared to never be null
// VARIADIC-NEXT: {{.*}}nonnull-arg.cpp:30:16: note: nonnull attribute specified here
}
return 0;
}
// RUN: %clangxx -fsanitize=returns-nonnull-attribute -w %s -O3 -o %t
// RUN: %run %t foo 2>&1 | FileCheck %s --check-prefix=NOERROR --allow-empty --implicit-check-not='runtime error'
// RUN: %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -fsanitize=returns-nonnull-attribute -fno-sanitize-recover=returns-nonnull-attribute -w %s -O3 -o %t.abort
// RUN: not %run %t.abort &> /dev/null
__attribute__((returns_nonnull)) char *foo(char *a);
char *foo(char *a) {
// CHECK: nonnull.cpp:[[@LINE+2]]:3: runtime error: null pointer returned from function declared to never return null
// CHECK-NEXT: nonnull.cpp:[[@LINE-4]]:16: note: returns_nonnull attribute specified here
return a;
}
__attribute__((returns_nonnull)) char *bar(int x, char *a) {
if (x > 10) {
// CHECK: nonnull.cpp:[[@LINE+2]]:5: runtime error: null pointer returned from function declared to never return null
// CHECK-NEXT: nonnull.cpp:[[@LINE-3]]:16: note: returns_nonnull attribute specified here
return a;
} else {
// CHECK: nonnull.cpp:[[@LINE+2]]:5: runtime error: null pointer returned from function declared to never return null
// CHECK-NEXT: nonnull.cpp:[[@LINE-7]]:16: note: returns_nonnull attribute specified here
return a;
}
}
int main(int argc, char **argv) {
char *a = argv[1];
foo(a);
bar(20, a);
// We expect to see a runtime error the first time we cover the "else"...
bar(5, a);
// ... but not a second time.
// CHECK-NOT: runtime error
bar(5, a);
return 0;
}
// NOERROR-NOT: runtime error
// RUN: %clangxx -fsanitize=null -fno-sanitize-recover=null %s -O3 -o %t
// RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD
// RUN: not %run %t s 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
// RUN: not %run %t r 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
// RUN: not %run %t m 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
// RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
// RUN: not %run %t t 2>&1 | FileCheck %s --check-prefix=CHECK-VCALL
// RUN: not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-VCALL2
struct S {
int f() { return 0; }
int k;
};
struct T {
virtual int v() { return 1; }
};
struct U : T {
virtual int v() { return 2; }
};
int main(int, char **argv) {
int *p = 0;
S *s = 0;
T *t = 0;
U *u = 0;
(void)*p; // ok!
(void)*t; // ok!
(void)*u; // ok!
switch (argv[1][0]) {
case 'l':
// CHECK-LOAD: null.cpp:[[@LINE+1]]:12: runtime error: load of null pointer of type 'int'
return *p;
case 's':
// CHECK-STORE: null.cpp:[[@LINE+1]]:5: runtime error: store to null pointer of type 'int'
*p = 1;
break;
case 'r':
// CHECK-REFERENCE: null.cpp:[[@LINE+1]]:15: runtime error: reference binding to null pointer of type 'int'
{int &r = *p;}
break;
case 'm':
// CHECK-MEMBER: null.cpp:[[@LINE+1]]:15: runtime error: member access within null pointer of type 'S'
return s->k;
case 'f':
// CHECK-MEMFUN: null.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'S'
return s->f();
case 't':
// CHECK-VCALL: null.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'T'
return t->v();
case 'u':
// CHECK-VCALL2: null.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'U'
return u->v();
}
}
// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t1 && not %run %t1 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t2 && not %run %t2 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t3 && not %run %t3 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t4 && not %run %t4 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
// RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t5 && not %run %t5 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
// RUN: %clangxx -DTOO_LOW -DOP='>>=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t6 && not %run %t6 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t7 && not %run %t7 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t8 && not %run %t8 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
// RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t9 && not %run %t9 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
// RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t10 && not %run %t10 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t12 && %run %t12
// RUN: %clangxx -DLSH_OVERFLOW -DOP='>>' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t13 && %run %t13
// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t14 && %run %t14
// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t15 && %run %t15
// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t16 && %run %t16
// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t17 && %run %t17
#include <stdint.h>
int main() {
int a = 1;
unsigned b = 1;
a <<= 31; // ok in C++11, not ok in C99/C11
b <<= 31; // ok
b <<= 1; // still ok, unsigned
#ifdef LSH_OVERFLOW
// CHECK-LSH_OVERFLOW: shift.cpp:[[@LINE+1]]:5: runtime error: left shift of negative value -2147483648
a OP 1;
#endif
#ifdef TOO_LOW
a = 0;
// CHECK-TOO_LOW: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent -3 is negative
a OP (-3);
#endif
#ifdef TOO_HIGH
a = 0;
// CHECK-TOO_HIGH: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent 32 is too large for 32-bit type 'int'
a OP 32;
#endif
}
// RUN: %clangxx -DADD_I32 -fsanitize=unsigned-integer-overflow %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I32
// RUN: %clangxx -DADD_I64 -fsanitize=unsigned-integer-overflow %s -o %t2 && %run %t2 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I64
// RUN: %clangxx -DADD_I128 -fsanitize=unsigned-integer-overflow %s -o %t3 && %run %t3 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I128
#include <stdint.h>
#include <stdio.h>
int main() {
// These promote to 'int'.
(void)(uint8_t(0xff) + uint8_t(0xff));
(void)(uint16_t(0xf0fff) + uint16_t(0x0fff));
#ifdef ADD_I32
uint32_t k = 0x87654321;
k += 0xedcba987;
// CHECK-ADD_I32: uadd-overflow.cpp:[[@LINE-1]]:5: runtime error: unsigned integer overflow: 2271560481 + 3989547399 cannot be represented in type 'unsigned int'
#endif
#ifdef ADD_I64
(void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull));
// CHECK-ADD_I64: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}'
#endif
#ifdef ADD_I128
# if defined(__SIZEOF_INT128__) && !defined(_WIN32)
(void)((__uint128_t(1) << 127) + (__uint128_t(1) << 127));
# else
puts("__int128 not supported");
# endif
// CHECK-ADD_I128: {{0x80000000000000000000000000000000 \+ 0x80000000000000000000000000000000 cannot be represented in type 'unsigned __int128'|__int128 not supported}}
#endif
}
// RUN: %clang %S/Inputs/returns-unexpectedly.c -O3 -c -o %t.ru.o
// RUN: %clangxx -fsanitize=unreachable -O3 -o %t %s %t.ru.o
// RUN: not %run %t builtin 2>&1 | FileCheck %s -check-prefix=BUILTIN
// RUN: not %run %t noreturn-callee-marked 2>&1 | FileCheck %s -check-prefix=NORETURN1
// RUN: not %run %t noreturn-caller-marked 2>&1 | FileCheck %s -check-prefix=NORETURN2
#include <string.h>
void __attribute__((noreturn)) callee_marked_noreturn() {
// NORETURN1: unreachable.cpp:[[@LINE+1]]:1: runtime error: execution reached an unreachable program point
}
extern "C" void __attribute__((noreturn)) returns_unexpectedly();
int main(int, char **argv) {
if (strcmp(argv[1], "builtin") == 0)
// BUILTIN: unreachable.cpp:[[@LINE+1]]:5: runtime error: execution reached an unreachable program point
__builtin_unreachable();
else if (strcmp(argv[1], "noreturn-callee-marked") == 0)
callee_marked_noreturn();
else if (strcmp(argv[1], "noreturn-caller-marked") == 0)
// NORETURN2: unreachable.cpp:[[@LINE+1]]:5: runtime error: execution reached an unreachable program point
returns_unexpectedly();
return 0;
}
// RUN: %clang -fsanitize=vla-bound %s -O3 -o %t
// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-MINUS-ONE
// RUN: %run %t a 2>&1 | FileCheck %s --check-prefix=CHECK-ZERO
// RUN: %run %t a b
int main(int argc, char **argv) {
// CHECK-MINUS-ONE: vla.c:[[@LINE+2]]:11: runtime error: variable length array bound evaluates to non-positive value -1
// CHECK-ZERO: vla.c:[[@LINE+1]]:11: runtime error: variable length array bound evaluates to non-positive value 0
int arr[argc - 2];
return 0;
}
#!/usr/bin/env python3
from distutils.command.build import build
import os
import fnmatch
......@@ -7,13 +9,14 @@ import datetime
compiler_list = [
'ndk-test',
#'sanitize',
'sanitize',
'arm-neon',
]
# Check the output directory
def check_target_dir():
target_dir = os.path.join(os.getcwd(),os.path.pardir,'target')
print(target_dir)
# print(target_dir)
if os.path.exists(target_dir) and os.path.isdir(target_dir):
# print('target directory exist')
for filename in os.listdir(target_dir):
......@@ -58,18 +61,24 @@ def copy_target():
for curdir, dirs, files in os.walk(file_path):
for dirname in dirs:
if dirname == 'output':
copy_tar_out = os.path.join(find_dir,'target',name,os.path.basename(curdir))
# print(copy_tar_out)
if not os.path.isdir(copy_tar_out):
os.makedirs(copy_tar_out)
tar_out = os.path.join(curdir,dirname)
# print(tar_out)
print(tar_out + '----->' + copy_tar_out)
for filename in os.listdir(tar_out):
src = os.path.join(tar_out, filename)
dst = os.path.join(copy_tar_out, filename)
print(src + '----->' + dst)
shutil.copy(src, dst)
if name == 'sanitize':
src = os.path.join(file_path,dirname)
copy_tar_out = os.path.join(find_dir,'target',name)
shutil.copytree(src,copy_tar_out)
shutil.rmtree(src)
else:
copy_tar_out = os.path.join(find_dir,'target',name,os.path.basename(curdir))
# print(copy_tar_out)
if not os.path.isdir(copy_tar_out):
os.makedirs(copy_tar_out)
tar_out = os.path.join(curdir,dirname)
# print(tar_out)
# print(tar_out + '----->' + copy_tar_out)
for filename in os.listdir(tar_out):
src = os.path.join(tar_out, filename)
dst = os.path.join(copy_tar_out, filename)
# print(src + '----->' + dst)
shutil.copy(src, dst)
copy_end = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('copy_target_end:' + copy_end)
......
import shutil
import os
cmake_path = shutil.which('cmake')
cmake_file = os.path.join(os.path.dirname(
cmake_path), '../../../build/cmake/ohos.toolchain.cmake')
find_toolchain_file = os.path.isfile(cmake_file)
if(find_toolchain_file):
toolchain_file = cmake_file
else:
print(cmake_file+" not found")
# toolchain_file = "~/openharmony/out/sdk/packages/ohos-sdk/linux/native/build/cmake/ohos.toolchain.cmake"
linux_args = [
'-DOHOS_STL=c++_shared' ,
'-DOHOS_ARCH=armeabi-v7a' ,
'-DOHOS_PLATFORM=OHOS' ,
'-DCMAKE_TOOLCHAIN_FILE=~/openharmony/out/sdk/packages/ohos-sdk/linux/native/build/cmake/ohos.toolchain.cmake' ,
]
'-DOHOS_STL=c++_shared',
'-DOHOS_ARCH=armeabi-v7a',
'-DOHOS_PLATFORM=OHOS',
'-DCMAKE_TOOLCHAIN_FILE='+toolchain_file,
]
\ No newline at end of file
- Place the compilation to generate the object file
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册