Add mj_markStack and mj_freeStack as public API functions.

Also add asan instrumentation to detect stack frame leakages (i.e. `mj_markStack` without a corresponding `mj_freeStack` in the same caller function).

PiperOrigin-RevId: 562625645
Change-Id: I4e3ff66ca0b9d08ed0a95cef45393db8e3053e22
This commit is contained in:
Saran Tunyasuvunakool
2023-09-04 17:03:23 -07:00
committed by Copybara-Service
parent 9308e1d383
commit 94a8705ad0
17 changed files with 311 additions and 45 deletions
+12 -6
View File
@@ -27,18 +27,21 @@ namespace {
using testing::NotNull;
template <typename T, int N, int Capacity>
template <int prev_size, typename T, int N, int capacity>
constexpr int GetExpectedStackUsageBytes() {
if constexpr (N <= 0) {
return 0;
return prev_size;
} else {
constexpr auto RoundUpToAlignment =
[](int x, int alignment) {
return alignment * (x / alignment + ((x % alignment) ? 1 : 0));
};
return RoundUpToAlignment(sizeof(mjArrayList), alignof(mjArrayList)) +
RoundUpToAlignment(Capacity * sizeof(T), alignof(std::max_align_t)) +
GetExpectedStackUsageBytes<T, N - Capacity, 2 * Capacity>();
constexpr int size_with_arraylist = RoundUpToAlignment(
prev_size + sizeof(mjArrayList), alignof(mjArrayList));
constexpr int size_with_buffer = RoundUpToAlignment(
size_with_arraylist + capacity * sizeof(T), alignof(std::max_align_t));
return GetExpectedStackUsageBytes<size_with_buffer, T, N - capacity,
2 * capacity>();
}
}
@@ -48,6 +51,7 @@ TEST(TestMjArrayList, TestMjArrayListSingleThreaded) {
ASSERT_THAT(m, NotNull()) << "Failed to load model: " << error.data();
mjData* d = mj_makeData(m);
mjMARKSTACK;
using DataType = int;
constexpr int kInitialCapacity = 10;
mjArrayList* array_list =
@@ -59,8 +63,10 @@ TEST(TestMjArrayList, TestMjArrayListSingleThreaded) {
}
EXPECT_EQ(mju_arrayListSize(array_list), kNumElements);
constexpr int kFrameMarkerSize = 2 * sizeof(size_t) + sizeof(void*);
constexpr int kExpectedMaxUseStack =
GetExpectedStackUsageBytes<DataType, kNumElements, kInitialCapacity>();
GetExpectedStackUsageBytes<kFrameMarkerSize, DataType, kNumElements,
kInitialCapacity>();
EXPECT_EQ(d->maxuse_stack, kExpectedMaxUseStack);
for (int i = 0; i < kNumElements; ++i) {