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());
+    }
+}

Reply via email to