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-bcel.git
The following commit(s) were added to refs/heads/master by this push:
new 2c8e5fa5 PMG attribute ignores declared length, enabling BCEL-vs-JVM
parse divergence (f019).
2c8e5fa5 is described below
commit 2c8e5fa5a565da8cb8bdbbb9dd4d24437974fe7e
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Sep 4 17:52:30 2026 -0400
PMG attribute ignores declared length, enabling BCEL-vs-JVM parse
divergence (f019).
---
src/changes/changes.xml | 1 +
.../java/org/apache/bcel/classfile/PMGClass.java | 3 +-
.../org/apache/bcel/classfile/PMGClassTest.java | 50 ++++++++++++++++++++++
3 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 515a661a..6062f03e 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -104,6 +104,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="fix" dev="ggregory" due-to="Gary
Gregory">Class2HTML emitters write attacker class-file strings into HTML
unescaped (stored XSS in reports) (f014).</action>
<action type="fix" dev="ggregory" due-to="Gary
Gregory">Class2HTML builds output file paths from the unvalidated class name
(f015).</action>
<action type="fix" dev="ggregory" due-to="Gary
Gregory">ClassPath.getBytes() sizes its buffer from the forged ZIP
uncompressed-size field (f016).</action>
+ <action type="fix" dev="ggregory" due-to="Gary
Gregory">PMG attribute ignores declared length, enabling BCEL-vs-JVM parse
divergence (f019).</action>
<!-- ADD -->
<action type="add" dev="ggregory" due-to="nbauma109,
Gary Gregory">Add support for permitted subclasses #493.</action>
<action type="add" dev="ggregory" due-to="nbauma109,
Gary Gregory">Add RecordComponentInfo.getAttribute(byte tag)#494.</action>
diff --git a/src/main/java/org/apache/bcel/classfile/PMGClass.java
b/src/main/java/org/apache/bcel/classfile/PMGClass.java
index 495de76a..70d27a5b 100644
--- a/src/main/java/org/apache/bcel/classfile/PMGClass.java
+++ b/src/main/java/org/apache/bcel/classfile/PMGClass.java
@@ -23,6 +23,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.bcel.Const;
+import org.apache.bcel.util.Args;
/**
* This class is derived from <em>Attribute</em> and represents a reference to
a PMG attribute.
@@ -57,7 +58,7 @@ public final class PMGClass extends Attribute {
* @param constantPool Array of constants.
*/
public PMGClass(final int nameIndex, final int length, final int pmgIndex,
final int pmgClassIndex, final ConstantPool constantPool) {
- super(Const.ATTR_PMG, nameIndex, length, constantPool);
+ super(Const.ATTR_PMG, nameIndex, Args.require(length, 4, "PMG
attribute length"), constantPool);
this.pmgIndex = pmgIndex;
this.pmgClassIndex = pmgClassIndex;
}
diff --git a/src/test/java/org/apache/bcel/classfile/PMGClassTest.java
b/src/test/java/org/apache/bcel/classfile/PMGClassTest.java
new file mode 100644
index 00000000..dea22836
--- /dev/null
+++ b/src/test/java/org/apache/bcel/classfile/PMGClassTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.bcel.classfile;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link PMGClass}.
+ */
+class PMGClassTest {
+
+ private ConstantPool newConstantPool() {
+ return new ConstantPool(new ConstantUtf8("PMG"), new
ConstantUtf8("pmg-value"), new ConstantUtf8("pmg.Class"));
+ }
+
+ /**
+ * A PMG attribute body is exactly two u2 values; a mismatched declared
length would let the remainder of the
+ * attribute be reparsed as subsequent class file structures, diverging
from a JVM that skips the attribute by its
+ * declared length.
+ */
+ @Test
+ void testDeclaredLengthMustMatchContent() {
+ assertThrowsExactly(ClassFormatException.class, () -> new PMGClass(1,
8, 2, 3, newConstantPool()));
+ assertThrowsExactly(ClassFormatException.class, () -> new PMGClass(1,
0, 2, 3, newConstantPool()));
+ }
+
+ @Test
+ void testValidLength() {
+ assertEquals(4, new PMGClass(1, 4, 2, 3,
newConstantPool()).getLength());
+ }
+}