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