decoder/dsdiff: reject overflowing chunk offsets - #2553
Merged
MaxKellermann merged 1 commit intoAug 10, 2026
Conversation
| uint64_t GetPaddedSize() const noexcept { | ||
| return (GetSize() + 1) & ~uint64_t(1); | ||
| [[nodiscard]] | ||
| bool GetPaddedSize(uint64_t &padded_size) const noexcept { |
Member
There was a problem hiding this comment.
This is horribly inelegant code and it's no longer obvious what this function really does. This needs API documentation. But probably it needs a rewrite to make it easier to understand. This whole PR looks like LLM slop.
acts-1631
force-pushed
the
fix/dsdiff-chunk-overflow
branch
from
August 2, 2026 13:06
77093d6 to
7b5036d
Compare
Comment on lines
+110
to
+103
| while (is.GetOffset() + sizeof(header) <= end_offset) { | ||
| while (is.GetOffset() < end_offset) { | ||
| if (end_offset - is.GetOffset() < sizeof(header)) |
Member
There was a problem hiding this comment.
How would it be possible for an attacker to produce an overflow here? With a file of 2^64-8 bytes size?
Comment on lines
+110
to
+115
| if ((chunk_size & 1) != 0) { | ||
| if (chunk_size == std::numeric_limits<uint64_t>::max()) | ||
| return false; | ||
|
|
||
| ++chunk_size; | ||
| } |
Member
There was a problem hiding this comment.
This block is very obscure code. Previously, it was obvious that this was about padding, but you removed the code that mentioned padding. This is still too complicated!
The DSDIFF metadata parser adds an untrusted chunk size to the input offset. An overflow can seek back to the chunk header and loop forever. Reject overflowing end offsets before skipping unknown metadata chunks.
acts-1631
force-pushed
the
fix/dsdiff-chunk-overflow
branch
from
August 9, 2026 20:43
7b5036d to
f4f5946
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dsdiff_read_metadata() reads a 64-bit chunk size from the DFF file and
adds it to the current input offset. If this addition overflows, the
result can point backward. For seekable input, dsdlib_skip_to() then
seeks back to the same chunk header, causing metadata scans to loop
indefinitely. Playback follows the same parsing path and can spin until
stopped.
Use checked offset addition in dsdiff_read_metadata(),
dsdiff_read_prop(), and dsdiff_read_prop_snd(). Also reject overflow
when applying DSDIFF even-byte padding and in dsdlib_skip() relative
seeks. Absolute backward seeks remain supported because the tag reader
uses them intentionally.
Verified with a 28-byte DFF file whose unknown chunk size wraps the
offset from 28 back to 16. The checked calculation now rejects the
chunk.