diff options
| author | Duck912 <350528965+Duck912@users.noreply.github.com> | 2026-11-03 12:56:43 -0500 |
|---|---|---|
| committer | Duck912 <350528965+Duck912@users.noreply.github.com> | 2026-11-03 13:06:59 -0500 |
| commit | f9d0c802e8e4e71644bf4b7e6cceca8e6df22464 (patch) | |
| tree | 74ab11bfe249617baa7f7c5b1f729eeb7538ba3e /src | |
| parent | f4f076fe447b2ddc158fcc12ee81ed2af2aecad7 (diff) | |
yuzu: bound the zip directory reads in the DLSS download
The central-directory parser trusted each entry's name, extra and comment lengths and the Zip64
extra field's length, so a malformed directory could make it read past the downloaded buffer. The
data comes from NVIDIA's GitHub release over TLS and the saved files are signature-checked, so the
risk is low.
Stop with an error when an entry runs past the directory, and read Zip64 fields only inside their
record.
Found by CodeRabbit review.
Assisted-by: Claude Opus 5.5 (implementation)
Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuzu/configuration/nvidia_dlss_panel.cpp | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/src/yuzu/configuration/nvidia_dlss_panel.cpp b/src/yuzu/configuration/nvidia_dlss_panel.cpp index 2329693a03..040ea90557 100644 --- a/src/yuzu/configuration/nvidia_dlss_panel.cpp +++ b/src/yuzu/configuration/nvidia_dlss_panel.cpp @@ -166,16 +166,21 @@ public: .size = U32(*directory, at + 24), .offset = U32(*directory, at + 42), }; + const size_t extra_end = at + 46 + name_length + extra_length; + if (extra_end + comment_length > directory->size()) { + error = "bad zip directory"; + return false; + } const std::string name = directory->substr(at + 46, name_length); // Zip64 sizes and offset, in this order, for the fields that overflowed. - const size_t extra_end = at + 46 + name_length + extra_length; for (size_t extra = at + 46 + name_length; extra + 4 <= extra_end;) { const u16 id = U16(*directory, extra); const u16 length = U16(*directory, extra + 2); + const size_t record_end = std::min<size_t>(extra + 4 + length, extra_end); if (id == 0x0001) { size_t field = extra + 4; for (u64* value : {&entry.size, &entry.compressed, &entry.offset}) { - if (*value == 0xFFFFFFFF) { + if (*value == 0xFFFFFFFF && field + 8 <= record_end) { *value = U64(*directory, field); field += 8; } |
