Make MuJoCo work with -fsanitize=alignment.
PiperOrigin-RevId: 563702045 Change-Id: Ieca69595b7e2fc1e35ca69754d7cc7971825f48b
This commit is contained in:
committed by
Copybara-Service
parent
7e5a7b76fc
commit
a07e172770
+11
-4
@@ -1289,16 +1289,23 @@ static inline void* stackalloc(mjData* d, size_t size, size_t alignment) {
|
|||||||
#ifdef ADDRESS_SANITIZER
|
#ifdef ADDRESS_SANITIZER
|
||||||
// actual stack usage (without red zone bytes) is stored in the red zone
|
// actual stack usage (without red zone bytes) is stored in the red zone
|
||||||
if (d->pstack) {
|
if (d->pstack) {
|
||||||
size_t* prev_usage_ptr = (size_t*)(end_of_arena_ptr - d->pstack);
|
char* prev_pstack_ptr = (char*)(end_of_arena_ptr - d->pstack);
|
||||||
|
size_t prev_misalign = (uintptr_t)prev_pstack_ptr % _Alignof(size_t);
|
||||||
|
size_t* prev_usage_ptr =
|
||||||
|
(size_t*)(prev_pstack_ptr +
|
||||||
|
(prev_misalign ? _Alignof(size_t) - prev_misalign : 0));
|
||||||
ASAN_UNPOISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
ASAN_UNPOISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
||||||
usage = current_alloc_usage + *prev_usage_ptr;
|
usage = current_alloc_usage + *prev_usage_ptr;
|
||||||
ASAN_POISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
ASAN_POISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// store new stack usage in the red zone
|
// store new stack usage in the red zone
|
||||||
ASAN_UNPOISON_MEMORY_REGION((void*)new_pstack_ptr, sizeof(size_t));
|
size_t misalign = new_pstack_ptr % _Alignof(size_t);
|
||||||
*(size_t*)new_pstack_ptr = usage;
|
size_t* usage_ptr =
|
||||||
ASAN_POISON_MEMORY_REGION((void*)new_pstack_ptr, sizeof(size_t));
|
(size_t*)(new_pstack_ptr + (misalign ? _Alignof(size_t) - misalign : 0));
|
||||||
|
ASAN_UNPOISON_MEMORY_REGION(usage_ptr, sizeof(size_t));
|
||||||
|
*usage_ptr = usage;
|
||||||
|
ASAN_POISON_MEMORY_REGION(usage_ptr, sizeof(size_t));
|
||||||
|
|
||||||
// unpoison the actual usable allocation
|
// unpoison the actual usable allocation
|
||||||
ASAN_UNPOISON_MEMORY_REGION((void*)start_ptr, size);
|
ASAN_UNPOISON_MEMORY_REGION((void*)start_ptr, size);
|
||||||
|
|||||||
+18
-9
@@ -114,6 +114,12 @@ static T* VecToArray(std::vector<T>& vector, bool clear = true){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read data of type T from a potentially unaligned buffer pointer.
|
||||||
|
template <typename T>
|
||||||
|
static void ReadFromBuffer(T* dst, const char* src) {
|
||||||
|
std::memcpy(dst, src, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
//------------------ class mjCMesh implementation --------------------------------------------------
|
//------------------ class mjCMesh implementation --------------------------------------------------
|
||||||
|
|
||||||
mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) {
|
mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) {
|
||||||
@@ -961,7 +967,7 @@ void mjCMesh::LoadSTL(mjResource* resource) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get number of triangles, check bounds
|
// get number of triangles, check bounds
|
||||||
nface_ = *(unsigned int*)(buffer+80);
|
ReadFromBuffer(&nface_, buffer + 80);
|
||||||
if (nface_<1 || nface_>200000) {
|
if (nface_<1 || nface_>200000) {
|
||||||
throw mjCError(this,
|
throw mjCError(this,
|
||||||
"number of faces should be between 1 and 200000 in STL file '%s';"
|
"number of faces should be between 1 and 200000 in STL file '%s';"
|
||||||
@@ -985,8 +991,10 @@ void mjCMesh::LoadSTL(mjResource* resource) {
|
|||||||
// add vertices and faces, including repeated for now
|
// add vertices and faces, including repeated for now
|
||||||
for (int i=0; i<nface_; i++) {
|
for (int i=0; i<nface_; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j<3; j++) {
|
||||||
// get pointer to vertex coordiates
|
// read vertex coordinates
|
||||||
float* v = (float*)(stl+50*i+12*(j+1));
|
float v[3];
|
||||||
|
ReadFromBuffer(&v, stl+50*i+12*(j+1));
|
||||||
|
|
||||||
for (int k=0; k < 3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
if (std::isnan(v[k]) || std::isinf(v[k])) {
|
if (std::isnan(v[k]) || std::isinf(v[k])) {
|
||||||
throw mjCError(this, "STL file '%s' contains invalid vertices.",
|
throw mjCError(this, "STL file '%s' contains invalid vertices.",
|
||||||
@@ -1039,10 +1047,10 @@ void mjCMesh::LoadMSH(mjResource* resource) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get sizes from header
|
// get sizes from header
|
||||||
nvert_ = ((int*)buffer)[0];
|
ReadFromBuffer(&nvert_, buffer);
|
||||||
nnormal_ = ((int*)buffer)[1];
|
ReadFromBuffer(&nnormal_, buffer + sizeof(int));
|
||||||
ntexcoord_ = ((int*)buffer)[2];
|
ReadFromBuffer(&ntexcoord_, buffer + 2*sizeof(int));
|
||||||
nface_ = ((int*)buffer)[3];
|
ReadFromBuffer(&nface_, buffer + 3*sizeof(int));
|
||||||
|
|
||||||
// check sizes
|
// check sizes
|
||||||
if (nvert_<4 || nface_<0 || nnormal_<0 || ntexcoord_<0 ||
|
if (nvert_<4 || nface_<0 || nnormal_<0 || ntexcoord_<0 ||
|
||||||
@@ -1058,7 +1066,8 @@ void mjCMesh::LoadMSH(mjResource* resource) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allocate and copy
|
// allocate and copy
|
||||||
float* fdata = (float*)(((int*)buffer) + 4);
|
using UnalignedFloat = char[sizeof(float)];
|
||||||
|
auto fdata = reinterpret_cast<UnalignedFloat*>(buffer + 4*sizeof(int));
|
||||||
if (nvert_) {
|
if (nvert_) {
|
||||||
vert_ = (float*) mju_malloc(3*nvert_*sizeof(float));
|
vert_ = (float*) mju_malloc(3*nvert_*sizeof(float));
|
||||||
memcpy(vert_, fdata, 3*nvert_*sizeof(float));
|
memcpy(vert_, fdata, 3*nvert_*sizeof(float));
|
||||||
@@ -1085,7 +1094,7 @@ void mjCMesh::LoadMSH(mjResource* resource) {
|
|||||||
memcpy(facetexcoord_, fdata, 3*nface_*sizeof(int));
|
memcpy(facetexcoord_, fdata, 3*nface_*sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
// rearange face data if left-handed scaling
|
// rearrange face data if left-handed scaling
|
||||||
if (nface_ && !righthand) {
|
if (nface_ && !righthand) {
|
||||||
for (int i=0; i<nface_; i++) {
|
for (int i=0; i<nface_; i++) {
|
||||||
int tmp = face_[3*i+1];
|
int tmp = face_[3*i+1];
|
||||||
|
|||||||
@@ -813,6 +813,30 @@ TEST_F(EngineIoTest, CanDetectStackFrameLeakage) {
|
|||||||
mj_deleteData(data);
|
mj_deleteData(data);
|
||||||
mj_deleteModel(model);
|
mj_deleteModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(EngineIoTest, RedZoneAlignmentTest) {
|
||||||
|
static constexpr char xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<worldbody>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||||
|
ASSERT_THAT(model, NotNull()) << "Failed to load model: " << error.data();
|
||||||
|
|
||||||
|
mjData* data = mj_makeData(model);
|
||||||
|
ASSERT_THAT(data, NotNull());
|
||||||
|
|
||||||
|
mj_markStack(data);
|
||||||
|
mj_stackAlloc(data, 1, 1);
|
||||||
|
mj_stackAlloc(data, 1, 1);
|
||||||
|
mj_freeStack(data);
|
||||||
|
|
||||||
|
mj_deleteData(data);
|
||||||
|
mj_deleteModel(model);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user