diff --git a/modules/objdetect/src/aruco/aruco_dictionary.cpp b/modules/objdetect/src/aruco/aruco_dictionary.cpp index 3e975c00bf..3779e3fb94 100644 --- a/modules/objdetect/src/aruco/aruco_dictionary.cpp +++ b/modules/objdetect/src/aruco/aruco_dictionary.cpp @@ -109,6 +109,8 @@ bool Dictionary::readDictionary(const cv::FileNode& fn) { int nMarkers = 0, _markerSize = 0; if (fn.empty() || !readParameter("nmarkers", nMarkers, fn) || !readParameter("markersize", _markerSize, fn)) return false; + if (_markerSize <= 0) + return false; Mat bytes(0, 0, CV_8UC1), marker(_markerSize, _markerSize, CV_8UC1); std::string markerString; for (int i = 0; i < nMarkers; i++) { @@ -116,6 +118,8 @@ bool Dictionary::readDictionary(const cv::FileNode& fn) { ostr << i; if (!readParameter("marker_" + ostr.str(), markerString, fn)) return false; + if (markerString.size() != (size_t)_markerSize * _markerSize) + return false; for (int j = 0; j < (int) markerString.size(); j++) marker.at(j) = (markerString[j] == '0') ? 0 : 1; bytes.push_back(Dictionary::getByteListFromBits(marker)); diff --git a/modules/objdetect/test/test_arucodetection.cpp b/modules/objdetect/test/test_arucodetection.cpp index 53f4302cc0..8b850eda1f 100644 --- a/modules/objdetect/test/test_arucodetection.cpp +++ b/modules/objdetect/test/test_arucodetection.cpp @@ -1409,6 +1409,46 @@ TEST(CV_ArucoMultiDict, serialization) } +TEST(CV_ArucoDictionary, readDictionary_oversized_marker) +{ + // A marker string longer than markersize*markersize must be rejected instead of + // being written past the markersize x markersize buffer in readDictionary. + std::string serialized; + { + FileStorage fs_out(".json", FileStorage::WRITE + FileStorage::MEMORY); + ASSERT_TRUE(fs_out.isOpened()); + fs_out << "nmarkers" << 1; + fs_out << "markersize" << 5; + fs_out << "marker_0" << std::string(2000, '1'); + serialized = fs_out.releaseAndGetString(); + } + FileStorage fs_in(serialized, FileStorage::READ + FileStorage::MEMORY); + ASSERT_TRUE(fs_in.isOpened()); + aruco::Dictionary dict; + bool ok = true; + ASSERT_NO_THROW(ok = dict.readDictionary(fs_in.root())); + EXPECT_FALSE(ok); +} + + +TEST(CV_ArucoDictionary, readDictionary_roundtrip) +{ + aruco::Dictionary dict = aruco::getPredefinedDictionary(aruco::DICT_5X5_50); + std::string serialized; + { + FileStorage fs_out(".json", FileStorage::WRITE + FileStorage::MEMORY); + ASSERT_TRUE(fs_out.isOpened()); + dict.writeDictionary(fs_out); + serialized = fs_out.releaseAndGetString(); + } + FileStorage fs_in(serialized, FileStorage::READ + FileStorage::MEMORY); + ASSERT_TRUE(fs_in.isOpened()); + aruco::Dictionary loaded; + ASSERT_TRUE(loaded.readDictionary(fs_in.root())); + EXPECT_EQ(dict, loaded); +} + + struct ArucoThreading: public testing::TestWithParam { struct NumThreadsSetter {