From 14b64f123d4ebc6f489d3034267ec34849ff3e5c Mon Sep 17 00:00:00 2001 From: vro Date: Tue, 24 Jan 2023 09:48:33 +0000 Subject: [PATCH] 0033320: Data Exchange - Reading of a VRML file with a long line fails Implement rolling back input stream to split on possible logical parts by comma or space. --- src/VrmlData/VrmlData_Scene.cxx | 72 ++++++++++++++++++++++++--------- tests/de_mesh/vrml_read/A5 | 16 ++++++++ 2 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 tests/de_mesh/vrml_read/A5 diff --git a/src/VrmlData/VrmlData_Scene.cxx b/src/VrmlData/VrmlData_Scene.cxx index ec8acc331c..1c851aab42 100644 --- a/src/VrmlData/VrmlData_Scene.cxx +++ b/src/VrmlData/VrmlData_Scene.cxx @@ -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; - } - } - theBuffer.LinePtr = &theBuffer.Line[0]; - theBuffer.IsProcessed = Standard_False; + { + 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; + } + } + 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 index 0000000000..ec4c1d9124 --- /dev/null +++ b/tests/de_mesh/vrml_read/A5 @@ -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