-
Notifications
You must be signed in to change notification settings - Fork 11k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sanitizer] Calculate Range sets intersection
Will be used to handle Root Regions in LSAN D151781. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D151779
- Loading branch information
1 parent
a15eb89
commit 6b3ae49
Showing
5 changed files
with
167 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
60 changes: 60 additions & 0 deletions
60
compiler-rt/lib/sanitizer_common/sanitizer_common_range.cpp
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,60 @@ | ||
//===-- sanitizer_common_range.cpp ----------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "sanitizer_common_range.h" | ||
|
||
namespace __sanitizer { | ||
|
||
void Intersect(ArrayRef<Range> a, ArrayRef<Range> b, | ||
InternalMmapVectorNoCtor<Range> &output) { | ||
output.clear(); | ||
|
||
struct Event { | ||
uptr val; | ||
s8 diff1; | ||
s8 diff2; | ||
}; | ||
|
||
InternalMmapVector<Event> events; | ||
for (const Range &r : a) { | ||
CHECK_LE(r.begin, r.end); | ||
events.push_back({r.begin, 1, 0}); | ||
events.push_back({r.end, -1, 0}); | ||
} | ||
|
||
for (const Range &r : b) { | ||
CHECK_LE(r.begin, r.end); | ||
events.push_back({r.begin, 0, 1}); | ||
events.push_back({r.end, 0, -1}); | ||
} | ||
|
||
Sort(events.data(), events.size(), | ||
[](const Event &lh, const Event &rh) { return lh.val < rh.val; }); | ||
|
||
uptr start = 0; | ||
sptr state1 = 0; | ||
sptr state2 = 0; | ||
for (const auto &e : events) { | ||
if (e.val != start) { | ||
DCHECK_GE(state1, 0); | ||
DCHECK_GE(state2, 0); | ||
if (state1 && state2) { | ||
if (!output.empty() && start == output.back().end) | ||
output.back().end = e.val; | ||
else | ||
output.push_back({start, e.val}); | ||
} | ||
start = e.val; | ||
} | ||
|
||
state1 += e.diff1; | ||
state2 += e.diff2; | ||
} | ||
} | ||
|
||
} // namespace __sanitizer |
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,39 @@ | ||
//===-- sanitizer_common_range.h --------------------------------*- C++ -*-===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Contais Range and related utilities. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SANITIZER_COMMON_REGION_H | ||
#define SANITIZER_COMMON_REGION_H | ||
|
||
#include "sanitizer_common.h" | ||
|
||
namespace __sanitizer { | ||
|
||
struct Range { | ||
uptr begin; | ||
uptr end; | ||
}; | ||
|
||
inline bool operator==(const Range &lhs, const Range &rhs) { | ||
return lhs.begin == rhs.begin && lhs.end == rhs.end; | ||
} | ||
|
||
inline bool operator!=(const Range &lhs, const Range &rhs) { | ||
return !(lhs == rhs); | ||
} | ||
|
||
// Calculates intersection of two sets of regions in O(N log N) time. | ||
void Intersect(ArrayRef<Range> a, ArrayRef<Range> b, | ||
InternalMmapVectorNoCtor<Range> &output); | ||
|
||
} // namespace __sanitizer | ||
|
||
#endif // SANITIZER_COMMON_REGION_H |
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
66 changes: 66 additions & 0 deletions
66
compiler-rt/lib/sanitizer_common/tests/sanitizer_common_range_test.cpp
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,66 @@ | ||
//===-- sanitizer_common_region_test.cpp ----------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file is a part of ThreadSanitizer/AddressSanitizer runtime. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#include "sanitizer_common/sanitizer_common_range.h" | ||
|
||
#include <algorithm> | ||
|
||
#include "gtest/gtest.h" | ||
#include "sanitizer_common/sanitizer_common.h" | ||
|
||
namespace __sanitizer { | ||
|
||
class SanitizerCommon | ||
: public testing::TestWithParam<std::tuple< | ||
std::vector<Range>, std::vector<Range>, std::vector<Range>>> {}; | ||
|
||
TEST_P(SanitizerCommon, Intersect) { | ||
{ | ||
InternalMmapVector<Range> output; | ||
Intersect(std::get<0>(GetParam()), std::get<1>(GetParam()), output); | ||
EXPECT_EQ(std::get<2>(GetParam()), | ||
std::vector<Range>(output.begin(), output.end())); | ||
} | ||
{ | ||
InternalMmapVector<Range> output; | ||
Intersect(std::get<1>(GetParam()), std::get<0>(GetParam()), output); | ||
EXPECT_EQ(std::get<2>(GetParam()), | ||
std::vector<Range>(output.begin(), output.end())); | ||
} | ||
} | ||
|
||
static void PrintTo(const Range &r, std::ostream *os) { | ||
*os << "[" << r.begin << ", " << r.end << ")"; | ||
} | ||
|
||
static const std::tuple<std::vector<Range>, std::vector<Range>, | ||
std::vector<Range>> | ||
kTests[] = { | ||
{{}, {}, {}}, | ||
{{{100, 1000}}, {{5000, 10000}}, {}}, | ||
{{{100, 1000}, {200, 2000}}, {{5000, 10000}, {6000, 11000}}, {}}, | ||
{{{100, 1000}}, {{100, 1000}}, {{100, 1000}}}, | ||
{{{100, 1000}}, {{50, 150}}, {{100, 150}}}, | ||
{{{100, 1000}}, {{150, 250}}, {{150, 250}}}, | ||
{{{100, 1000}, {100, 1000}}, {{100, 1000}}, {{100, 1000}}}, | ||
{{{100, 1000}}, {{500, 1500}}, {{500, 1000}}}, | ||
{{{100, 200}}, {{200, 300}, {1, 1000}}, {{100, 200}}}, | ||
{{{100, 200}, {200, 300}}, {{100, 300}}, {{100, 300}}}, | ||
{{{100, 200}, {200, 300}, {300, 400}}, {{150, 350}}, {{150, 350}}}, | ||
{{{100, 200}, {300, 400}, {500, 600}}, | ||
{{0, 1000}}, | ||
{{100, 200}, {300, 400}, {500, 600}}}, | ||
}; | ||
|
||
INSTANTIATE_TEST_SUITE_P(SanitizerCommonEmpty, SanitizerCommon, | ||
testing::ValuesIn(kTests)); | ||
|
||
} // namespace __sanitizer |