diff --git a/src/engine/engine_io.c b/src/engine/engine_io.c index c6380960..d8a85059 100644 --- a/src/engine/engine_io.c +++ b/src/engine/engine_io.c @@ -1282,7 +1282,11 @@ const char* mj_validateReferences(const mjModel* m) { int *nums = (numarray); \ for (int i=0; inadrs; i++) { \ int adrsmin = m->adrarray[i]; \ - int adrsmax = m->adrarray[i] + (nums ? nums[i] : 1); \ + int num = (nums ? nums[i] : 1); \ + if (num < 0) { \ + return "Invalid model: " #numarray " is negative."; \ + } \ + int adrsmax = m->adrarray[i] + num; \ if (adrsmax > m->ntarget || adrsmin < -1) { \ return "Invalid model: " #adrarray " out of bounds."; \ } \ diff --git a/test/engine/engine_io_test.cc b/test/engine/engine_io_test.cc index 034b9069..2407c37c 100644 --- a/test/engine/engine_io_test.cc +++ b/test/engine/engine_io_test.cc @@ -257,6 +257,32 @@ TEST_F(ValidateReferencesTest, AddressRange) { mj_deleteModel(model); } +TEST_F(ValidateReferencesTest, AddressRangeNegativeNum) { + static const char xml[] = R"( + + + + + + + + + + )"; + + std::array error; + mjModel* model = LoadModelFromString(xml, error.data(), error.size()); + ASSERT_THAT(model, NotNull()) << "Failed to load model: " << error.data(); + + EXPECT_THAT(mj_validateReferences(model), IsNull()); + + // jntadr + jntnum is within safe range, but jntnum is negative. + model->body_jntadr[1] += 5; + model->body_jntnum[1] -= 5; + EXPECT_THAT(mj_validateReferences(model), HasSubstr("body_jntnum")); + mj_deleteModel(model); +} + TEST_F(ValidateReferencesTest, GeomCondim) { static const char xml[] = R"(