diff options
Diffstat (limited to 'CPP/7zip/Archive/Udf')
-rwxr-xr-x | CPP/7zip/Archive/Udf/UdfHandler.cpp | 47 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Udf/UdfIn.cpp | 73 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Udf/UdfIn.h | 7 |
3 files changed, 85 insertions, 42 deletions
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 10a1a900..e503e843 100755 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -236,25 +236,40 @@ STDMETHODIMP CUdfInStream::Read(void *data, UInt32 size, UInt32 *processedSize) const CFile &file = _archive->Files[ref.FileIndex]; const CItem &item = _archive->Items[file.ItemIndex]; - const CMyExtent &extent = item.Extents[_extentIndex]; - UInt32 rem = extent.GetLen() - _offsetInExtent; - if (rem == 0) + HRESULT res = S_OK; + if (item.IsInline) { - _extentIndex++; - _offsetInExtent = 0; - continue; + size_t rem = item.InlineData.GetCapacity() - _offsetInExtent; + if (rem == 0) + return S_OK; + if (rem > _rem) + rem = (size_t)_rem; + memcpy(data, (const Byte *)item.InlineData + _offsetInExtent, rem); } - if (size > rem) - size = rem; - - int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; - UInt32 logBlockNumber = extent.Pos; - const CPartition &partition = _archive->Partitions[partitionIndex]; - UInt64 offset = ((UInt64)partition.Pos << _archive->SecLogSize) + + else + { + if (_extentIndex >= item.Extents.Size()) + return S_OK; + const CMyExtent &extent = item.Extents[_extentIndex]; + UInt32 rem = extent.GetLen() - _offsetInExtent; + if (rem == 0) + { + _extentIndex++; + _offsetInExtent = 0; + continue; + } + if (size > rem) + size = rem; + + int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; + UInt32 logBlockNumber = extent.Pos; + const CPartition &partition = _archive->Partitions[partitionIndex]; + UInt64 offset = ((UInt64)partition.Pos << _archive->SecLogSize) + (UInt64)logBlockNumber * vol.BlockSize + _offsetInExtent; - - RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); - HRESULT res = _stream->Read(data, size, &size); + + RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + res = _stream->Read(data, size, &size); + } _offsetInExtent += size; _rem -= size; if (processedSize) diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 3637bbc6..75a0c333 100755 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -26,6 +26,7 @@ const int kNumFilesMax = 1 << 28; const int kNumRefsMax = 1 << 28; const UInt32 kNumExtentsMax = (UInt32)1 << 30; const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33; +const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; void MY_FAST_CALL Crc16GenerateTable(void); @@ -275,6 +276,11 @@ HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &b { if (item.Size >= (UInt32)1 << 30) return S_FALSE; + if (item.IsInline) + { + buf = item.InlineData; + return S_OK; + } buf.SetCapacity((size_t)item.Size); size_t pos = 0; for (int i = 0; i < item.Extents.Size(); i++) @@ -448,37 +454,46 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la pos += extendedAttrLen; int desctType = item.IcbTag.GetDescriptorType(); - // if (desctType == ICB_DESC_TYPE_INLINE || desctType == ICB_DESC_TYPE_EXTENDED) - if (desctType != ICB_DESC_TYPE_SHORT && desctType != ICB_DESC_TYPE_LONG) - return S_FALSE; if (allocDescriptorsLen > size - pos) return S_FALSE; - for (UInt32 i = 0; i < allocDescriptorsLen;) + if (desctType == ICB_DESC_TYPE_INLINE) { - CMyExtent e; - if (desctType == ICB_DESC_TYPE_SHORT) - { - if (i + 8 > allocDescriptorsLen) - return S_FALSE; - CShortAllocDesc sad; - sad.Parse(p + pos + i); - e.Pos = sad.Pos; - e.Len = sad.Len; - e.PartitionRef = lad.Location.PartitionRef; - i += 8; - } - else + item.IsInline = true; + item.InlineData.SetCapacity(allocDescriptorsLen); + memcpy(item.InlineData, p + pos, allocDescriptorsLen); + } + else + { + item.IsInline = false; + if (desctType != ICB_DESC_TYPE_SHORT && desctType != ICB_DESC_TYPE_LONG) + return S_FALSE; + for (UInt32 i = 0; i < allocDescriptorsLen;) { - if (i + 16 > allocDescriptorsLen) - return S_FALSE; - CLongAllocDesc ladNew; - ladNew.Parse(p + pos + i); - e.Pos = ladNew.Location.Pos; - e.PartitionRef = ladNew.Location.PartitionRef; - e.Len = ladNew.Len; - i += 16; + CMyExtent e; + if (desctType == ICB_DESC_TYPE_SHORT) + { + if (i + 8 > allocDescriptorsLen) + return S_FALSE; + CShortAllocDesc sad; + sad.Parse(p + pos + i); + e.Pos = sad.Pos; + e.Len = sad.Len; + e.PartitionRef = lad.Location.PartitionRef; + i += 8; + } + else + { + if (i + 16 > allocDescriptorsLen) + return S_FALSE; + CLongAllocDesc ladNew; + ladNew.Parse(p + pos + i); + e.Pos = ladNew.Location.Pos; + e.PartitionRef = ladNew.Location.PartitionRef; + e.Len = ladNew.Len; + i += 16; + } + item.Extents.Add(e); } - item.Extents.Add(e); } if (item.IcbTag.IsDir()) @@ -489,6 +504,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la RINOK(ReadFromFile(volIndex, item, buf)); item.Size = 0; item.Extents.ClearAndFree(); + item.InlineData.Free(); const Byte *p = buf; size = buf.GetCapacity(); @@ -524,6 +540,10 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la if ((UInt32)item.Extents.Size() > kNumExtentsMax - _numExtents) return S_FALSE; _numExtents += item.Extents.Size(); + + if (item.InlineData.GetCapacity() > kInlineExtentsSizeMax - _inlineExtentsSize) + return S_FALSE; + _inlineExtentsSize += item.InlineData.GetCapacity(); } return S_OK; @@ -769,6 +789,7 @@ void CInArchive::Clear() _fileNameLengthTotal = 0; _numRefs = 0; _numExtents = 0; + _inlineExtentsSize = 0; _processedProgressBytes = 0; } diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index f99991a0..46b9a7e8 100755 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h @@ -167,6 +167,8 @@ struct CPartitionMap int PartitionIndex; }; +// ECMA 4/14.6 + enum EIcbFileType { ICB_FILE_TYPE_DIR = 4, @@ -243,6 +245,8 @@ struct CItem // CRegId ImplId; // UInt64 UniqueId; + bool IsInline; + CByteBuffer InlineData; CRecordVector<CMyExtent> Extents; CRecordVector<int> SubFiles; @@ -258,6 +262,8 @@ struct CItem UInt64 GetChunksSumSize() const { + if (IsInline) + return InlineData.GetCapacity(); UInt64 size = 0; for (int i = 0; i < Extents.Size(); i++) size += Extents[i].GetLen(); @@ -343,6 +349,7 @@ class CInArchive UInt64 _fileNameLengthTotal; int _numRefs; UInt32 _numExtents; + UInt64 _inlineExtentsSize; bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const; public: HRESULT Open(IInStream *inStream, CProgressVirt *progress); |