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 3cdf5d1f Pass 3b dataflow stores frames per instruction and clones 
ever-growing execution chains (f006).
3cdf5d1f is described below

commit 3cdf5d1f5ff06fec3834e7820b5a7c812b9f4ffe
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Sep 4 15:54:40 2026 -0400

    Pass 3b dataflow stores frames per instruction and clones ever-growing
    execution chains (f006).
---
 src/changes/changes.xml                            |  1 +
 .../bcel/verifier/structurals/Pass3bVerifier.java  | 34 +++++++++++++++++++---
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 186cd931..25dcc758 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -93,6 +93,7 @@ The <action> type attribute can be add,update,fix,remove.
       <action                  type="fix" dev="ggregory" due-to="Gary 
Gregory">Opcodes tableswitch and lookupswitch add boundary checks 
(f003).</action>
       <action                  type="fix" dev="ggregory" due-to="Gary 
Gregory">JustIce Pass 2 hangs on cyclic superclass chain of a referenced 
exception class (f004).</action>
       <action                  type="fix" dev="ggregory" due-to="Gary 
Gregory">JustIce Pass 2 LVT check amplifies each 10-byte entry into ~131k 
hashtable operations (f005).</action>
+      <action                  type="fix" dev="ggregory" due-to="Gary 
Gregory">Pass 3b dataflow stores frames per instruction and clones ever-growing 
execution chains (f006).</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/verifier/structurals/Pass3bVerifier.java 
b/src/main/java/org/apache/bcel/verifier/structurals/Pass3bVerifier.java
index 53b9722c..0b6b7a0d 100644
--- a/src/main/java/org/apache/bcel/verifier/structurals/Pass3bVerifier.java
+++ b/src/main/java/org/apache/bcel/verifier/structurals/Pass3bVerifier.java
@@ -47,13 +47,16 @@ import 
org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
 import org.apache.bcel.verifier.exc.VerifierConstraintViolatedException;
 
 /**
- * This PassVerifier verifies a method of class file according to pass 3, 
so-called structural verification as described
- * in The Java Virtual Machine Specification, 2nd edition. More detailed 
information is to be found at the do_verify()
- * method's documentation.
+ * This PassVerifier verifies a method of class file according to pass 3, 
so-called structural verification as described in The Java Virtual Machine
+ * Specification, 2nd edition. More detailed information is to be found at the 
do_verify() method's documentation.
+ * <p>
+ * The system property {@code org.apache.bcel.verifier.maxFrameSlots} bounds 
the size of the pass 3b data flow analysis, measured in frame slots:
+ * {@code (max_locals + max_stack) * instruction count} of the method under 
verification. Methods above the bound are rejected instead of analyzed. The 
default
+ * is 100,000,000; a value of zero or less disables the bound.
+ * </p>
  *
  * @see #do_verify()
  */
-
 public final class Pass3bVerifier extends PassVerifier {
     /*
      * TODO: Throughout pass 3b, upper halves of LONG and DOUBLE are 
represented by Type.UNKNOWN. This should be changed in
@@ -140,6 +143,15 @@ public final class Pass3bVerifier extends PassVerifier {
     /** In DEBUG mode, the verification algorithm is not randomized. */
     private static final boolean DEBUG = true;
 
+    /**
+     * The name of the system property bounding the size of the pass 3b data 
flow analysis, measured in frame slots:
+     * {@code (max_locals + max_stack) * instruction count} of the method 
under verification. Methods above the bound
+     * are rejected instead of analyzed. The default is 100,000,000; a value 
of zero or less disables the bound.
+     */
+    private static final String MAX_FRAME_SLOTS_PROPERTY = 
"org.apache.bcel.verifier.maxFrameSlots";
+
+    private static final long MAX_FRAME_SLOTS = 
Long.getLong(MAX_FRAME_SLOTS_PROPERTY, 100_000_000L).longValue();
+
     /** The Verifier that created this. */
     private final Verifier myOwner;
 
@@ -364,6 +376,20 @@ public final class Pass3bVerifier extends PassVerifier {
             ////////////// DFA BEGINS HERE ////////////////
             if (!(mg.isAbstract() || mg.isNative())) { // IF mg HAS CODE (See 
pass 2)
 
+                // Reject pathological resource claims before running the data 
flow analysis: an 'in' and an 'out'
+                // Frame sized max_locals + max_stack is stored for every 
reachable instruction (and per calling
+                // subroutine), so a small crafted method declaring max_locals 
= max_stack = 65535 over tens of
+                // thousands of instructions would force tens of gigabytes of 
allocations before any constraint
+                // could fail. The limit can be changed (or disabled with a 
value <= 0) via the
+                // MAX_FRAME_SLOTS_PROPERTY system property.
+                final int instructionCount = 
mg.getInstructionList().getLength();
+                final long frameSlots = ((long) mg.getMaxLocals() + 
mg.getMaxStack()) * instructionCount;
+                if (MAX_FRAME_SLOTS > 0 && frameSlots > MAX_FRAME_SLOTS) {
+                    throw new StructuralCodeConstraintException("Data flow 
analysis of this method would require more than " + MAX_FRAME_SLOTS
+                        + " frame slots: max_locals '" + mg.getMaxLocals() + 
"' plus max_stack '" + mg.getMaxStack() + "' over '" + instructionCount
+                        + "' instructions. Adjust the '" + 
MAX_FRAME_SLOTS_PROPERTY + "' system property to change this limit.");
+                }
+
                 final ControlFlowGraph cfg = new ControlFlowGraph(mg);
 
                 // Build the initial frame situation for this method.

Reply via email to