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 63df9b9a Escape referenced names in BCELFactory java output (#501)
63df9b9a is described below

commit 63df9b9a05903d15c141d34dad8e4758b75ea665
Author: Dexter.k <[email protected]>
AuthorDate: Mon Jun 15 21:25:58 2026 +0000

    Escape referenced names in BCELFactory java output (#501)
    
    * escape constant pool names in BCELFactory java output
    
    * escape remaining constant pool names in BCELifier output
---
 .../java/org/apache/bcel/util/BCELFactory.java     | 12 ++--
 src/main/java/org/apache/bcel/util/BCELifier.java  | 34 +++++++----
 .../java/org/apache/bcel/util/BCELifierTest.java   | 71 ++++++++++++++++++++++
 3 files changed, 101 insertions(+), 16 deletions(-)

diff --git a/src/main/java/org/apache/bcel/util/BCELFactory.java 
b/src/main/java/org/apache/bcel/util/BCELFactory.java
index d515a27c..59674b68 100644
--- a/src/main/java/org/apache/bcel/util/BCELFactory.java
+++ b/src/main/java/org/apache/bcel/util/BCELFactory.java
@@ -112,7 +112,7 @@ final class BCELFactory extends EmptyVisitor {
             embed += "L";
         } else if (value instanceof ObjectType) {
             final ObjectType ot = (ObjectType) value;
-            embed = "new ObjectType(\"" + ot.getClassName() + "\")";
+            embed = "new ObjectType(\"" + 
Utility.convertString(ot.getClassName()) + "\")";
         } else if (value instanceof ArrayType) {
             final ArrayType at = (ArrayType) value;
             embed = "new ArrayType(" + BCELifier.printType(at.getBasicType()) 
+ ", " + at.getDimensions() + ")";
@@ -184,7 +184,7 @@ final class BCELFactory extends EmptyVisitor {
         int dim = 1;
         switch (opcode) {
         case Const.NEW:
-            printWriter.println("il.append(_factory.createNew(\"" + 
((ObjectType) type).getClassName() + "\"));");
+            printWriter.println("il.append(_factory.createNew(\"" + 
Utility.convertString(((ObjectType) type).getClassName()) + "\"));");
             break;
         case Const.MULTIANEWARRAY:
             dim = ((MULTIANEWARRAY) i).getDimensions();
@@ -271,7 +271,8 @@ final class BCELFactory extends EmptyVisitor {
         final String className = i.getClassName(constantPoolGen);
         final String fieldName = i.getFieldName(constantPoolGen);
         final Type type = i.getFieldType(constantPoolGen);
-        printWriter.println("il.append(_factory.createFieldAccess(\"" + 
className + "\", \"" + fieldName + "\", " + BCELifier.printType(type) + ", "
+        printWriter.println("il.append(_factory.createFieldAccess(\"" + 
Utility.convertString(className) + "\", \"" + Utility.convertString(fieldName) 
+ "\", "
+                + BCELifier.printType(type) + ", "
                 + CONSTANT_PREFIX + 
StringUtils.toRootUpperCase(Const.getOpcodeName(opcode)) + "));");
     }
 
@@ -297,8 +298,9 @@ final class BCELFactory extends EmptyVisitor {
         final String methodName = i.getMethodName(constantPoolGen);
         final Type type = i.getReturnType(constantPoolGen);
         final Type[] argTypes = i.getArgumentTypes(constantPoolGen);
-        printWriter.println("il.append(_factory.createInvoke(\"" + className + 
"\", \"" + methodName + "\", " + BCELifier.printType(type) + ", "
-            + BCELifier.printArgumentTypes(argTypes) + ", " + CONSTANT_PREFIX 
+ StringUtils.toRootUpperCase(Const.getOpcodeName(opcode)) + "));");
+        printWriter.println("il.append(_factory.createInvoke(\"" + 
Utility.convertString(className) + "\", \"" + Utility.convertString(methodName) 
+ "\", "
+            + BCELifier.printType(type) + ", " + 
BCELifier.printArgumentTypes(argTypes) + ", " + CONSTANT_PREFIX
+            + StringUtils.toRootUpperCase(Const.getOpcodeName(opcode)) + 
"));");
     }
 
     @Override
diff --git a/src/main/java/org/apache/bcel/util/BCELifier.java 
b/src/main/java/org/apache/bcel/util/BCELifier.java
index f59d6794..e6039d88 100644
--- a/src/main/java/org/apache/bcel/util/BCELifier.java
+++ b/src/main/java/org/apache/bcel/util/BCELifier.java
@@ -96,6 +96,17 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         bcelifier.start();
     }
 
+    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;
+    }
+
     static String printArgumentTypes(final Type[] argTypes) {
         if (argTypes.length == 0) {
             return "Type.NO_ARGS";
@@ -210,7 +221,7 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         final String className = clazz.getClassName();
         printWriter.println("  public static void main(String[] args) throws 
Exception {");
         printWriter.println("    " + className + "Creator creator = new " + 
className + "Creator();");
-        printWriter.println("    creator.create(new FileOutputStream(\"" + 
className + ".class\"));");
+        printWriter.println("    creator.create(new FileOutputStream(\"" + 
Utility.convertString(className) + ".class\"));");
         printWriter.println("  }");
     }
 
@@ -225,8 +236,8 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
     @Override
     public void visitField(final Field field) {
         printWriter.println();
-        printWriter.println(
-            "    field = new FieldGen(" + printFlags(field.getAccessFlags()) + 
", " + printType(field.getSignature()) + ", \"" + field.getName() + "\", 
_cp);");
+        printWriter.println("    field = new FieldGen(" + 
printFlags(field.getAccessFlags()) + ", " + printType(field.getSignature()) + 
", \""
+            + Utility.convertString(field.getName()) + "\", _cp);");
         final ConstantValue cv = field.getConstantValue();
         if (cv != null) {
             printWriter.print("    field.setInitValue(");
@@ -259,7 +270,7 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         String className = clazz.getClassName();
         final String superName = clazz.getSuperclassName();
         final String packageName = clazz.getPackageName();
-        final String inter = Utility.printArray(clazz.getInterfaceNames(), 
false, true);
+        final String inter = 
Utility.printArray(escape(clazz.getInterfaceNames()), false, true);
         if (StringUtils.isNotEmpty(packageName)) {
             className = className.substring(packageName.length() + 1);
             printWriter.println("package " + packageName + ";");
@@ -276,8 +287,9 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         printWriter.println("  private ClassGen           _cg;");
         printWriter.println();
         printWriter.println("  public " + className + "Creator() {");
-        printWriter.println("    _cg = new ClassGen(\"" + 
(packageName.isEmpty() ? className : packageName + "." + className) + "\", \"" 
+ superName
-            + "\", \"" + clazz.getSourceFileName() + "\", " + 
printFlags(clazz.getAccessFlags(), FLAGS.CLASS) + ", " + "new String[] { " + 
inter + " });");
+        printWriter.println("    _cg = new ClassGen(\"" + 
Utility.convertString(packageName.isEmpty() ? className : packageName + "." + 
className) + "\", \""
+            + Utility.convertString(superName) + "\", \"" + 
Utility.convertString(clazz.getSourceFileName()) + "\", "
+            + printFlags(clazz.getAccessFlags(), FLAGS.CLASS) + ", " + "new 
String[] { " + inter + " });");
         printWriter.println("    _cg.setMajor(" + clazz.getMajor() + ");");
         printWriter.println("    _cg.setMinor(" + clazz.getMinor() + ");");
         printWriter.println();
@@ -312,14 +324,14 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         final MethodGen mg = new MethodGen(method, clazz.getClassName(), 
constantPoolGen);
         printWriter.println("    InstructionList il = new InstructionList();");
         printWriter.println("    MethodGen method = new MethodGen(" + 
printFlags(method.getAccessFlags(), FLAGS.METHOD) + ", " + 
printType(mg.getReturnType())
-            + ", " + printArgumentTypes(mg.getArgumentTypes()) + ", new 
String[] { " + Utility.printArray(mg.getArgumentNames(), false, true) + " }, \""
-            + method.getName() + "\", \"" + clazz.getClassName() + "\", il, 
_cp);");
+            + ", " + printArgumentTypes(mg.getArgumentTypes()) + ", new 
String[] { " + Utility.printArray(escape(mg.getArgumentNames()), false, true) + 
" }, \""
+            + Utility.convertString(method.getName()) + "\", \"" + 
Utility.convertString(clazz.getClassName()) + "\", il, _cp);");
         final ExceptionTable exceptionTable = method.getExceptionTable();
         if (exceptionTable != null) {
             final String[] exceptionNames = exceptionTable.getExceptionNames();
             for (final String exceptionName : exceptionNames) {
                 printWriter.print("    method.addException(\"");
-                printWriter.print(exceptionName);
+                printWriter.print(Utility.convertString(exceptionName));
                 printWriter.println("\");");
             }
         }
@@ -344,7 +356,7 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         super.visitStackMap(stackMap);
         printWriter.print("    method.addCodeAttribute(");
         printWriter.print("new StackMap(_cp.addUtf8(\"");
-        printWriter.print(stackMap.getName());
+        printWriter.print(Utility.convertString(stackMap.getName()));
         printWriter.print("\"), ");
         printWriter.print(stackMap.getLength());
         printWriter.print(", ");
@@ -390,7 +402,7 @@ public class BCELifier extends 
org.apache.bcel.classfile.EmptyVisitor {
         printWriter.print(", ");
         if (stackMapType.hasIndex()) {
             printWriter.print("_cp.addClass(\"");
-            printWriter.print(stackMapType.getClassName());
+            
printWriter.print(Utility.convertString(stackMapType.getClassName()));
             printWriter.print("\")");
         } else {
             printWriter.print("-1");
diff --git a/src/test/java/org/apache/bcel/util/BCELifierTest.java 
b/src/test/java/org/apache/bcel/util/BCELifierTest.java
index 7a87577b..2f4e1733 100644
--- a/src/test/java/org/apache/bcel/util/BCELifierTest.java
+++ b/src/test/java/org/apache/bcel/util/BCELifierTest.java
@@ -19,6 +19,7 @@
 package org.apache.bcel.util;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -34,10 +35,18 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.bcel.AbstractTest;
+import org.apache.bcel.Const;
 import org.apache.bcel.HelloWorldCreator;
 import org.apache.bcel.classfile.JavaClass;
 import org.apache.bcel.classfile.Utility;
 import org.apache.bcel.generic.BinaryOpCreator;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.InstructionConst;
+import org.apache.bcel.generic.InstructionFactory;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.Type;
 import org.apache.commons.lang3.SystemProperties;
 import org.apache.commons.lang3.SystemUtils;
 import org.junit.jupiter.api.Test;
@@ -279,6 +288,68 @@ class BCELifierTest extends AbstractTest {
         assertEquals("Hello World" + EOL, exec(workDir, getAppJava(), "-cp", 
CLASSPATH, className, "Hello"));
     }
 
+    @Test
+    void testCreateInvokeEscapesConstantPoolName() throws Exception {
+        // A hostile constant pool can hold any UTF-8 as a referenced method 
name.
+        final String evilName = "evil\"); System.exit(1); il.append(\"";
+        final ClassGen cg = new ClassGen("Example", "java.lang.Object", 
"Example.java", Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
+        final ConstantPoolGen cp = cg.getConstantPool();
+        final InstructionFactory factory = new InstructionFactory(cg, cp);
+        final InstructionList il = new InstructionList();
+        il.append(InstructionConst.ALOAD_0);
+        il.append(factory.createInvoke("java.lang.Object", evilName, 
Type.VOID, Type.NO_ARGS, Const.INVOKEVIRTUAL));
+        il.append(InstructionConst.RETURN);
+        final MethodGen mg = new MethodGen(Const.ACC_PUBLIC, Type.VOID, 
Type.NO_ARGS, new String[] {}, "m", "Example", il, cp);
+        mg.setMaxStack();
+        mg.setMaxLocals();
+        cg.addMethod(mg.getMethod());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        new BCELifier(cg.getJavaClass(), os).start();
+        final String source = new String(os.toByteArray(), 
StandardCharsets.UTF_8);
+
+        
assertTrue(source.contains("_factory.createInvoke(\"java.lang.Object\", \"" + 
Utility.convertString(evilName) + "\", "), source);
+        assertFalse(source.contains('"' + evilName + '"'), source);
+    }
+
+    @Test
+    void testMethodNameEscapedInOutput() throws Exception {
+        // A hostile constant pool can hold any UTF-8 as a method name.
+        final String evilName = "evil\"); System.exit(1); String x = (\"";
+        final ClassGen cg = new ClassGen("Example", "java.lang.Object", 
"Example.java", Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
+        final ConstantPoolGen cp = cg.getConstantPool();
+        final InstructionList il = new InstructionList();
+        il.append(InstructionConst.RETURN);
+        final MethodGen mg = new MethodGen(Const.ACC_PUBLIC, Type.VOID, 
Type.NO_ARGS, new String[] {}, evilName, "Example", il, cp);
+        mg.setMaxStack();
+        mg.setMaxLocals();
+        cg.addMethod(mg.getMethod());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        new BCELifier(cg.getJavaClass(), os).start();
+        final String source = new String(os.toByteArray(), 
StandardCharsets.UTF_8);
+
+        assertTrue(source.contains("\"" + Utility.convertString(evilName) + 
"\", \"Example\", il, _cp);"), source);
+        assertFalse(source.contains('"' + evilName + '"'), source);
+    }
+
+    @Test
+    void testClassNamesEscapedInOutput() throws Exception {
+        // Superclass and source file names are constant-pool derived and can 
hold any UTF-8.
+        final String evilSuper = "java.lang.Object\"); System.exit(1); _cg = 
new ClassGen(\"x";
+        final String evilSource = "Example.java\"); System.exit(2); String s = 
(\"";
+        final ClassGen cg = new ClassGen("Example", evilSuper, evilSource, 
Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        new BCELifier(cg.getJavaClass(), os).start();
+        final String source = new String(os.toByteArray(), 
StandardCharsets.UTF_8);
+
+        assertTrue(source.contains(Utility.convertString(evilSuper)), source);
+        assertTrue(source.contains(Utility.convertString(evilSource)), source);
+        assertFalse(source.contains('"' + evilSuper + '"'), source);
+        assertFalse(source.contains('"' + evilSource + '"'), source);
+    }
+
     @Test
     void testStart() throws Exception {
         final OutputStream os = new ByteArrayOutputStream();

Reply via email to