Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[dfsan] Add test cases for struct/pair
This is a child diff of D92261. This locks down the behavior before the change.
- Loading branch information
1 parent
ee571f8
commit 6fa0662
Showing
2 changed files
with
215 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// RUN: %clangxx_dfsan %s -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -o %t && %run %t | ||
|
||
#include <algorithm> | ||
#include <assert.h> | ||
#include <sanitizer/dfsan_interface.h> | ||
#include <utility> | ||
|
||
__attribute__((noinline)) | ||
std::pair<int *, int> | ||
make_pair(int *p, int i) { return {p, i}; } | ||
|
||
__attribute__((noinline)) | ||
std::pair<int *, int> | ||
copy_pair1(const std::pair<int *, int> &pair) { | ||
return pair; | ||
} | ||
|
||
__attribute__((noinline)) | ||
std::pair<int *, int> | ||
copy_pair2(std::pair<int *, int> *pair) { | ||
return *pair; | ||
} | ||
|
||
__attribute__((noinline)) | ||
std::pair<int *, int> | ||
copy_pair3(std::pair<int *, int> &&pair) { | ||
return std::move(pair); | ||
} | ||
|
||
__attribute__((noinline)) | ||
std::pair<const char *, uint32_t> | ||
return_ptr_and_i32(const char *p, uint32_t res) { | ||
for (uint32_t i = 2; i < 5; i++) { | ||
uint32_t byte = static_cast<uint8_t>(p[i]); | ||
res += (byte - 1) << (7 * i); | ||
if (byte < 128) { | ||
return {p + i + 1, res}; | ||
} | ||
} | ||
return {nullptr, 0}; | ||
} | ||
|
||
__attribute__((noinline)) | ||
std::pair<const char *, uint64_t> | ||
return_ptr_and_i64(const char *p, uint32_t res32) { | ||
uint64_t res = res32; | ||
for (uint32_t i = 2; i < 10; i++) { | ||
uint64_t byte = static_cast<uint8_t>(p[i]); | ||
res += (byte - 1) << (7 * i); | ||
if (byte < 128) { | ||
return {p + i + 1, res}; | ||
} | ||
} | ||
return {nullptr, 0}; | ||
} | ||
|
||
void test_simple_constructors() { | ||
int i = 1; | ||
int *ptr = NULL; | ||
dfsan_set_label(8, &i, sizeof(i)); | ||
dfsan_set_label(2, &ptr, sizeof(ptr)); | ||
|
||
std::pair<int *, int> pair1 = make_pair(ptr, i); | ||
int i1 = pair1.second; | ||
int *ptr1 = pair1.first; | ||
|
||
assert(dfsan_read_label(&i1, sizeof(i1)) == 10); | ||
assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10); | ||
|
||
std::pair<int *, int> pair2 = copy_pair1(pair1); | ||
int i2 = pair2.second; | ||
int *ptr2 = pair2.first; | ||
|
||
assert(dfsan_read_label(&i2, sizeof(i2)) == 10); | ||
assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 10); | ||
|
||
std::pair<int *, int> pair3 = copy_pair2(&pair1); | ||
int i3 = pair3.second; | ||
int *ptr3 = pair3.first; | ||
|
||
assert(dfsan_read_label(&i3, sizeof(i3)) == 10); | ||
assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 10); | ||
|
||
std::pair<int *, int> pair4 = copy_pair3(std::move(pair1)); | ||
int i4 = pair4.second; | ||
int *ptr4 = pair4.first; | ||
|
||
assert(dfsan_read_label(&i4, sizeof(i4)) == 10); | ||
assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 10); | ||
} | ||
|
||
void test_branches() { | ||
uint32_t res = 4; | ||
dfsan_set_label(8, &res, sizeof(res)); | ||
|
||
char p[100]; | ||
const char *q = p; | ||
dfsan_set_label(2, &q, sizeof(q)); | ||
|
||
{ | ||
std::fill_n(p, 100, static_cast<char>(128)); | ||
|
||
{ | ||
std::pair<const char *, uint32_t> r = return_ptr_and_i32(q, res); | ||
assert(dfsan_read_label(&r.first, sizeof(r.first)) == 0); | ||
assert(dfsan_read_label(&r.second, sizeof(r.second)) == 0); | ||
} | ||
|
||
{ | ||
std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res); | ||
assert(dfsan_read_label(&r.first, sizeof(r.first)) == 0); | ||
assert(dfsan_read_label(&r.second, sizeof(r.second)) == 0); | ||
} | ||
} | ||
|
||
{ | ||
std::fill_n(p, 100, 0); | ||
|
||
{ | ||
std::pair<const char *, uint32_t> r = return_ptr_and_i32(q, res); | ||
assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10); | ||
assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10); | ||
} | ||
|
||
{ | ||
std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res); | ||
assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10); | ||
assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10); | ||
} | ||
} | ||
} | ||
|
||
int main(void) { | ||
test_simple_constructors(); | ||
test_branches(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// RUN: %clang_dfsan %s -o %t && %run %t | ||
|
||
#include <assert.h> | ||
#include <sanitizer/dfsan_interface.h> | ||
|
||
typedef struct Pair { | ||
int i; | ||
char *ptr; | ||
} Pair; | ||
|
||
__attribute__((noinline)) | ||
Pair make_pair(int i, char *ptr) { | ||
Pair pair; | ||
pair.i = i; | ||
pair.ptr = ptr; | ||
return pair; | ||
} | ||
|
||
__attribute__((noinline)) | ||
Pair copy_pair1(const Pair *pair0) { | ||
Pair pair; | ||
pair.i = pair0->i; | ||
pair.ptr = pair0->ptr; | ||
return pair; | ||
} | ||
|
||
__attribute__((noinline)) | ||
Pair copy_pair2(const Pair pair0) { | ||
Pair pair; | ||
pair.i = pair0.i; | ||
pair.ptr = pair0.ptr; | ||
return pair; | ||
} | ||
|
||
int main(void) { | ||
int i = 1; | ||
char *ptr = NULL; | ||
dfsan_label i_label = dfsan_create_label("i", 0); | ||
dfsan_set_label(i_label, &i, sizeof(i)); | ||
dfsan_label ptr_label = dfsan_create_label("ptr", 0); | ||
dfsan_set_label(ptr_label, &ptr, sizeof(ptr)); | ||
|
||
Pair pair1 = make_pair(i, ptr); | ||
int i1 = pair1.i; | ||
char *ptr1 = pair1.ptr; | ||
|
||
dfsan_label i1_label = dfsan_read_label(&i1, sizeof(i1)); | ||
dfsan_label ptr1_label = dfsan_read_label(&ptr1, sizeof(ptr1)); | ||
assert(dfsan_has_label(i1_label, i_label)); | ||
assert(dfsan_has_label(i1_label, ptr_label)); | ||
assert(dfsan_has_label(ptr1_label, i_label)); | ||
assert(dfsan_has_label(ptr1_label, ptr_label)); | ||
|
||
Pair pair2 = copy_pair1(&pair1); | ||
int i2 = pair2.i; | ||
char *ptr2 = pair2.ptr; | ||
|
||
dfsan_label i2_label = dfsan_read_label(&i2, sizeof(i2)); | ||
dfsan_label ptr2_label = dfsan_read_label(&ptr2, sizeof(ptr2)); | ||
assert(dfsan_has_label(i2_label, i_label)); | ||
assert(dfsan_has_label(i2_label, ptr_label)); | ||
assert(dfsan_has_label(ptr2_label, i_label)); | ||
assert(dfsan_has_label(ptr2_label, ptr_label)); | ||
|
||
Pair pair3 = copy_pair2(pair1); | ||
int i3 = pair3.i; | ||
char *ptr3 = pair3.ptr; | ||
|
||
dfsan_label i3_label = dfsan_read_label(&i3, sizeof(i3)); | ||
dfsan_label ptr3_label = dfsan_read_label(&ptr3, sizeof(ptr3)); | ||
assert(dfsan_has_label(i3_label, i_label)); | ||
assert(dfsan_has_label(i3_label, ptr_label)); | ||
assert(dfsan_has_label(ptr3_label, i_label)); | ||
assert(dfsan_has_label(ptr3_label, ptr_label)); | ||
|
||
return 0; | ||
} |