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.