From ac993896cc84952c81897358287fd56e30454944 Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Tue, 20 Nov 2012 06:17:52 +0100 Subject: [PATCH] Fixed writing private fields with a compiled structure modifier. Incredibly hard to track down. Lucked out by randomly removing a semicolon. --- .../compiler/CompiledStructureModifier.java | 25 ++++++------- .../reflect/compiler/StructureCompiler.java | 35 +++++++++++-------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java index 45bca0f9..0698892c 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java @@ -30,9 +30,8 @@ import com.google.common.collect.Sets; * Represents a compiled structure modifier. * * @author Kristian - * @param Field type. */ -public abstract class CompiledStructureModifier extends StructureModifier { +public abstract class CompiledStructureModifier extends StructureModifier { // Used to compile instances of structure modifiers protected StructureCompiler compiler; @@ -64,9 +63,8 @@ public abstract class CompiledStructureModifier extends StructureModifie } // Speed up the default writer - @SuppressWarnings("unchecked") @Override - public StructureModifier writeDefaults() throws FieldAccessException { + public StructureModifier writeDefaults() throws FieldAccessException { DefaultInstances generator = DefaultInstances.DEFAULT; @@ -75,21 +73,20 @@ public abstract class CompiledStructureModifier extends StructureModifie Integer index = entry.getValue(); Field field = entry.getKey(); - write(index, (TField) generator.getDefault(field.getType())); + write(index, (Object) generator.getDefault(field.getType())); } return this; } - @SuppressWarnings("unchecked") @Override - public final TField read(int fieldIndex) throws FieldAccessException { + public final Object read(int fieldIndex) throws FieldAccessException { Object result = readGenerated(fieldIndex); if (converter != null) return converter.getSpecific(result); else - return (TField) result; + return result; } /** @@ -104,11 +101,10 @@ public abstract class CompiledStructureModifier extends StructureModifie protected abstract Object readGenerated(int fieldIndex) throws FieldAccessException; - @SuppressWarnings("unchecked") @Override - public StructureModifier write(int index, Object value) throws FieldAccessException { + public StructureModifier write(int index, Object value) throws FieldAccessException { if (converter != null) - value = converter.getGeneric(getFieldType(index), (TField) value); + value = converter.getGeneric(getFieldType(index), value); return writeGenerated(index, value); } @@ -118,15 +114,14 @@ public abstract class CompiledStructureModifier extends StructureModifie * @param value - new value. * @throws FieldAccessException The field doesn't exist, or it cannot be accessed under the current security contraints. */ - @SuppressWarnings("unchecked") protected void writeReflected(int index, Object value) throws FieldAccessException { - super.write(index, (TField) value); + super.write(index, value); } - protected abstract StructureModifier writeGenerated(int index, Object value) throws FieldAccessException; + protected abstract StructureModifier writeGenerated(int index, Object value) throws FieldAccessException; @Override - public StructureModifier withTarget(Object target) { + public StructureModifier withTarget(Object target) { if (compiler != null) return compiler.compile(super.withTarget(target)); else diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/StructureCompiler.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/StructureCompiler.java index 87175da6..ac49f45b 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/StructureCompiler.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/StructureCompiler.java @@ -138,7 +138,7 @@ public final class StructureCompiler { * Construct a structure compiler. * @param loader - main class loader. */ - StructureCompiler(ClassLoader loader) { + public StructureCompiler(ClassLoader loader) { this.loader = loader; } @@ -219,15 +219,14 @@ public final class StructureCompiler { } cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, PACKAGE_NAME + "/" + className, - "L" + COMPILED_CLASS + ";", - COMPILED_CLASS, null); + null, COMPILED_CLASS, null); createFields(cw, targetSignature); createConstructor(cw, className, targetSignature, targetName); createReadMethod(cw, className, source.getFields(), targetSignature, targetName); createWriteMethod(cw, className, source.getFields(), targetSignature, targetName); cw.visitEnd(); - + byte[] data = cw.toByteArray(); // Call the define method @@ -295,14 +294,16 @@ public final class StructureCompiler { private void createWriteMethod(ClassWriter cw, String className, List fields, String targetSignature, String targetName) { String methodDescriptor = "(ILjava/lang/Object;)L" + SUPER_CLASS + ";"; - String methodSignature = "(ITTField;)L" + SUPER_CLASS + ";"; + String methodSignature = "(ILjava/lang/Object;)L" + SUPER_CLASS + ";"; MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, "writeGenerated", methodDescriptor, methodSignature, new String[] { FIELD_EXCEPTION_CLASS }); BoxingHelper boxingHelper = new BoxingHelper(mv); + String generatedClassName = PACKAGE_NAME + "/" + className; + mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitFieldInsn(Opcodes.GETFIELD, PACKAGE_NAME + "/" + className, "typedTarget", targetSignature); + mv.visitFieldInsn(Opcodes.GETFIELD, generatedClassName, "typedTarget", targetSignature); mv.visitVarInsn(Opcodes.ASTORE, 3); mv.visitVarInsn(Opcodes.ILOAD, 1); @@ -351,7 +352,7 @@ public final class StructureCompiler { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ILOAD, 1); mv.visitVarInsn(Opcodes.ALOAD, 2); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, COMPILED_CLASS, "writeReflected", "(ILjava/lang/Object;)V;"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedClassName, "writeReflected", "(ILjava/lang/Object;)V"); } mv.visitJumpInsn(Opcodes.GOTO, returnLabel); @@ -384,9 +385,11 @@ public final class StructureCompiler { new String[] { "com/comphenix/protocol/reflect/FieldAccessException" }); BoxingHelper boxingHelper = new BoxingHelper(mv); + String generatedClassName = PACKAGE_NAME + "/" + className; + mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitFieldInsn(Opcodes.GETFIELD, PACKAGE_NAME + "/" + className, "typedTarget", targetSignature); + mv.visitFieldInsn(Opcodes.GETFIELD, generatedClassName, "typedTarget", targetSignature); mv.visitVarInsn(Opcodes.ASTORE, 2); mv.visitVarInsn(Opcodes.ILOAD, 1); @@ -425,7 +428,7 @@ public final class StructureCompiler { // We have to use reflection for private and protected fields. mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ILOAD, 1); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, COMPILED_CLASS, "readReflected", "(I)Ljava/lang/Object;"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedClassName, "readReflected", "(I)Ljava/lang/Object;"); } mv.visitInsn(Opcodes.ARETURN); @@ -451,25 +454,27 @@ public final class StructureCompiler { private void createConstructor(ClassWriter cw, String className, String targetSignature, String targetName) { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "(L" + SUPER_CLASS + ";L" + PACKAGE_NAME + "/StructureCompiler;)V", - "(L" + SUPER_CLASS + ";L" + SUPER_CLASS + ";)V", null); + "(L" + SUPER_CLASS + ";L" + PACKAGE_NAME + "/StructureCompiler;)V", null); + String fullClassName = PACKAGE_NAME + "/" + className; + mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, COMPILED_CLASS, "", "()V"); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 1); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, PACKAGE_NAME + "/" + className, "initialize", "(L" + SUPER_CLASS + ";)V"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, fullClassName, "initialize", "(L" + SUPER_CLASS + ";)V"); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, SUPER_CLASS, "getTarget", "()Ljava/lang/Object;"); - mv.visitFieldInsn(Opcodes.PUTFIELD, PACKAGE_NAME + "/" + className, "target", "Ljava/lang/Object;"); + mv.visitFieldInsn(Opcodes.PUTFIELD, fullClassName, "target", "Ljava/lang/Object;"); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitFieldInsn(Opcodes.GETFIELD, PACKAGE_NAME + "/" + className, "target", "Ljava/lang/Object;"); + mv.visitFieldInsn(Opcodes.GETFIELD, fullClassName, "target", "Ljava/lang/Object;"); mv.visitTypeInsn(Opcodes.CHECKCAST, targetName); - mv.visitFieldInsn(Opcodes.PUTFIELD, PACKAGE_NAME + "/" + className, "typedTarget", targetSignature); + mv.visitFieldInsn(Opcodes.PUTFIELD, fullClassName, "typedTarget", targetSignature); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 2); - mv.visitFieldInsn(Opcodes.PUTFIELD, PACKAGE_NAME + "/" + className, "compiler", "L" + PACKAGE_NAME + "/StructureCompiler;"); + mv.visitFieldInsn(Opcodes.PUTFIELD, fullClassName, "compiler", "L" + PACKAGE_NAME + "/StructureCompiler;"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(2, 3); mv.visitEnd();