Skip to content

Commit

Permalink
Fix issue when using readable streams that read fewer bytes than requ…
Browse files Browse the repository at this point in the history
…ested, such as compressor streams. Reported by a user.
  • Loading branch information
peteroupc committed Feb 18, 2022
1 parent 8dfe455 commit 3659b2b
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 277 deletions.
57 changes: 33 additions & 24 deletions CBOR/PeterO/Cbor/CBORReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,30 @@ private CBORObject ReadStringArrayMap(int type, long uadditional) {
return null;
}

private static void ReadHelper(
Stream stream,
byte[] bytes,
int offset,
int count) {
// Assert.CheckBuffer(bytes, offset, count);
int t = count;
var tpos = offset;
while (t > 0) {
int rcount = stream.Read(bytes, tpos, t);
if (rcount <= 0) {
throw new CBORException("Premature end of data");
}
if (rcount > t) {
throw new CBORException("Internal error");
}
tpos = checked(tpos + rcount);
t = checked(t - rcount);
}
if (t != 0) {
throw new CBORException("Internal error");
}
}

public CBORObject ReadForFirstByte(int firstbyte) {
if (this.depth > 500) {
throw new CBORException("Too deeply nested");
Expand Down Expand Up @@ -313,10 +337,8 @@ public CBORObject ReadForFirstByte(int firstbyte) {
// include the first byte because GetFixedLengthObject
// will assume it exists for some head bytes
data[0] = unchecked((byte)firstbyte);
if (expectedLength > 1 &&
this.stream.Read(data, 1, expectedLength - 1) != expectedLength
- 1) {
throw new CBORException("Premature end of data");
if (expectedLength > 1) {
ReadHelper(this.stream, data, 1, expectedLength - 1);
}
CBORObject cbor = CBORObject.GetFixedLengthObject(firstbyte, data);
if (this.stringRefs != null && (type == 2 || type == 3)) {
Expand All @@ -341,8 +363,7 @@ public CBORObject ReadForFirstByte(int firstbyte) {
}
long len = ReadDataLength(this.stream, nextByte, 2);
if ((len >> 63) != 0 || len > Int32.MaxValue) {
throw new CBORException("Length" + ToUnsignedEInteger(len)
+
throw new CBORException("Length" + ToUnsignedEInteger(len) +
" is bigger than supported ");
}
if (nextByte != 0x40) {
Expand Down Expand Up @@ -515,9 +536,7 @@ private static byte[] ReadByteData(
if (uadditional <= 0x10000) {
// Simple case: small size
var data = new byte[(int)uadditional];
if (stream.Read(data, 0, data.Length) != data.Length) {
throw new CBORException("Premature end of stream");
}
ReadHelper(stream, data, 0, data.Length);
if (outputStream != null) {
outputStream.Write(data, 0, data.Length);
return null;
Expand All @@ -529,9 +548,7 @@ private static byte[] ReadByteData(
if (outputStream != null) {
while (total > 0) {
int bufsize = Math.Min(tmpdata.Length, total);
if (stream.Read(tmpdata, 0, bufsize) != bufsize) {
throw new CBORException("Premature end of stream");
}
ReadHelper(stream, tmpdata, 0, bufsize);
outputStream.Write(tmpdata, 0, bufsize);
total -= bufsize;
}
Expand All @@ -540,9 +557,7 @@ private static byte[] ReadByteData(
using (var ms = new MemoryStream(0x10000)) {
while (total > 0) {
int bufsize = Math.Min(tmpdata.Length, total);
if (stream.Read(tmpdata, 0, bufsize) != bufsize) {
throw new CBORException("Premature end of stream");
}
ReadHelper(stream, tmpdata, 0, bufsize);
ms.Write(tmpdata, 0, bufsize);
total -= bufsize;
}
Expand Down Expand Up @@ -586,9 +601,7 @@ private static long ReadDataLength(
return tmp;
}
case 25: {
if (stream.Read(data, 0, 2) != 2) {
throw new CBORException("Premature end of data");
}
ReadHelper(stream, data, 0, 2);
int lowAdditional = ((int)(data[0] & (int)0xff)) << 8;
lowAdditional |= (int)(data[1] & (int)0xff);
if (!allowNonShortest && lowAdditional < 256) {
Expand All @@ -597,9 +610,7 @@ private static long ReadDataLength(
return lowAdditional;
}
case 26: {
if (stream.Read(data, 0, 4) != 4) {
throw new CBORException("Premature end of data");
}
ReadHelper(stream, data, 0, 4);
long uadditional = ((long)(data[0] & 0xffL)) << 24;
uadditional |= ((long)(data[1] & 0xffL)) << 16;
uadditional |= ((long)(data[2] & 0xffL)) << 8;
Expand All @@ -610,9 +621,7 @@ private static long ReadDataLength(
return uadditional;
}
case 27: {
if (stream.Read(data, 0, 8) != 8) {
throw new CBORException("Premature end of data");
}
ReadHelper(stream, data, 0, 8);
// Treat return value as an unsigned integer
long uadditional = ((long)(data[0] & 0xffL)) << 56;
uadditional |= ((long)(data[1] & 0xffL)) << 48;
Expand Down
4 changes: 2 additions & 2 deletions CBORTest/BEncodingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Test {
public class BEncodingTest {
private static CBORObject EncodingFromBytes(byte[] b) {
try {
using (var s = new MemoryStream(b)) {
using (var s = new Test.DelayingStream(b)) {
return BEncoding.Read(s);
}
} catch (IOException ex) {
Expand All @@ -20,7 +20,7 @@ private static CBORObject EncodingFromBytes(byte[] b) {

private static byte[] EncodingToBytes(CBORObject b) {
try {
using (var ms = new MemoryStream()) {
using (var ms = new Test.DelayingStream()) {
BEncoding.Write(b, ms);
return ms.ToArray();
}
Expand Down
Loading

0 comments on commit 3659b2b

Please sign in to comment.