Fix null pointer deref for unknown class names.
PiperOrigin-RevId: 610391077 Change-Id: I5abd62ff46e31e788f06fe111adb3c25287d4fdc
This commit is contained in:
committed by
Copybara-Service
parent
b47d97652e
commit
8679c9fc59
@@ -346,6 +346,18 @@ mjmDefault* mjm_getDefault(mjElement element) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// find default in model by class name
|
||||||
|
mjmDefault* mjm_findDefault(mjmModel* modelspec, const char* classname) {
|
||||||
|
mjCModel* model = reinterpret_cast<mjCModel*>(modelspec->element);
|
||||||
|
mjCDef* cdef = model->FindDef(classname);
|
||||||
|
if (!cdef) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &cdef->spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// find body in model by name
|
// find body in model by name
|
||||||
mjmBody* mjm_findBody(mjmModel* modelspec, const char* name) {
|
mjmBody* mjm_findBody(mjmModel* modelspec, const char* name) {
|
||||||
mjCModel* model = reinterpret_cast<mjCModel*>(modelspec->element);
|
mjCModel* model = reinterpret_cast<mjCModel*>(modelspec->element);
|
||||||
|
|||||||
@@ -821,6 +821,9 @@ MJAPI mjmModel* mjm_getModel(mjmBody* body);
|
|||||||
// Get default corresponding to an mjElement.
|
// Get default corresponding to an mjElement.
|
||||||
MJAPI mjmDefault* mjm_getDefault(mjElement element);
|
MJAPI mjmDefault* mjm_getDefault(mjElement element);
|
||||||
|
|
||||||
|
// Find default in model by class name.
|
||||||
|
MJAPI mjmDefault* mjm_findDefault(mjmModel* model, const char* classname);
|
||||||
|
|
||||||
// Find body in model by name.
|
// Find body in model by name.
|
||||||
MJAPI mjmBody* mjm_findBody(mjmModel* model, const char* name);
|
MJAPI mjmBody* mjm_findBody(mjmModel* model, const char* name);
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
|
|
||||||
#include <mujoco/mjmodel.h>
|
#include <mujoco/mjmodel.h>
|
||||||
#include <mujoco/mjplugin.h>
|
#include <mujoco/mjplugin.h>
|
||||||
#include <mujoco/mjvisualize.h>
|
|
||||||
#include <mujoco/mjtnum.h>
|
#include <mujoco/mjtnum.h>
|
||||||
|
#include <mujoco/mjvisualize.h>
|
||||||
#include "engine/engine_plugin.h"
|
#include "engine/engine_plugin.h"
|
||||||
#include "engine/engine_util_errmem.h"
|
#include "engine/engine_util_errmem.h"
|
||||||
#include "engine/engine_util_misc.h"
|
#include "engine/engine_util_misc.h"
|
||||||
@@ -3986,12 +3986,14 @@ void mjXReader::Keyframe(XMLElement* section) {
|
|||||||
// get defaults class
|
// get defaults class
|
||||||
mjmDefault* mjXReader::GetClass(XMLElement* section) {
|
mjmDefault* mjXReader::GetClass(XMLElement* section) {
|
||||||
string text;
|
string text;
|
||||||
mjmDefault* def = 0;
|
mjmDefault* def = nullptr;
|
||||||
|
|
||||||
if (ReadAttrTxt(section, "class", text)) {
|
if (ReadAttrTxt(section, "class", text)) {
|
||||||
def = &model->FindDef(text)->spec;
|
def = mjm_findDefault(&model->spec, text.c_str());
|
||||||
if (!def) {
|
if (!def) {
|
||||||
throw mjXError(section, "unknown default class");
|
throw mjXError(
|
||||||
|
section,
|
||||||
|
std::string("unknown default class name '" + text + "'").c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,13 @@ namespace mujoco {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using ::std::string;
|
using ::std::string;
|
||||||
|
using ::testing::AllOf;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
|
using ::testing::FloatEq;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::IsNan;
|
using ::testing::IsNan;
|
||||||
using ::testing::IsNull;
|
using ::testing::IsNull;
|
||||||
using ::testing::NotNull;
|
using ::testing::NotNull;
|
||||||
using ::testing::FloatEq;
|
|
||||||
|
|
||||||
using XMLReaderTest = MujocoTest;
|
using XMLReaderTest = MujocoTest;
|
||||||
|
|
||||||
@@ -462,6 +463,29 @@ TEST_F(XMLReaderTest, RepeatedDefaultName) {
|
|||||||
EXPECT_THAT(error.data(), HasSubstr("repeated default class name"));
|
EXPECT_THAT(error.data(), HasSubstr("repeated default class name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(XMLReaderTest, InvalidDefaultClassName) {
|
||||||
|
static constexpr char xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<default>
|
||||||
|
<default class="sphere">
|
||||||
|
<geom type="sphere" size="1"/>
|
||||||
|
</default>
|
||||||
|
</default>
|
||||||
|
<worldbody>
|
||||||
|
<body>
|
||||||
|
<geom class="invalid"/>
|
||||||
|
</body>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||||
|
ASSERT_THAT(model, IsNull()) << error.data();
|
||||||
|
EXPECT_THAT(error.data(),
|
||||||
|
AllOf(HasSubstr("unknown default class name 'invalid'"),
|
||||||
|
HasSubstr("Element 'geom'"), HasSubstr("line 10")));
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------ test including -------------------------------------
|
// ------------------------ test including -------------------------------------
|
||||||
|
|
||||||
// credit: https://www.mjt.me.uk/posts/smallest-png/
|
// credit: https://www.mjt.me.uk/posts/smallest-png/
|
||||||
|
|||||||
Reference in New Issue
Block a user