Skip to content

Commit

Permalink
verify RAR crc on header and file data
Browse files Browse the repository at this point in the history
  • Loading branch information
coderb committed Apr 4, 2017
1 parent 356c977 commit 7fd8b66
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 13 deletions.
34 changes: 26 additions & 8 deletions src/SharpCompress/Common/Rar/Headers/RarHeader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using SharpCompress.IO;

namespace SharpCompress.Common.Rar.Headers
Expand All @@ -18,14 +19,14 @@ private void FillBase(RarHeader baseHeader)
ReadBytes = baseHeader.ReadBytes;
}

internal static RarHeader Create(MarkingBinaryReader reader)
internal static RarHeader Create(RarCrcBinaryReader reader)
{
try
{
RarHeader header = new RarHeader();

reader.Mark();
header.ReadFromReader(reader);
header.ReadStartFromReader(reader);
header.ReadBytes += reader.CurrentReadByteCount;

return header;
Expand All @@ -36,9 +37,10 @@ internal static RarHeader Create(MarkingBinaryReader reader)
}
}

protected virtual void ReadFromReader(MarkingBinaryReader reader)
private void ReadStartFromReader(RarCrcBinaryReader reader)
{
HeadCRC = reader.ReadInt16();
HeadCRC = reader.ReadUInt16();
reader.ResetCrc();
HeaderType = (HeaderType)(reader.ReadByte() & 0xff);
Flags = reader.ReadInt16();
HeaderSize = reader.ReadInt16();
Expand All @@ -48,7 +50,11 @@ protected virtual void ReadFromReader(MarkingBinaryReader reader)
}
}

internal T PromoteHeader<T>(MarkingBinaryReader reader)
protected virtual void ReadFromReader(MarkingBinaryReader reader) {
throw new NotImplementedException();
}

internal T PromoteHeader<T>(RarCrcBinaryReader reader)
where T : RarHeader, new()
{
T header = new T();
Expand All @@ -65,9 +71,21 @@ internal T PromoteHeader<T>(MarkingBinaryReader reader)
reader.ReadBytes(headerSizeDiff);
}

VerifyHeaderCrc(reader.GetCrc());

return header;
}

private void VerifyHeaderCrc(ushort crc) {
if (HeaderType != HeaderType.MarkHeader)
{
if (crc != HeadCRC)
{
throw new InvalidFormatException("rar header crc mismatch");
}
}
}

protected virtual void PostReadingBytes(MarkingBinaryReader reader)
{
}
Expand All @@ -77,7 +95,7 @@ protected virtual void PostReadingBytes(MarkingBinaryReader reader)
/// </summary>
protected long ReadBytes { get; private set; }

protected short HeadCRC { get; private set; }
protected ushort HeadCRC { get; private set; }

internal HeaderType HeaderType { get; private set; }

Expand All @@ -93,4 +111,4 @@ protected virtual void PostReadingBytes(MarkingBinaryReader reader)
/// </summary>
protected uint AdditionalSize { get; private set; }
}
}
}
4 changes: 2 additions & 2 deletions src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private RarHeader ReadNextHeader(Stream stream)
reader.InitializeAes(salt);
}
#else
var reader = new MarkingBinaryReader(stream);
var reader = new RarCrcBinaryReader(stream);

#endif

Expand Down Expand Up @@ -247,4 +247,4 @@ private RarHeader ReadNextHeader(Stream stream)
}
}
}
}
}
30 changes: 30 additions & 0 deletions src/SharpCompress/Common/Rar/RarCrcBinaryReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.IO;
using SharpCompress.Compressors.Rar;
using SharpCompress.IO;

namespace SharpCompress.Common.Rar {
internal class RarCrcBinaryReader : MarkingBinaryReader {
private uint currentCrc;

public RarCrcBinaryReader(Stream stream) : base(stream)
{
}

public ushort GetCrc()
{
return (ushort)~this.currentCrc;
}

public void ResetCrc()
{
this.currentCrc = 0xffffffff;
}

public override byte[] ReadBytes(int count)
{
var result = base.ReadBytes(count);
this.currentCrc = RarCRC.CheckCrc(this.currentCrc, result, 0, result.Length);
return result;
}
}
}
2 changes: 1 addition & 1 deletion src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace SharpCompress.Common.Rar
{
internal class RarCryptoBinaryReader : MarkingBinaryReader
internal class RarCryptoBinaryReader : RarCrcBinaryReader
{
private RarRijndael rijndael;
private byte[] salt;
Expand Down
40 changes: 40 additions & 0 deletions src/SharpCompress/Compressors/Rar/RarCrcStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.Rar.Headers;

namespace SharpCompress.Compressors.Rar {
internal class RarCrcStream : RarStream {
private readonly uint expectedCrc;
private uint currentCrc;

public RarCrcStream(Unpack unpack, FileHeader fileHeader, Stream readStream) : base(unpack, fileHeader, readStream)
{
this.expectedCrc = fileHeader.FileCRC;
ResetCrc();
}

public uint GetCrc()
{
return ~this.currentCrc;
}

public void ResetCrc()
{
this.currentCrc = 0xffffffff;
}


public override int Read(byte[] buffer, int offset, int count)
{
var result = base.Read(buffer, offset, count);
if (result != 0)
{
this.currentCrc = RarCRC.CheckCrc(this.currentCrc, buffer, offset, result);
} else if (GetCrc() != this.expectedCrc)
{
throw new InvalidFormatException("file crc mismatch");
}
return result;
}
}
}
4 changes: 2 additions & 2 deletions src/SharpCompress/Readers/Rar/RarReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ protected virtual IEnumerable<FilePart> CreateFilePartEnumerableForCurrentEntry(

protected override EntryStream GetEntryStream()
{
return CreateEntryStream(new RarStream(pack, Entry.FileHeader,
return CreateEntryStream(new RarCrcStream(pack, Entry.FileHeader,
new MultiVolumeReadOnlyStream(
CreateFilePartEnumerableForCurrentEntry().Cast<RarFilePart>(), this)));
}
}
}
}

0 comments on commit 7fd8b66

Please sign in to comment.