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 279ec230 Sort members
279ec230 is described below

commit 279ec2300c1d9757061454c200d5e19090bee39e
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Sep 4 20:19:11 2026 -0400

    Sort members
---
 .../java/org/apache/bcel/classfile/Signature.java  | 12 ++--
 src/main/java/org/apache/bcel/util/BCELifier.java  | 22 ++++----
 src/main/java/org/apache/bcel/util/Class2HTML.java | 64 +++++++++++-----------
 .../bcel/verifier/structurals/Subroutines.java     | 16 +++---
 .../java/org/apache/bcel/util/BCELifierTest.java   | 22 ++++----
 5 files changed, 68 insertions(+), 68 deletions(-)

diff --git a/src/main/java/org/apache/bcel/classfile/Signature.java 
b/src/main/java/org/apache/bcel/classfile/Signature.java
index 68b12c88..4a43cccf 100644
--- a/src/main/java/org/apache/bcel/classfile/Signature.java
+++ b/src/main/java/org/apache/bcel/classfile/Signature.java
@@ -55,6 +55,12 @@ public final class Signature extends Attribute {
         }
     }
 
+    /**
+     * The maximum nesting depth of a signature accepted by {@link 
#translate(String)}. Guards against a
+     * {@link StackOverflowError} from deeply nested, attacker-supplied 
generic signatures.
+     */
+    private static final int MAX_NESTING_DEPTH = 512;
+
     private static boolean identStart(final int ch) {
         return ch == 'T' || ch == 'L';
     }
@@ -81,12 +87,6 @@ public final class Signature extends Attribute {
         return s.startsWith("<") && s.indexOf(':') > 0;
     }
 
-    /**
-     * The maximum nesting depth of a signature accepted by {@link 
#translate(String)}. Guards against a
-     * {@link StackOverflowError} from deeply nested, attacker-supplied 
generic signatures.
-     */
-    private static final int MAX_NESTING_DEPTH = 512;
-
     private static void matchGJIdent(final MyByteArrayInputStream in, final 
StringBuilder buf) {
         matchGJIdent(in, buf, 0);
     }
diff --git a/src/main/java/org/apache/bcel/util/BCELifier.java 
b/src/main/java/org/apache/bcel/util/BCELifier.java
index ab869363..a40c8a94 100644
--- a/src/main/java/org/apache/bcel/util/BCELifier.java
+++ b/src/main/java/org/apache/bcel/util/BCELifier.java
@@ -71,17 +71,6 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
     private static final String BASE_PACKAGE = 
Const.class.getPackage().getName();
     private static final String CONSTANT_PREFIX = Const.class.getSimpleName() 
+ ".";
 
-    private static String[] escape(final String[] names) {
-        if (names == null) {
-            return null;
-        }
-        final String[] escaped = new String[names.length];
-        for (int i = 0; i < names.length; i++) {
-            escaped[i] = names[i] == null ? null : 
Utility.convertString(names[i]);
-        }
-        return escaped;
-    }
-
     /**
      * Checks that a name from the parsed class file is a dotted sequence of 
valid Java identifiers before it is
      * emitted in identifier position of the generated source. The class file 
format allows characters in names (for
@@ -113,6 +102,17 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         return name;
     }
 
+    private static String[] escape(final String[] names) {
+        if (names == null) {
+            return null;
+        }
+        final String[] escaped = new String[names.length];
+        for (int i = 0; i < names.length; i++) {
+            escaped[i] = names[i] == null ? null : 
Utility.convertString(names[i]);
+        }
+        return escaped;
+    }
+
     // Needs to be accessible from unit test code
     static JavaClass getJavaClass(final String name) throws 
ClassNotFoundException, IOException {
         JavaClass javaClass;
diff --git a/src/main/java/org/apache/bcel/util/Class2HTML.java 
b/src/main/java/org/apache/bcel/util/Class2HTML.java
index 69d010c3..bb3e252e 100644
--- a/src/main/java/org/apache/bcel/util/Class2HTML.java
+++ b/src/main/java/org/apache/bcel/util/Class2HTML.java
@@ -71,6 +71,29 @@ public class Class2HTML implements Constants {
         basicTypes.add("float");
     }
 
+    /**
+     * The class name comes from the attacker-controlled this_class constant 
of the parsed class file and is
+     * concatenated into the five output file paths ("dir + className + 
suffix"). Class file parsing only folds
+     * '/' into '.', so Windows separators ('\\'), drive designators (':') and 
".." segments survive and would
+     * let a crafted class file write its HTML output outside the target 
directory (CWE-22).
+     *
+     * @param name the class name about to be used as part of a file name.
+     * @throws IOException if the name contains a path separator, a 
Windows-reserved file name character, a
+     *         control character, or a ".." sequence.
+     */
+    private static void checkFileNameSafe(final String name) throws 
IOException {
+        for (int i = 0; i < name.length(); i++) {
+            final char c = name.charAt(i);
+            if (c < ' ' || "\\/:*?\"<>|".indexOf(c) >= 0) {
+                throw new IOException("Refusing to write HTML for a class 
whose name contains the unsafe character (0x"
+                    + Integer.toHexString(c) + "): " + name);
+            }
+        }
+        if (name.contains("..")) {
+            throw new IOException("Refusing to write HTML for a class whose 
name contains \"..\": " + name);
+        }
+    }
+
     /**
      * Main program to convert class files to HTML.
      *
@@ -153,15 +176,6 @@ public class Class2HTML implements Constants {
         return "<A HREF=\"" + toHTMLRef(baseType) + ".html\" TARGET=_top>" + 
toHTML(shortType) + "</A>";
     }
 
-    /**
-     * Escapes a class or type name taken from the constant pool for use as a 
relative link target inside an HREF
-     * attribute value. On top of the text escaping done by {@code 
toHTML(String)}, any ':' is replaced so an
-     * attacker-chosen name cannot smuggle a URL scheme such as "javascript:" 
into the generated link.
-     */
-    static String toHTMLRef(final String str) {
-        return toHTML(str.replace(':', '_'));
-    }
-
     static String toHTML(final String str) {
         final StringBuilder buf = new StringBuilder();
         for (int i = 0; i < str.length(); i++) {
@@ -195,6 +209,15 @@ public class Class2HTML implements Constants {
         return buf.toString();
     }
 
+    /**
+     * Escapes a class or type name taken from the constant pool for use as a 
relative link target inside an HREF
+     * attribute value. On top of the text escaping done by {@code 
toHTML(String)}, any ':' is replaced so an
+     * attacker-chosen name cannot smuggle a URL scheme such as "javascript:" 
into the generated link.
+     */
+    static String toHTMLRef(final String str) {
+        return toHTML(str.replace(':', '_'));
+    }
+
     private final JavaClass javaClass; // current class object
 
     private final String dir;
@@ -236,29 +259,6 @@ public class Class2HTML implements Constants {
         }
     }
 
-    /**
-     * The class name comes from the attacker-controlled this_class constant 
of the parsed class file and is
-     * concatenated into the five output file paths ("dir + className + 
suffix"). Class file parsing only folds
-     * '/' into '.', so Windows separators ('\\'), drive designators (':') and 
".." segments survive and would
-     * let a crafted class file write its HTML output outside the target 
directory (CWE-22).
-     *
-     * @param name the class name about to be used as part of a file name.
-     * @throws IOException if the name contains a path separator, a 
Windows-reserved file name character, a
-     *         control character, or a ".." sequence.
-     */
-    private static void checkFileNameSafe(final String name) throws 
IOException {
-        for (int i = 0; i < name.length(); i++) {
-            final char c = name.charAt(i);
-            if (c < ' ' || "\\/:*?\"<>|".indexOf(c) >= 0) {
-                throw new IOException("Refusing to write HTML for a class 
whose name contains the unsafe character (0x"
-                    + Integer.toHexString(c) + "): " + name);
-            }
-        }
-        if (name.contains("..")) {
-            throw new IOException("Refusing to write HTML for a class whose 
name contains \"..\": " + name);
-        }
-    }
-
     private void writeMainHTML(final AttributeHTML attributeHtml, final 
Charset charset) throws FileNotFoundException, UnsupportedEncodingException {
         try (PrintWriter file = new PrintWriter(dir + className + ".html", 
charset.name())) {
             // @formatter:off
diff --git 
a/src/main/java/org/apache/bcel/verifier/structurals/Subroutines.java 
b/src/main/java/org/apache/bcel/verifier/structurals/Subroutines.java
index 2013b7b4..6e00db5d 100644
--- a/src/main/java/org/apache/bcel/verifier/structurals/Subroutines.java
+++ b/src/main/java/org/apache/bcel/verifier/structurals/Subroutines.java
@@ -394,6 +394,14 @@ public class Subroutines {
         return single;
     }
 
+    private static StructuralCodeConstraintException 
recursiveCallException(final Subroutine sub2) {
+        // Don't use toString() here because of possibly infinite recursive 
subSubs() calls then.
+        final SubroutineImpl si = (SubroutineImpl) sub2;
+        return new StructuralCodeConstraintException("Subroutine with local 
variable '" + si.localVariable + "', JSRs '" + si.theJSRs + "', RET '"
+            + si.theRET + "' is called by a subroutine which uses the same 
local variable index as itself; maybe even a recursive call?"
+            + " JustIce's clean definition of a subroutine forbids both.");
+    }
+
     /**
      * The map containing the subroutines found. Key: InstructionHandle of the 
leader of the subroutine. Elements:
      * SubroutineImpl objects.
@@ -678,14 +686,6 @@ public class Subroutines {
         return subtreeLocals;
     }
 
-    private static StructuralCodeConstraintException 
recursiveCallException(final Subroutine sub2) {
-        // Don't use toString() here because of possibly infinite recursive 
subSubs() calls then.
-        final SubroutineImpl si = (SubroutineImpl) sub2;
-        return new StructuralCodeConstraintException("Subroutine with local 
variable '" + si.localVariable + "', JSRs '" + si.theJSRs + "', RET '"
-            + si.theRET + "' is called by a subroutine which uses the same 
local variable index as itself; maybe even a recursive call?"
-            + " JustIce's clean definition of a subroutine forbids both.");
-    }
-
     /**
      * Returns the subroutine object associated with the given instruction. 
This is a costly operation, you should consider
      * using getSubroutine(InstructionHandle). Returns 'null' if the given 
InstructionHandle lies in so-called 'dead code',
diff --git a/src/test/java/org/apache/bcel/util/BCELifierTest.java 
b/src/test/java/org/apache/bcel/util/BCELifierTest.java
index cd605564..715b4016 100644
--- a/src/test/java/org/apache/bcel/util/BCELifierTest.java
+++ b/src/test/java/org/apache/bcel/util/BCELifierTest.java
@@ -177,6 +177,17 @@ class BCELifierTest extends AbstractTest {
         }
     }
 
+    @Test
+    void testClassNameRejectedWhenNotJavaIdentifier() {
+        // Class file names may contain characters the Java language forbids 
(JVMS 4.2.2 bans only . ; [ /).
+        // BCELifier must refuse to emit such a name in identifier position 
rather than let a crafted
+        // this_class inject statements into the generated source.
+        final ClassGen cg = new ClassGen("Evil {}\nclass Injected {}//", 
"java.lang.Object", "Evil.java", Const.ACC_PUBLIC | Const.ACC_SUPER,
+            new String[] {});
+        final BCELifier bcelifier = new BCELifier(cg.getJavaClass(), new 
ByteArrayOutputStream());
+        assertThrows(IllegalArgumentException.class, bcelifier::start);
+    }
+
     @Test
     void testClassNamesEscapedInOutput() throws Exception {
         // Superclass and source file names are constant-pool derived and can 
hold any UTF-8.
@@ -194,17 +205,6 @@ class BCELifierTest extends AbstractTest {
         assertFalse(source.contains('"' + toEscapeSource + '"'), source);
     }
 
-    @Test
-    void testClassNameRejectedWhenNotJavaIdentifier() {
-        // Class file names may contain characters the Java language forbids 
(JVMS 4.2.2 bans only . ; [ /).
-        // BCELifier must refuse to emit such a name in identifier position 
rather than let a crafted
-        // this_class inject statements into the generated source.
-        final ClassGen cg = new ClassGen("Evil {}\nclass Injected {}//", 
"java.lang.Object", "Evil.java", Const.ACC_PUBLIC | Const.ACC_SUPER,
-            new String[] {});
-        final BCELifier bcelifier = new BCELifier(cg.getJavaClass(), new 
ByteArrayOutputStream());
-        assertThrows(IllegalArgumentException.class, bcelifier::start);
-    }
-
     private void testClassOnPath(final String javaClassFileName) throws 
Exception {
         final File workDir = new File("target", getClass().getSimpleName());
         Files.createDirectories(workDir.getParentFile().toPath());

Reply via email to