Make load failed for invalid bvh format 63/296363/2
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 26 Jul 2023 06:18:53 +0000 (15:18 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Wed, 26 Jul 2023 06:54:06 +0000 (15:54 +0900)
Let we exist bvh parsing when it have some invalid informations.

Change-Id: I82f090b6207911ef9c49cbbbba8123c6cdeb46ab
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
15 files changed:
automated-tests/resources/test-empty.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy0.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy1.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy2.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy3.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy4.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy5.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy6.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy7.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion0.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion1.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion2.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion3.bvh [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp
dali-scene3d/public-api/loader/bvh-loader.cpp

diff --git a/automated-tests/resources/test-empty.bvh b/automated-tests/resources/test-empty.bvh
new file mode 100644 (file)
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 (file)
index 0000000..c8c0cb8
--- /dev/null
@@ -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 (file)
index 0000000..be6cd56
--- /dev/null
@@ -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 (file)
index 0000000..3bb962a
--- /dev/null
@@ -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 (file)
index 0000000..3ff6a12
--- /dev/null
@@ -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 (file)
index 0000000..3175816
--- /dev/null
@@ -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 (file)
index 0000000..576adae
--- /dev/null
@@ -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 (file)
index 0000000..6f64833
--- /dev/null
@@ -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 (file)
index 0000000..058fde0
--- /dev/null
@@ -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 (file)
index 0000000..37a8bdc
--- /dev/null
@@ -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 (file)
index 0000000..1bba75a
--- /dev/null
@@ -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 (file)
index 0000000..c003a2d
--- /dev/null
@@ -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 (file)
index 0000000..0a4a582
--- /dev/null
@@ -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
index d642ef4db9472c36f8ebd9d46eeb4f03a00ad5b6..4fb5a79ec6d2e810578925559b209759c7fd72e6 100644 (file)
@@ -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
index 3930d333a674fe2195f4305b182955424a2ba13c..7bff27fbf30a31bf4304e32e1c047d9afb019fdc 100644 (file)
@@ -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>& joint)
+bool ParseHierarchy(std::istream& file, std::shared_ptr<Joint>& 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)
       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>& joint, std::vector<std::shared_ptr<Joint>>& jointList)
@@ -171,7 +217,7 @@ void MakeList(std::shared_ptr<Joint>& joint, std::vector<std::shared_ptr<Joint>>
   }
 }
 
-void ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t& frameCount, float& frameTime)
+bool ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t& frameCount, float& frameTime)
 {
   std::vector<std::shared_ptr<Joint>> jointList;
   MakeList(hierarchy, jointList);
@@ -198,10 +244,33 @@ void ParseMotion(std::istream& file, std::shared_ptr<Joint>& 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<Joint>& 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<Joint>& 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<Joint>& hierarchy, uint32_t frameCount, float frameTime, const Vector3& scale)