This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push:
new 3c50b8226 Reject short LZMA properties and oversized dictionary in
LZMADecoder (#784)
3c50b8226 is described below
commit 3c50b8226b81ddca4d59d6af4fa8f1b7617b3a20
Author: KALI 834X <[email protected]>
AuthorDate: Mon Jul 13 22:36:14 2026 +0530
Reject short LZMA properties and oversized dictionary in LZMADecoder (#784)
* Reject short LZMA properties and oversized dictionary in LZMADecoder
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI
<[email protected]>
---------
Co-authored-by: Gary Gregory <[email protected]>
Co-authored-by: Copilot Autofix powered by AI
<[email protected]>
---
.../compress/archivers/sevenz/LZMADecoder.java | 14 ++++--
.../archivers/sevenz/SevenZLZMADecoderTest.java | 56 ++++++++++++++++++++++
2 files changed, 65 insertions(+), 5 deletions(-)
diff --git
a/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
b/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
index 893867d07..d56cc5176 100644
---
a/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
+++
b/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
@@ -47,9 +47,6 @@ InputStream decode(final String archiveName, final
InputStream in, final long un
}
final byte propsByte = coder.properties[0];
final int dictSize = getDictionarySize(coder);
- if (dictSize > LZMAInputStream.DICT_SIZE_MAX) {
- throw new ArchiveException("Dictionary larger than 4 GiB maximum
size used in '%s'", archiveName);
- }
final int memoryUsageKiB = LZMAInputStream.getMemoryUsage(dictSize,
propsByte);
MemoryLimitException.checkKiB(memoryUsageKiB, maxMemoryLimitKiB);
final LZMAInputStream lzmaIn = new LZMAInputStream(in,
uncompressedLength, propsByte, dictSize);
@@ -63,8 +60,15 @@ OutputStream encode(final OutputStream out, final Object
opts) throws IOExceptio
return new FlushShieldFilterOutputStream(new LZMAOutputStream(out,
getOptions(opts), false));
}
- private int getDictionarySize(final Coder coder) throws
IllegalArgumentException {
- return (int) ByteUtils.fromLittleEndian(coder.properties, 1, 4);
+ private int getDictionarySize(final Coder coder) throws ArchiveException {
+ if (coder.properties.length < 5) {
+ throw new ArchiveException("LZMA properties too short (expected 5
bytes)");
+ }
+ final long dictionarySize =
ByteUtils.fromLittleEndian(coder.properties, 1, 4);
+ if (dictionarySize > LZMAInputStream.DICT_SIZE_MAX) {
+ throw new ArchiveException("Dictionary larger than 4 GiB maximum
size");
+ }
+ return (int) dictionarySize;
}
private LZMA2Options getOptions(final Object opts) throws IOException {
diff --git
a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZLZMADecoderTest.java
b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZLZMADecoderTest.java
new file mode 100644
index 000000000..ae6383317
--- /dev/null
+++
b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZLZMADecoderTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.sevenz;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for class {@link LZMADecoder}.
+ *
+ * @see LZMADecoder
+ **/
+class SevenZLZMADecoderTest {
+
+ private static final byte VALID_PROPS_BYTE = 0x5d; // lc=3, lp=0, pb=2
+
+ @Test
+ void testDecodeRejectsOversizedDictionary() {
+ // 5 valid property bytes but a 4 GiB - 1 dictionary size; the value
must not narrow to a negative int and slip past the cap
+ final byte[] properties = { VALID_PROPS_BYTE, (byte) 0xff, (byte)
0xff, (byte) 0xff, (byte) 0xff };
+ final Coder coder = new Coder(null, 0, 0, properties);
+ assertThrows(ArchiveException.class,
+ () -> new LZMADecoder().decode("x", new
ByteArrayInputStream(new byte[0]), 0, coder, null, Integer.MAX_VALUE));
+ }
+
+ @Test
+ void testDecodeRejectsShortProperties() throws IOException {
+ // LZMA properties are 5 bytes; a shorter field must not over-read the
dictionary size bytes
+ final byte[] properties = { VALID_PROPS_BYTE };
+ final Coder coder = new Coder(null, 0, 0, properties);
+ assertThrows(ArchiveException.class,
+ () -> new LZMADecoder().decode("x", new
ByteArrayInputStream(new byte[0]), 0, coder, null, Integer.MAX_VALUE));
+ }
+}