From 5374971f6bf2f8ddc5827f4bffcc50965f5b6b78 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Wed, 26 Jul 2023 15:18:53 +0900 Subject: [PATCH] Make load failed for invalid bvh format Let we exist bvh parsing when it have some invalid informations. Change-Id: I82f090b6207911ef9c49cbbbba8123c6cdeb46ab Signed-off-by: Eunki, Hong --- automated-tests/resources/test-empty.bvh | 0 .../resources/test-invalid-hierarchy0.bvh | 19 +++++ .../resources/test-invalid-hierarchy1.bvh | 19 +++++ .../resources/test-invalid-hierarchy2.bvh | 18 +++++ .../resources/test-invalid-hierarchy3.bvh | 19 +++++ .../resources/test-invalid-hierarchy4.bvh | 19 +++++ .../resources/test-invalid-hierarchy5.bvh | 18 +++++ .../resources/test-invalid-hierarchy6.bvh | 22 +++++ .../resources/test-invalid-hierarchy7.bvh | 22 +++++ automated-tests/resources/test-invalid-motion0.bvh | 21 +++++ automated-tests/resources/test-invalid-motion1.bvh | 20 +++++ automated-tests/resources/test-invalid-motion2.bvh | 19 +++++ automated-tests/resources/test-invalid-motion3.bvh | 19 +++++ .../src/dali-scene3d/utc-Dali-BvhLoader.cpp | 33 ++++++++ dali-scene3d/public-api/loader/bvh-loader.cpp | 93 ++++++++++++++++++++-- 15 files changed, 354 insertions(+), 7 deletions(-) create mode 100644 automated-tests/resources/test-empty.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy0.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy1.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy2.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy3.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy4.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy5.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy6.bvh create mode 100644 automated-tests/resources/test-invalid-hierarchy7.bvh create mode 100644 automated-tests/resources/test-invalid-motion0.bvh create mode 100644 automated-tests/resources/test-invalid-motion1.bvh create mode 100644 automated-tests/resources/test-invalid-motion2.bvh create mode 100644 automated-tests/resources/test-invalid-motion3.bvh diff --git a/automated-tests/resources/test-empty.bvh b/automated-tests/resources/test-empty.bvh new file mode 100644 index 0000000..e69de29 diff --git a/automated-tests/resources/test-invalid-hierarchy0.bvh b/automated-tests/resources/test-invalid-hierarchy0.bvh new file mode 100644 index 0000000..c8c0cb8 --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy0.bvh @@ -0,0 +1,19 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy1.bvh b/automated-tests/resources/test-invalid-hierarchy1.bvh new file mode 100644 index 0000000..be6cd56 --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy1.bvh @@ -0,0 +1,19 @@ +HIERARCHY +ROOT root + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +} +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy2.bvh b/automated-tests/resources/test-invalid-hierarchy2.bvh new file mode 100644 index 0000000..3bb962a --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy2.bvh @@ -0,0 +1,18 @@ +HIERARCHY +ROOT root + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy3.bvh b/automated-tests/resources/test-invalid-hierarchy3.bvh new file mode 100644 index 0000000..3ff6a12 --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy3.bvh @@ -0,0 +1,19 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } +} +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy4.bvh b/automated-tests/resources/test-invalid-hierarchy4.bvh new file mode 100644 index 0000000..3175816 --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy4.bvh @@ -0,0 +1,19 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + OFFSET 0 0 0 + } + } +} +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy5.bvh b/automated-tests/resources/test-invalid-hierarchy5.bvh new file mode 100644 index 0000000..576adae --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy5.bvh @@ -0,0 +1,18 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + OFFSET 0 0 0 + } +} +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy6.bvh b/automated-tests/resources/test-invalid-hierarchy6.bvh new file mode 100644 index 0000000..6f64833 --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy6.bvh @@ -0,0 +1,22 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + { + OFFSET 0 0 0 + } + } + } +} +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-hierarchy7.bvh b/automated-tests/resources/test-invalid-hierarchy7.bvh new file mode 100644 index 0000000..058fde0 --- /dev/null +++ b/automated-tests/resources/test-invalid-hierarchy7.bvh @@ -0,0 +1,22 @@ +HIERARCHY +ROOT root +{ + { + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } + } +} +MOTION +Frames: 2 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-motion0.bvh b/automated-tests/resources/test-invalid-motion0.bvh new file mode 100644 index 0000000..37a8bdc --- /dev/null +++ b/automated-tests/resources/test-invalid-motion0.bvh @@ -0,0 +1,21 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +} +MOTION +Frames: 3 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-motion1.bvh b/automated-tests/resources/test-invalid-motion1.bvh new file mode 100644 index 0000000..1bba75a --- /dev/null +++ b/automated-tests/resources/test-invalid-motion1.bvh @@ -0,0 +1,20 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +} +MOTION +Frames: 1 +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-motion2.bvh b/automated-tests/resources/test-invalid-motion2.bvh new file mode 100644 index 0000000..c003a2d --- /dev/null +++ b/automated-tests/resources/test-invalid-motion2.bvh @@ -0,0 +1,19 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +} +MOTION +Frame Time: 0.3 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/resources/test-invalid-motion3.bvh b/automated-tests/resources/test-invalid-motion3.bvh new file mode 100644 index 0000000..0a4a582 --- /dev/null +++ b/automated-tests/resources/test-invalid-motion3.bvh @@ -0,0 +1,19 @@ +HIERARCHY +ROOT root +{ + OFFSET 0.0 -0.948831 1.32574 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + JOINT first + { + OFFSET -0.0 4.130377 -0.008512 + CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation + End Site + { + OFFSET 0 0 0 + } + } +} +MOTION +Frames: 2 +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0 \ No newline at end of file diff --git a/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp b/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp index d642ef4..4fb5a79 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp @@ -154,4 +154,37 @@ int UtcDaliLoadBvhFailed02(void) AnimationDefinition animDef = LoadBvhFromBuffer(nullptr, 0, "testBvh"); DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION); END_TEST; +} + +int UtcDaliLoadBvhFailed03(void) +{ + TestApplication application; + + tet_infoline("Parse error for hierarchy1"); + uint32_t caseHierarchyCount = 8; + for(uint32_t tc = 0; tc < caseHierarchyCount; ++tc) + { + tet_printf("Parse error for hierarchy %u\n", tc); + std::ostringstream oss; + oss << TEST_RESOURCE_DIR << "/test-invalid-hierarchy" << tc << ".bvh"; + AnimationDefinition animDef = LoadBvh(oss.str(), "testBvh"); + DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION); + } + + uint32_t caseMotionCount = 4; + for(uint32_t tc = 0; tc < caseMotionCount; ++tc) + { + tet_printf("Parse error for motion %u\n", tc); + std::ostringstream oss; + oss << TEST_RESOURCE_DIR << "/test-invalid-motion" << tc << ".bvh"; + AnimationDefinition animDef = LoadBvh(oss.str(), "testBvh"); + DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION); + } + + { + tet_infoline("empty file"); + AnimationDefinition animDef = LoadBvh(TEST_RESOURCE_DIR "/test-empty.bvh", "testBvh"); + DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION); + } + END_TEST; } \ No newline at end of file diff --git a/dali-scene3d/public-api/loader/bvh-loader.cpp b/dali-scene3d/public-api/loader/bvh-loader.cpp index 3930d33..7bff27f 100644 --- a/dali-scene3d/public-api/loader/bvh-loader.cpp +++ b/dali-scene3d/public-api/loader/bvh-loader.cpp @@ -49,6 +49,7 @@ static constexpr std::string_view TOKEN_ROOT = "ROOT"; static constexpr std::string_view TOKEN_MOTION = "MOTION"; static constexpr std::string_view PROPERTY_NAME_POSITION = "position"; static constexpr std::string_view PROPERTY_NAME_ORIENTATION = "orientation"; +static constexpr std::string_view TOKEN_OPENING_BRACE = "{"; static constexpr std::string_view TOKEN_CLOSING_BRACE = "}"; enum class Channel @@ -87,9 +88,10 @@ void trim(std::string& s) s.end()); } -void ParseHierarchy(std::istream& file, std::shared_ptr& joint) +bool ParseHierarchy(std::istream& file, std::shared_ptr& joint) { std::string line; + bool braceExist = false; while(std::getline(file, line)) { trim(line); @@ -142,24 +144,68 @@ void ParseHierarchy(std::istream& file, std::shared_ptr& joint) joint->children.push_back(child); std::getline(stream, token, ' '); child->name = token; - ParseHierarchy(file, child); + + if(DALI_UNLIKELY(!ParseHierarchy(file, child))) + { + return false; + } } else if(line == TOKEN_END_SITE.data()) { + bool braceExistEndSite = false; while(std::getline(file, line)) { trim(line); - if(line == TOKEN_CLOSING_BRACE.data()) + if(line == TOKEN_OPENING_BRACE.data()) + { + if(DALI_UNLIKELY(braceExistEndSite)) + { + DALI_LOG_ERROR("Parsing error : Joint[%s] End Site opening brace not matched\n", joint->name.c_str()); + return false; + } + braceExistEndSite = true; + } + else if(line == TOKEN_CLOSING_BRACE.data()) { + if(DALI_UNLIKELY(!braceExistEndSite)) + { + DALI_LOG_ERROR("Parsing error : Joint[%s] End Site closing brace not matched\n", joint->name.c_str()); + return false; + } break; } } + if(DALI_UNLIKELY(!braceExistEndSite)) + { + DALI_LOG_ERROR("Parsing error : Joint[%s] End Site opening brace not exist\n", joint->name.c_str()); + return false; + } + } + else if(line == TOKEN_OPENING_BRACE.data()) + { + if(DALI_UNLIKELY(braceExist)) + { + DALI_LOG_ERROR("Parsing error : Joint[%s] opening brace not matched\n", joint->name.c_str()); + return false; + } + braceExist = true; } else if(token == TOKEN_CLOSING_BRACE.data()) { + if(DALI_UNLIKELY(!braceExist)) + { + DALI_LOG_ERROR("Parsing error : Joint[%s] closing brace not matched\n", joint->name.c_str()); + return false; + } break; } } + if(DALI_UNLIKELY(!braceExist)) + { + DALI_LOG_ERROR("Parsing error : Joint[%s] opening brace not exist\n", joint->name.c_str()); + return false; + } + return true; } void MakeList(std::shared_ptr& joint, std::vector>& jointList) @@ -171,7 +217,7 @@ void MakeList(std::shared_ptr& joint, std::vector> } } -void ParseMotion(std::istream& file, std::shared_ptr& hierarchy, uint32_t& frameCount, float& frameTime) +bool ParseMotion(std::istream& file, std::shared_ptr& hierarchy, uint32_t& frameCount, float& frameTime) { std::vector> jointList; MakeList(hierarchy, jointList); @@ -198,10 +244,33 @@ void ParseMotion(std::istream& file, std::shared_ptr& hierarchy, uint32_t } } + if(DALI_UNLIKELY(!frameCountLoaded)) + { + DALI_LOG_ERROR("Parsing error : Frames not exist!\n"); + return false; + } + if(DALI_UNLIKELY(!frameTimeLoaded)) + { + DALI_LOG_ERROR("Parsing error : Frame Time not exist!\n"); + return false; + } + + uint32_t loadedFrameCount = 0u; + while(std::getline(file, line)) { trim(line); + if(DALI_UNLIKELY(line.empty())) + { + continue; + } std::istringstream stream(line); + if(DALI_UNLIKELY(++loadedFrameCount > frameCount)) + { + // Parse failed. Just skip decoding, and get the number of line for debug. + continue; + } + for(auto&& joint : jointList) { Vector3 translation; @@ -243,11 +312,21 @@ void ParseMotion(std::istream& file, std::shared_ptr& hierarchy, uint32_t joint->rotations.push_back(rotation[2] * rotation[0] * rotation[1]); } } + + if(DALI_UNLIKELY(loadedFrameCount != frameCount)) + { + DALI_LOG_ERROR("Parsing error : Motion frame count not matched! expect : %u, loaded : %u\n", frameCount, loadedFrameCount); + return false; + } + + return true; } bool ParseBvh(std::istream& file, uint32_t& frameCount, float& frameTime, std::shared_ptr& rootJoint) { std::string line; + bool parseHierarchy = false; + bool parseMotion = false; while(std::getline(file, line)) { trim(line); @@ -267,17 +346,17 @@ bool ParseBvh(std::istream& file, uint32_t& frameCount, float& frameTime, std::s { std::getline(stream, token, ' '); rootJoint->name = token; - ParseHierarchy(file, rootJoint); + parseHierarchy = ParseHierarchy(file, rootJoint); break; } } } if(token == TOKEN_MOTION.data()) { - ParseMotion(file, rootJoint, frameCount, frameTime); + parseMotion = ParseMotion(file, rootJoint, frameCount, frameTime); } } - return true; + return parseHierarchy && parseMotion; } AnimationDefinition GenerateAnimation(const std::string& animationName, std::shared_ptr& hierarchy, uint32_t frameCount, float frameTime, const Vector3& scale) -- 2.7.4