0028736: An error to read a binary OCAF document of > 2Gb
authorvro <vro@opencascade.com>
Tue, 16 May 2017 07:48:29 +0000 (10:48 +0300)
committerabv <abv@opencascade.com>
Thu, 18 May 2017 13:48:50 +0000 (16:48 +0300)
A binary file of OCAF document contains file-position of several sections (header section, shape section).
This file-position represents an integer value.
For document files of less than 2Gb it is enough to use "int" type to keep the file-position.
But for greater document files we need more digits.
The fix consists in extension of the type for keeping of file-position within the document file on disk: it was "int", now it is "uint64_t".

src/BinLDrivers/BinLDrivers.cxx
src/BinLDrivers/BinLDrivers_DocumentSection.cxx
src/BinLDrivers/BinLDrivers_DocumentSection.hxx
src/FSD/FSD_BinaryFile.cxx
src/FSD/FSD_BinaryFile.hxx

index 7c689c8..17c0893 100644 (file)
@@ -33,7 +33,7 @@
 //#include <BinMNaming.hxx>
 static Standard_GUID BinLStorageDriver  ("13a56835-8269-11d5-aab2-0050044b1af1");
 static Standard_GUID BinLRetrievalDriver("13a56836-8269-11d5-aab2-0050044b1af1");
-#define CURRENT_DOCUMENT_VERSION 9
+#define CURRENT_DOCUMENT_VERSION 10
 
 //=======================================================================
 //function : Factory
index 1fab06a..1032888 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <BinLDrivers_DocumentSection.hxx>
 #include <FSD_FileHeader.hxx>
+#include <BinMDataStd.hxx>
 
 //=======================================================================
 //function : BinLDrivers_DocumentSection
@@ -58,7 +59,7 @@ const TCollection_AsciiString&  BinLDrivers_DocumentSection::Name () const
 //purpose  : 
 //=======================================================================
 
-Standard_Size BinLDrivers_DocumentSection::Offset () const
+uint64_t BinLDrivers_DocumentSection::Offset () const
 {
   return myValue[0];
 }
@@ -68,7 +69,7 @@ Standard_Size BinLDrivers_DocumentSection::Offset () const
 //purpose  : 
 //=======================================================================
 
-void BinLDrivers_DocumentSection::SetOffset (const Standard_Size theOffset)
+void BinLDrivers_DocumentSection::SetOffset (const uint64_t theOffset)
 {
   myValue[0] = theOffset;
 }
@@ -88,7 +89,7 @@ Standard_Boolean BinLDrivers_DocumentSection::IsPostRead () const
 //purpose  : 
 //=======================================================================
 
-Standard_Size BinLDrivers_DocumentSection::Length () const
+uint64_t BinLDrivers_DocumentSection::Length () const
 {
   return myValue[1];
 }
@@ -98,7 +99,7 @@ Standard_Size BinLDrivers_DocumentSection::Length () const
 //purpose  : 
 //=======================================================================
 
-void BinLDrivers_DocumentSection::SetLength (const Standard_Size theLength)
+void BinLDrivers_DocumentSection::SetLength (const uint64_t theLength)
 {
   myValue[1] = theLength;
 }
@@ -131,14 +132,14 @@ void BinLDrivers_DocumentSection::WriteTOC (Standard_OStream& theStream)
 
     // Write the buffer: size + string
 #if DO_INVERSE
-    aBufSz[0] = InverseSize ((Standard_Integer)aBufSize);
+    aBufSz[0] = InverseInt ((Standard_Integer)aBufSize);
 #else
     aBufSz[0] = (Standard_Integer)aBufSize;
 #endif
     theStream.write (&aBuf[0], aBufSize + sizeof(Standard_Integer));
 
     // Store the address of Offset word in the file
-    myValue[0] = (Standard_Size) theStream.tellp();
+    myValue[0] = (uint64_t) theStream.tellp();
     myValue[1] = 0;
 
     // Write the placeholders of Offset and Length of the section that should
@@ -146,7 +147,7 @@ void BinLDrivers_DocumentSection::WriteTOC (Standard_OStream& theStream)
     aBufSz[0] = 0;
     aBufSz[1] = 0;
     aBufSz[2] = 0;
-    theStream.write (&aBuf[0], 3*sizeof(Standard_Integer));
+    theStream.write (&aBuf[0], 3*sizeof(uint64_t));
   }
 }
 
@@ -156,24 +157,24 @@ void BinLDrivers_DocumentSection::WriteTOC (Standard_OStream& theStream)
 //=======================================================================
 
 void BinLDrivers_DocumentSection::Write (Standard_OStream&   theStream,
-                                         const Standard_Size theOffset)
+                                         const uint64_t theOffset)
 {
-  const Standard_Size aSectionEnd = (Standard_Size) theStream.tellp();
+  const uint64_t aSectionEnd = (uint64_t) theStream.tellp();
   theStream.seekp(myValue[0]);
   myValue[0] = theOffset;
   myValue[1] = aSectionEnd - theOffset;
-  Standard_Integer aVal[3] = {
-    Standard_Integer(myValue[0]),
-    Standard_Integer(myValue[1]),
-    Standard_Integer(myIsPostRead ? 1 : 0)
+  uint64_t aVal[3] = {
+    myValue[0],
+    myValue[1],
+    uint64_t(myIsPostRead ? 1 : 0)
   };
 #if DO_INVERSE
-  aVal[0] = InverseSize(aVal[0]);
-  aVal[1] = InverseSize(aVal[1]);
-  aVal[2] = InverseSize(aVal[2]);
+  aVal[0] = InverseUint64(aVal[0]);
+  aVal[1] = InverseUint64(aVal[1]);
+  aVal[2] = InverseUint64(aVal[2]);
 #endif
 
-  theStream.write((char *)&aVal[0], 3*sizeof(Standard_Integer));
+  theStream.write((char *)&aVal[0], 3*sizeof(uint64_t));
   theStream.seekp(aSectionEnd);
 }
 
@@ -195,15 +196,35 @@ void BinLDrivers_DocumentSection::ReadTOC
   if (aNameBufferSize > 0) {
     theStream.read ((char *)&aBuf[0], (Standard_Size)aNameBufferSize);
     theSection.myName = (Standard_CString)&aBuf[0];
-    Standard_Integer aValue[3];
-    theStream.read ((char *)&aValue[0], 3*sizeof(Standard_Integer));
+
+    uint64_t aValue[3];
+    if (BinMDataStd::DocumentVersion() <= 9)
+    {
+      // Old documents stored file position as 4-bytes values.
+      Standard_Integer aValInt[3];
+      theStream.read ((char *)&aValInt[0], 3*sizeof(Standard_Integer));
 #if DO_INVERSE
-    aValue[0] = InverseSize (aValue[0]);
-    aValue[1] = InverseSize (aValue[1]);
-    aValue[2] = InverseSize (aValue[2]);
+      aValue[0] = InverseInt (aValInt[0]);
+      aValue[1] = InverseInt (aValInt[1]);
+      aValue[2] = InverseInt (aValInt[2]);
+#else
+      aValue[0] = aValInt[0];
+      aValue[1] = aValInt[1];
+      aValue[2] = aValInt[2];
 #endif
-    theSection.myValue[0] = (Standard_Size)aValue[0];
-    theSection.myValue[1] = (Standard_Size)aValue[1];
-    theSection.myIsPostRead = aValue[2] != 0;
+    }
+    else
+    {
+      theStream.read ((char *)&aValue[0], 3*sizeof(uint64_t));
+#if DO_INVERSE
+      aValue[0] = InverseUint64 (aValue[0]);
+      aValue[1] = InverseUint64 (aValue[1]);
+      aValue[2] = InverseUint64 (aValue[2]);
+#endif
+    }
+
+    theSection.myValue[0] = aValue[0];
+    theSection.myValue[1] = aValue[1];
+    theSection.myIsPostRead = (aValue[2] != 0);
   }
 }
index bafc9df..0fd63f2 100644 (file)
@@ -52,23 +52,23 @@ public:
   Standard_EXPORT Standard_Boolean IsPostRead() const;
   
   //! Query the offset of the section in the persistent file
-  Standard_EXPORT Standard_Size Offset() const;
+  Standard_EXPORT uint64_t Offset() const;
   
   //! Set the offset of the section in the persistent file
-  Standard_EXPORT void SetOffset (const Standard_Size theOffset);
+  Standard_EXPORT void SetOffset (const uint64_t theOffset);
   
   //! Query the length of the section in the persistent file
-  Standard_EXPORT Standard_Size Length() const;
+  Standard_EXPORT uint64_t Length() const;
   
   //! Set the length of the section in the persistent file
-  Standard_EXPORT void SetLength (const Standard_Size theLength);
+  Standard_EXPORT void SetLength (const uint64_t theLength);
   
   //! Create a Section entry in the Document TOC (list of sections)
   Standard_EXPORT void WriteTOC (Standard_OStream& theOS);
   
   //! Save Offset and Length data into the Section entry
   //! in the Document TOC (list of sections)
-  Standard_EXPORT void Write (Standard_OStream& theOS, const Standard_Size theOffset);
+  Standard_EXPORT void Write (Standard_OStream& theOS, const uint64_t theOffset);
   
   //! Fill a DocumentSection instance from the data that are read
   //! from TOC.
@@ -88,7 +88,7 @@ private:
 
 
   TCollection_AsciiString myName;
-  Standard_Size myValue[2];
+  uint64_t myValue[2];
   Standard_Boolean myIsPostRead;
 
 
index a978db7..8cc2344 100644 (file)
@@ -1860,20 +1860,20 @@ Standard_ShortReal FSD_BinaryFile::InverseShortReal (const Standard_ShortReal th
 //=======================================================================
 
 template<int size>
-inline Standard_Size OCCT_InverseSizeSpecialized (const Standard_Size theValue, int);
+inline uint64_t OCCT_InverseSizeSpecialized (const uint64_t theValue, int);
 
 template<>
-inline Standard_Size OCCT_InverseSizeSpecialized <4> (const Standard_Size theValue, int)
+inline uint64_t OCCT_InverseSizeSpecialized <4> (const uint64_t theValue, int)
 {
   return FSD_BinaryFile::InverseInt(static_cast<Standard_Integer>(theValue));
 }
 
 template<>
-inline Standard_Size OCCT_InverseSizeSpecialized <8> (const Standard_Size theValue, int)
+inline uint64_t OCCT_InverseSizeSpecialized <8> (const uint64_t theValue, int)
 {
   union {
     Standard_Integer i[2];
-    Standard_Size    aValue;
+    uint64_t    aValue;
   } aWrapUnion;
 
   aWrapUnion.aValue = theValue;
@@ -1887,5 +1887,10 @@ inline Standard_Size OCCT_InverseSizeSpecialized <8> (const Standard_Size theVal
 
 Standard_Size FSD_BinaryFile::InverseSize (const Standard_Size theValue)
 {
-  return OCCT_InverseSizeSpecialized <sizeof(Standard_Size)> (theValue, 0);
+  return (Standard_Size) OCCT_InverseSizeSpecialized <sizeof(Standard_Size)> (theValue, 0);
+}
+
+uint64_t FSD_BinaryFile::InverseUint64 (const uint64_t theValue)
+{
+  return OCCT_InverseSizeSpecialized <sizeof(uint64_t)> (theValue, 0);
 }
index 3060a1d..09921b8 100644 (file)
@@ -335,6 +335,8 @@ Storage_BaseDriver& operator >> (Standard_ShortReal& aValue)
 
   ///Inverse bytes in size value
   Standard_EXPORT static Standard_Size InverseSize(const Standard_Size theValue);
+  ///Inverse bytes in 64bit unsigned int value
+  Standard_EXPORT static uint64_t InverseUint64(const uint64_t theValue);
 
   Standard_EXPORT static void ReadHeader (Standard_IStream& theIStream, FSD_FileHeader& theFileHeader);