]> OCCT Git - occt.git/commitdiff
0033320: Data Exchange - Reading of a VRML file with a long line fails IR-2023-01-27
authorvro <vro@opencascade.com>
Tue, 24 Jan 2023 09:48:33 +0000 (09:48 +0000)
committerdpasukhi <dpasukhi@opencascade.com>
Tue, 24 Jan 2023 22:38:57 +0000 (22:38 +0000)
Implement rolling back input stream to split on possible logical parts by comma or space.

src/VrmlData/VrmlData_Scene.cxx
tests/de_mesh/vrml_read/A5 [new file with mode: 0644]

index ec8acc331ce2345e19681fdaa0bb37c02fcc6db7..1c851aab428ec64275df11cba3156b13a2da125e 100644 (file)
@@ -194,29 +194,63 @@ const Handle(VrmlData_WorldInfo)& VrmlData_Scene::WorldInfo() const
 //purpose  : 
 //=======================================================================
 
-VrmlData_ErrorStatus VrmlData_Scene::readLine (VrmlData_InBuffer& theBuffer)
+VrmlData_ErrorStatus VrmlData_Scene::readLine(VrmlData_InBuffer& theBuffer)
 {
   VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
   if (theBuffer.Input.eof())
-    aStatus = VrmlData_EndOfFile;
-  else {
-    theBuffer.Input.getline (theBuffer.Line, sizeof(theBuffer.Line));
-    theBuffer.LineCount++;
-    const int stat = theBuffer.Input.rdstate();
-    if (stat & std::ios::badbit) {
-      aStatus = VrmlData_UnrecoverableError;
-    }
-    else if (stat & std::ios::failbit) {
-      if (stat & std::ios::eofbit) {
-        aStatus = VrmlData_EndOfFile;
-      }
-      else {
-        aStatus = VrmlData_GeneralError;
+  {
+    return VrmlData_EndOfFile;
+  }
+  // Read a line.
+  theBuffer.Input.getline(theBuffer.Line, sizeof(theBuffer.Line));
+
+  // Check the number of read symbols.
+  // If maximum number is read, process the array of symbols separately
+  // rolling back the array to the last comma or space symbol.
+  std::streamsize aNbChars = theBuffer.Input.gcount();
+  if (theBuffer.Input.rdstate() & std::ios::failbit &&
+      aNbChars == sizeof(theBuffer.Line) - 1)
+  {
+    // Clear the error.
+    // We will fix it here below.
+    theBuffer.Input.clear();
+    size_t anInd = aNbChars - 1;
+    for (; anInd > 0; anInd--)
+    {
+      Standard_Character aChar = theBuffer.Line[anInd];
+      if (aChar == ',' || aChar == ' ')
+      {
+        theBuffer.Line[anInd + 1] = '\0';
+        break;
       }
     }
-    theBuffer.LinePtr = &theBuffer.Line[0];
-    theBuffer.IsProcessed = Standard_False;
+    if (anInd == 0) // no possible to rolling back
+    {
+      return VrmlData_UnrecoverableError;
+    }
+    theBuffer.Input.seekg(-(aNbChars - anInd - 1), std::ios::cur);
+  }
+
+  // Check the reading status.
+  theBuffer.LineCount++;
+  const int stat = theBuffer.Input.rdstate();
+  if (stat & std::ios::badbit)
+  {
+    aStatus = VrmlData_UnrecoverableError;
+  }
+  else if (stat & std::ios::failbit)
+  {
+    if (stat & std::ios::eofbit)
+    {
+      aStatus = VrmlData_EndOfFile;
+    }
+    else
+    {
+      aStatus = VrmlData_GeneralError;
+    }
   }
+  theBuffer.LinePtr = &theBuffer.Line[0];
+  theBuffer.IsProcessed = Standard_False;
   return aStatus;
 }
 
diff --git a/tests/de_mesh/vrml_read/A5 b/tests/de_mesh/vrml_read/A5
new file mode 100644 (file)
index 0000000..ec4c1d9
--- /dev/null
@@ -0,0 +1,16 @@
+puts "============"
+puts "0033320: Data Exchange - Reading of a VRML file with a long line fails"
+puts "============"
+puts ""
+
+set aFile [locate_data_file bug33320_wM_BugBlender_2.wrl]
+
+catch { Close D }
+
+ReadVrml D $aFile
+vinit Driver1/View_${casename}/${casename}
+XDisplay D -dispMode 1
+vfit
+checkview -screenshot -3d -path ${imagedir}/${test_image}.png
+
+Close D