Skip to content

Commit

Permalink
Update int buffers to exact unsigned max length and eliminate additio…
Browse files Browse the repository at this point in the history
…nal byte allocation
  • Loading branch information
iamcarbon committed Apr 15, 2024
1 parent ec720b1 commit 36d1093
Showing 1 changed file with 21 additions and 14 deletions.
35 changes: 21 additions & 14 deletions src/UglyToad.PdfPig.Core/ReadHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,21 @@ public static long ReadLong(IInputBytes bytes)
{
SkipSpaces(bytes);

ReadOnlySpan<byte> longBuffer = ReadNumberAsUtf8Bytes(bytes);
Span<byte> buffer = stackalloc byte[19]; // max ulong32 length

if (Utf8Parser.TryParse(longBuffer, out long result, out _))
ReadNumberAsUtf8Bytes(bytes, buffer, out int bytesRead);

ReadOnlySpan<byte> longBytes = buffer.Slice(0, bytesRead);

if (Utf8Parser.TryParse(longBytes, out long result, out _))
{
return result;
}
else
{
bytes.Seek(bytes.CurrentOffset - longBuffer.Length);
bytes.Seek(bytes.CurrentOffset - bytesRead);

throw new InvalidOperationException($"Error: Expected a long type at offset {bytes.CurrentOffset}, instead got \'{OtherEncodings.BytesAsLatin1String(longBuffer)}\'");
throw new InvalidOperationException($"Error: Expected a long type at offset {bytes.CurrentOffset}, instead got \'{OtherEncodings.BytesAsLatin1String(longBytes)}\'");
}
}

Expand All @@ -233,17 +237,21 @@ public static int ReadInt(IInputBytes bytes)

SkipSpaces(bytes);

ReadOnlySpan<byte> intBuffer = ReadNumberAsUtf8Bytes(bytes);
Span<byte> buffer = stackalloc byte[10]; // max uint32 length

ReadNumberAsUtf8Bytes(bytes, buffer, out int bytesRead);

if (Utf8Parser.TryParse(intBuffer, out int result, out _))
var intBytes = buffer.Slice(0, bytesRead);

if (Utf8Parser.TryParse(intBytes, out int result, out _))
{
return result;
}
else
{
bytes.Seek(bytes.CurrentOffset - intBuffer.Length);
bytes.Seek(bytes.CurrentOffset - bytesRead);

throw new PdfDocumentFormatException($"Error: Expected an integer type at offset {bytes.CurrentOffset}, instead got \'{OtherEncodings.BytesAsLatin1String(intBuffer)}\'");
throw new PdfDocumentFormatException($"Error: Expected an integer type at offset {bytes.CurrentOffset}, instead got \'{OtherEncodings.BytesAsLatin1String(intBytes)}\'");
}
}

Expand Down Expand Up @@ -296,9 +304,8 @@ public static bool IsValidUtf8(byte[] input)
#endif
}

private static byte[] ReadNumberAsUtf8Bytes(IInputBytes reader)
private static void ReadNumberAsUtf8Bytes(IInputBytes reader, scoped Span<byte> buffer, out int bytesRead)
{
Span<byte> buffer = stackalloc byte[MaximumNumberStringLength]; // 20 bytes
int position = 0;

byte lastByte;
Expand All @@ -311,20 +318,20 @@ private static byte[] ReadNumberAsUtf8Bytes(IInputBytes reader)
lastByte != '(' && // PDFBOX-2579
lastByte != 0)
{
buffer[position++] = lastByte;

if (position > MaximumNumberStringLength)
if (position >= buffer.Length)
{
throw new InvalidOperationException($"Number \'{OtherEncodings.BytesAsLatin1String(buffer.Slice(0, position))}\' is getting too long, stop reading at offset {reader.CurrentOffset}");
}

buffer[position++] = lastByte;
}

if (!reader.IsAtEnd())
{
reader.Seek(reader.CurrentOffset - 1);
}

return buffer.Slice(0, position).ToArray();
bytesRead = position;
}
}
}
Expand Down

0 comments on commit 36d1093

Please sign in to comment.