From 7e236700ad16fc30b89582a23d6e7cac1eabbf32 Mon Sep 17 00:00:00 2001
From: winscripter <142818255+winscripter@users.noreply.github.com>
Date: Mon, 24 Aug 2026 23:57:39 +0400
Subject: [PATCH] Add CodestreamMarker, don't manually check for out-of-bounds
Bit Reader should automatically throw if it reads out of bounds anyway
---
.../Jxl/Processing/Decoder/JxlDecoderCore.cs | 36 ++++++-------------
.../Formats/Jxl/Processing/JxlShared.cs | 7 ++++
2 files changed, 17 insertions(+), 26 deletions(-)
diff --git a/src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlDecoderCore.cs b/src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlDecoderCore.cs
index 35c52cc46..0287760e4 100644
--- a/src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlDecoderCore.cs
@@ -223,7 +223,7 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
///
/// Output data for extra channels.
///
- private List extraChannelOutputs = [];
+ private readonly List extraChannelOutputs = [];
///
/// Codec metadata if present.
@@ -255,7 +255,7 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
///
private long nextSection;
- private List sectionProcessed = [];
+ private readonly List sectionProcessed = [];
///
/// The frame header, if present.
@@ -301,11 +301,11 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
///
/// All frame reference.s
///
- private List frameReferences = [];
+ private readonly List frameReferences = [];
- private List frameExternalToInternal = [];
+ private readonly List frameExternalToInternal = [];
- private List frameRequired = [];
+ private readonly List frameRequired = [];
///
/// Codestream input data is temporarily copied here.
@@ -802,7 +802,7 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
throw new EndOfStreamException();
}
- if (secondByte == CodestreamMarker)
+ if (secondByte == JxlShared.CodestreamMarker)
{
return JxlSignature.CodeStream;
}
@@ -961,7 +961,7 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
{
const long bufferLimit = 1 << 48;
return length < bufferLimit &&
- (length + this.jxlpOooBufferTotal + (this.codestreamCopy?.Memory.Length ?? 0)) < bufferLimit;
+ (length + this.jxlpOooBufferTotal + (this.codestreamCopy?.AsMemory().Length ?? 0)) < bufferLimit;
}
public bool TryInjectNextBufferedJxlpBox()
@@ -1471,14 +1471,14 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
/// Reads a single bundle into .
///
/// Type of the bundle to read.
- /// Bundle binary data.
+ /// Stream to read data from.
/// Bit reader to continue from.
/// The bundle to parse.
/// Status of parsing the bundle.
- private bool ReadBundle(Span data, JxlBitReader br, T bundle)
+ private bool ReadBundle(Stream stream, JxlBitReader br, T bundle)
where T : IJxlFields
{
- JxlBitReader reader = new(data);
+ JxlBitReader reader = new(stream);
reader.SkipBits64((ulong)br.TotalBitsConsumed);
bool canRead = JxlBundle.CanRead(reader, bundle);
@@ -1646,22 +1646,6 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
this.frameDecoder.ProcessSections(sectionInfo, sectionStatus);
- bool outOfBounds = false;
-
- foreach (JxlSectionInfo info in sectionInfo)
- {
- if (!info.BitReader.AllReadsWithinBounds)
- {
- outOfBounds = true;
- break;
- }
- }
-
- if (outOfBounds)
- {
- throw new InvalidOperationException("Frame out of bounds");
- }
-
for (int i = 0; i < sectionStatus.Count; i++)
{
JxlSectionStatus ss = sectionStatus[i];
diff --git a/src/ImageSharp/Formats/Jxl/Processing/JxlShared.cs b/src/ImageSharp/Formats/Jxl/Processing/JxlShared.cs
index 711dbc27e..e8126bc4d 100644
--- a/src/ImageSharp/Formats/Jxl/Processing/JxlShared.cs
+++ b/src/ImageSharp/Formats/Jxl/Processing/JxlShared.cs
@@ -18,6 +18,13 @@ internal static class JxlShared
///
public const int MaximumNumberOfReferenceFrames = 4;
+ ///
+ /// Reserved by ISO/IEC 10918-1. LF causes files opened in text mode
+ /// to be rejected because the marker changes to 0x0D instead. The
+ /// 0xFF prefix also ensures there were no 7-bit transmission limitations.
+ ///
+ public const byte CodestreamMarker = 0x0A;
+
///
/// Gets the 12-byte signature (a.k.a. magic) for JPEG XL files.
///