diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Configuration.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Configuration.java index d19cbb78d..31bd7acd4 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Configuration.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Configuration.java @@ -46,6 +46,7 @@ public class Configuration { public static ControlFlowManager controlFlowManager = new StandardControlFlowManager(); public static String controlFlowManagerPackage = null; public static boolean QUIET_MODE = false; + // Option is set for Java 9+ JVM by the embedded configuration public static boolean IS_JAVA_8 = true; public static Set ignoredMethods = new HashSet<>(); public static TaintTagFactory taintTagFactory = new DataAndControlFlowTagFactory(); diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PCLoggingTransformer.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PCLoggingTransformer.java index e9454868d..f85b9f114 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PCLoggingTransformer.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PCLoggingTransformer.java @@ -2,6 +2,7 @@ import edu.columbia.cs.psl.phosphor.instrumenter.*; import edu.columbia.cs.psl.phosphor.instrumenter.asm.OffsetPreservingClassReader; +import edu.columbia.cs.psl.phosphor.mask.SerializationFixingCV; import edu.columbia.cs.psl.phosphor.org.objectweb.asm.commons.OurSerialVersionUIDAdder; import edu.columbia.cs.psl.phosphor.runtime.StringUtils; import edu.columbia.cs.psl.phosphor.runtime.TaintInstrumented; diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Phosphor.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Phosphor.java index 335a5988f..8549b1ebb 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Phosphor.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/Phosphor.java @@ -42,13 +42,15 @@ public static InstrumentationAdaptor getInstrumentation() { } @InvokedViaInstrumentation(record = TaintMethodRecord.INSTRUMENT_CLASS_BYTES) - public static byte[] instrumentClassBytes(byte[] in) { - return new PCLoggingTransformer().transform(null, null, null, null, in, false); + public static byte[] instrumentClassBytes(byte[] classFileBuffer) { + byte[] result = new PCLoggingTransformer().transform(null, null, null, null, classFileBuffer, false); + return result == null ? classFileBuffer : result; } @InvokedViaInstrumentation(record = TaintMethodRecord.INSTRUMENT_CLASS_BYTES_ANONYMOUS) - public static byte[] instrumentClassBytesAnonymous(byte[] in) { - return new PCLoggingTransformer().transform(null, null, null, null, in, true); + public static byte[] instrumentClassBytesAnonymous(byte[] classFileBuffer) { + byte[] result = new PCLoggingTransformer().transform(null, null, null, null, classFileBuffer, true); + return result == null ? classFileBuffer : result; } private static String[] parseOptions(String agentArgs) { @@ -64,9 +66,6 @@ private static String[] parseOptions(String agentArgs) { } } } - if (Configuration.IS_JAVA_8) { - options.addLast("-java8"); - } return options.toArray(new String[0]); } @@ -172,7 +171,6 @@ public static boolean isUninstrumentedField(String owner, String name) { } public static boolean isUnsafeClass(String className) { - return (Configuration.IS_JAVA_8 && "sun/misc/Unsafe".equals(className)) - || (!Configuration.IS_JAVA_8 && "jdk/internal/misc/Unsafe".equals(className)); + return "sun/misc/Unsafe".equals(className) || "jdk/internal/misc/Unsafe".equals(className); } } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java index 26a5609d0..3551655dc 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorOption.java @@ -285,12 +285,6 @@ public void configure(boolean forRuntimeInst, boolean isPresent, CommandLine com } } }, - JAVA_8(new PhosphorOptionBuilder(null, true, true).alternativeName("java8")) { - @Override - public void configure(boolean forRuntimeInst, boolean isPresent, CommandLine commandLine) { - Configuration.IS_JAVA_8 = isPresent; - } - }, JVM_MODULES(new PhosphorOptionBuilder("For Java 9+ JVM generation: list of Java modules to include in instrumented JVM", true, false).argType(String.class).alternativeName("jvmModules")) { @Override diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatcher.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatcher.java deleted file mode 100644 index e7f3cb9ab..000000000 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatcher.java +++ /dev/null @@ -1,44 +0,0 @@ -package edu.columbia.cs.psl.phosphor.agent; - -import edu.columbia.cs.psl.phosphor.Configuration; -import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; -import org.objectweb.asm.*; - -public class AsmPatcher extends ClassVisitor { - private static final String ASM_PREFIX = "edu/columbia/cs/psl/phosphor/org/objectweb/asm/"; - private static final Type OBJECT_TYPE = Type.getType(Object.class); - - public AsmPatcher(ClassWriter cw) { - super(Configuration.ASM_VERSION, cw); - } - - @Override - public MethodVisitor visitMethod( - int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - return new MethodVisitor(api, mv) { - - @Override - public void visitMethodInsn( - int opcode, String owner, String name, String descriptor, boolean isInterface) { - super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); - // Ensure that the return value is unwrapped if necessary - if (owner.startsWith("java/") && OBJECT_TYPE.equals(Type.getReturnType(descriptor))) { - TaintMethodRecord.TAINTED_REFERENCE_ARRAY_UNWRAP.delegateVisit(mv); - } - } - }; - } - - public static byte[] patch(byte[] classFileBuffer) { - ClassReader cr = new ClassReader(classFileBuffer); - ClassWriter cw = new ClassWriter(cr, 0); - ClassVisitor cv = new AsmPatcher(cw); - cr.accept(cv, 0); - return cw.toByteArray(); - } - - public static boolean isApplicable(String className) { - return className.startsWith(ASM_PREFIX); - } -} \ No newline at end of file diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatchingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatchingCV.java new file mode 100644 index 000000000..340a3eaff --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatchingCV.java @@ -0,0 +1,42 @@ +package edu.columbia.cs.psl.phosphor.agent; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +public final class AsmPatchingCV extends ClassVisitor { + private static final String ASM_PREFIX = "edu/columbia/cs/psl/phosphor/org/objectweb/asm/"; + private static final Type OBJECT_TYPE = Type.getType(Object.class); + + public AsmPatchingCV(ClassVisitor classVisitor) { + super(Configuration.ASM_VERSION, classVisitor); + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + return new AsmPatchingMV(mv); + } + + public static boolean isApplicable(String className) { + return className.startsWith(ASM_PREFIX); + } + + private static class AsmPatchingMV extends MethodVisitor { + public AsmPatchingMV(MethodVisitor mv) { + super(Configuration.ASM_VERSION, mv); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + // Ensure that the return value is unwrapped if necessary + if (owner.startsWith("java/") && OBJECT_TYPE.equals(Type.getReturnType(descriptor))) { + TaintMethodRecord.TAINTED_REFERENCE_ARRAY_UNWRAP.delegateVisit(mv); + } + } + } +} \ No newline at end of file diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingCV.java new file mode 100644 index 000000000..4cbad5815 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingCV.java @@ -0,0 +1,100 @@ +package edu.columbia.cs.psl.phosphor.agent; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; +import edu.columbia.cs.psl.phosphor.struct.harmony.util.Set; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import static org.objectweb.asm.Opcodes.*; + +/** + * Embeds the current values for the field of {@link Configuration} into the class file for {@link Configuration}. + */ +public class ConfigurationEmbeddingCV extends ClassVisitor { + private static final String TARGET_METHOD_NAME = ""; + + protected ConfigurationEmbeddingCV(ClassVisitor classVisitor) { + super(Configuration.ASM_VERSION, classVisitor); + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + return !name.equals(TARGET_METHOD_NAME) ? mv : new ConfigurationEmbeddingMV(mv); + } + + public static boolean isApplicable(String className) { + return Type.getInternalName(Configuration.class).equals(className); + } + + private static class ConfigurationEmbeddingMV extends MethodVisitor { + protected ConfigurationEmbeddingMV(MethodVisitor methodVisitor) { + super(Configuration.ASM_VERSION, methodVisitor); + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + if (opcode == Opcodes.PUTSTATIC) { + try { + Field f = Configuration.class.getField(name); + f.setAccessible(true); + if (Modifier.isPublic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers())) { + replaceValue(Type.getType(descriptor), f.get(null)); + } + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Failed to access field owned by " + Configuration.class, e); + } + } + super.visitFieldInsn(opcode, owner, name, descriptor); + } + + private void replaceValue(Type type, Object newValue) { + switch (type.getSort()) { + case Type.VOID: + case Type.ARRAY: + case Type.METHOD: + return; + } + // Pop the original value + super.visitInsn(type.getSize() == 1 ? POP : POP2); + // Push the new value + if (type.getSort() != Type.OBJECT || newValue instanceof String) { + super.visitLdcInsn(newValue); + } else if (newValue == null) { + super.visitInsn(ACONST_NULL); + } else if (newValue instanceof Class) { + mv.visitLdcInsn(Type.getType((Class) newValue)); + } else if (newValue instanceof Set) { + Set set = (Set) newValue; + newInstance(newValue.getClass()); + for (Object element : set) { + super.visitInsn(DUP); + super.visitLdcInsn(element); + TaintMethodRecord.SET_ADD.delegateVisit(mv); + super.visitInsn(POP); + } + } else { + newInstance(newValue.getClass()); + } + } + + private void newInstance(Class clazz) { + try { + clazz.getConstructor(); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Public, zero-argument constructor not found for: " + clazz); + } + String className = Type.getInternalName(clazz); + super.visitTypeInsn(Opcodes.NEW, className); + super.visitInsn(DUP); + super.visitMethodInsn(INVOKESPECIAL, className, "", "()V", false); + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingMV.java deleted file mode 100644 index e204be3a7..000000000 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingMV.java +++ /dev/null @@ -1,80 +0,0 @@ -package edu.columbia.cs.psl.phosphor.agent; - -import edu.columbia.cs.psl.phosphor.Configuration; -import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; -import edu.columbia.cs.psl.phosphor.struct.harmony.util.Set; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -import static org.objectweb.asm.Opcodes.*; - -/** - * Embeds the current values for the field of {@link Configuration} into the class file for {@link Configuration}. - */ -public class ConfigurationEmbeddingMV extends MethodVisitor { - public ConfigurationEmbeddingMV(MethodVisitor mv) { - super(Configuration.ASM_VERSION, mv); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { - if (opcode == Opcodes.PUTSTATIC) { - try { - Field f = Configuration.class.getField(name); - f.setAccessible(true); - if (Modifier.isPublic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers())) { - replaceValue(Type.getType(descriptor), f.get(null)); - } - } catch (ReflectiveOperationException e) { - throw new RuntimeException("Failed to access field owned by " + Configuration.class, e); - } - } - super.visitFieldInsn(opcode, owner, name, descriptor); - } - - public void replaceValue(Type type, Object newValue) { - switch (type.getSort()) { - case Type.VOID: - case Type.ARRAY: - case Type.METHOD: - return; - } - // Pop the original value - super.visitInsn(type.getSize() == 1 ? POP : POP2); - // Push the new value - if (type.getSort() != Type.OBJECT || newValue instanceof String) { - super.visitLdcInsn(newValue); - } else if (newValue == null) { - super.visitInsn(ACONST_NULL); - } else if (newValue instanceof Class) { - mv.visitLdcInsn(Type.getType((Class) newValue)); - } else if (newValue instanceof Set) { - Set set = (Set) newValue; - newInstance(newValue.getClass()); - for (Object element : set) { - super.visitInsn(DUP); - super.visitLdcInsn(element); - TaintMethodRecord.SET_ADD.delegateVisit(mv); - super.visitInsn(POP); - } - } else { - newInstance(newValue.getClass()); - } - } - - private void newInstance(Class clazz) { - try { - clazz.getConstructor(); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("Public, zero-argument constructor not found for: " + clazz); - } - String className = Type.getInternalName(clazz); - super.visitTypeInsn(Opcodes.NEW, className); - super.visitInsn(DUP); - super.visitMethodInsn(INVOKESPECIAL, className, "", "()V", false); - } -} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/EmbeddedPhosphorPatcher.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/EmbeddedPhosphorPatcher.java index 373d18a55..78989c2bc 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/EmbeddedPhosphorPatcher.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/EmbeddedPhosphorPatcher.java @@ -1,35 +1,29 @@ package edu.columbia.cs.psl.phosphor.agent; -import edu.columbia.cs.psl.phosphor.Configuration; -import edu.columbia.cs.psl.phosphor.runtime.jdk.unsupported.UnsafeProxy; -import org.objectweb.asm.*; +import edu.columbia.cs.psl.phosphor.runtime.mask.JdkUnsafeMasker; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - /** - * Performs patching of embedded Phosphors (for Java 9+). + * Performs patching of embedded Phosphor JAR (for Java 9+). */ public class EmbeddedPhosphorPatcher { private final boolean patchUnsafeNames; public EmbeddedPhosphorPatcher(byte[] unsafeClassFileBuffer) { - this(shouldPatchUnsafeNames(unsafeClassFileBuffer)); - } - - public EmbeddedPhosphorPatcher(boolean patchUnsafeNames) { - this.patchUnsafeNames = patchUnsafeNames; + this.patchUnsafeNames = shouldPatchUnsafeNames(unsafeClassFileBuffer); } - public byte[] patch(String name, byte[] content) throws IOException { - if (name.equals("edu/columbia/cs/psl/phosphor/Configuration.class")) { - return setConfigurationVersion(new ByteArrayInputStream(content)); - } else if (name.equals("edu/columbia/cs/psl/phosphor/runtime/RuntimeJDKInternalUnsafePropagator.class")) { - return transformUnsafePropagator( - new ByteArrayInputStream(content), "jdk/internal/misc/Unsafe", patchUnsafeNames); + public byte[] patch(String name, byte[] content) { + name = name.replace(".class", ""); + if (ConfigurationEmbeddingCV.isApplicable(name)) { + return PhosphorPatcher.apply(content, ConfigurationEmbeddingCV::new); + } else if (name.equals(Type.getInternalName(JdkUnsafeMasker.class))) { + return PhosphorPatcher.apply(content, cv -> new UnsafePatchingCV(cv, patchUnsafeNames)); + } else if (JdkUnsafeAdapterPatchingCV.isApplicable(name, patchUnsafeNames)) { + return PhosphorPatcher.apply(content, JdkUnsafeAdapterPatchingCV::new); } else { return content; } @@ -45,112 +39,4 @@ private static boolean shouldPatchUnsafeNames(byte[] in) { } return true; } - - /** - * Modify {@link Configuration} to set {@link Configuration#IS_JAVA_8} to false. - * This flag must be set correctly in order to boot the JVM. - */ - private static byte[] setConfigurationVersion(InputStream is) throws IOException { - ClassReader cr = new ClassReader(is); - ClassWriter cw = new ClassWriter(cr, 0); - ClassVisitor cv = new ClassVisitor(Configuration.ASM_VERSION, cw) { - @Override - public MethodVisitor visitMethod( - int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - if (name.equals("")) { - return new ConfigurationEmbeddingMV(mv); - } else { - return mv; - } - } - }; - cr.accept(cv, 0); - return cw.toByteArray(); - } - - public static byte[] transformUnsafePropagator(InputStream in, String unsafeInternalName, boolean patchUnsafeNames) - throws IOException { - ClassReader cr = new ClassReader(in); - ClassWriter cw = new ClassWriter(cr, 0); - ClassVisitor cv = new UnsafePatchingCV(cw, unsafeInternalName, patchUnsafeNames); - cr.accept(cv, 0); - return cw.toByteArray(); - } - - private static class UnsafePatchingCV extends ClassVisitor { - private static final String UNSAFE_PROXY_INTERNAL_NAME = Type.getInternalName(UnsafeProxy.class); - private static final String UNSAFE_PROXY_DESC = Type.getDescriptor(UnsafeProxy.class); - private final String unsafeDesc; - private final boolean patchNames; - private final String unsafeInternalName; - - public UnsafePatchingCV(ClassWriter cw, String unsafeInternalName, boolean patchNames) { - super(Configuration.ASM_VERSION, cw); - this.unsafeInternalName = unsafeInternalName; - this.unsafeDesc = "L" + unsafeInternalName + ";"; - this.patchNames = patchNames; - } - - private String patchInternalName(String name) { - return UNSAFE_PROXY_INTERNAL_NAME.equals(name) ? unsafeInternalName : name; - } - - private String patchDesc(String desc) { - return desc == null ? null : desc.replace(UNSAFE_PROXY_DESC, unsafeDesc); - } - - private String patchMethodName(String owner, String name) { - return patchNames && owner.equals(UNSAFE_PROXY_INTERNAL_NAME) ? name.replace("Reference", "Object") : name; - } - - @Override - public MethodVisitor visitMethod( - int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, patchDesc(descriptor), patchDesc(signature), exceptions); - return new MethodVisitor(api, mv) { - @Override - public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) { - for (int i = 0; i < numLocal; i++) { - if (local[i] instanceof String) { - local[i] = patchInternalName((String) local[i]); - } - } - for (int i = 0; i < numStack; i++) { - if (stack[i] instanceof String) { - stack[i] = patchInternalName((String) stack[i]); - } - } - super.visitFrame(type, numLocal, local, numStack, stack); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { - super.visitFieldInsn(opcode, patchInternalName(owner), name, patchDesc(descriptor)); - } - - @Override - public void visitMethodInsn( - int opcode, String owner, String name, String descriptor, boolean isInterface) { - super.visitMethodInsn( - opcode, - patchInternalName(owner), - patchMethodName(owner, name), - patchDesc(descriptor), - isInterface); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - super.visitTypeInsn(opcode, patchInternalName(type)); - } - - @Override - public void visitLocalVariable( - String name, String descriptor, String signature, Label start, Label end, int index) { - super.visitLocalVariable(name, patchDesc(descriptor), signature, start, end, index); - } - }; - } - } } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/InstrumentedJREProxyGenerator.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/InstrumentedJREProxyGenerator.java index b0f5ff366..8f07bdeaa 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/InstrumentedJREProxyGenerator.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/InstrumentedJREProxyGenerator.java @@ -1,48 +1,47 @@ package edu.columbia.cs.psl.phosphor.agent; - import edu.columbia.cs.psl.phosphor.Configuration; import org.objectweb.asm.*; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.util.CheckClassAdapter; -import java.io.FileInputStream; +import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; public class InstrumentedJREProxyGenerator { - static String[] CLASSES = {"edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREFieldHelper", - "edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREMethodHelper"}; + static String[] CLASSES = { + "edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREFieldHelper", + "edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREMethodHelper" + }; public static void main(String[] args) throws IOException { String outputDir = args[0]; - String version = System.getProperty("java.version"); - - String pathToUnsafePropagator = outputDir + "/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/RuntimeSunMiscUnsafePropagator.class"; - InputStream sunMiscUnsafeIn = new FileInputStream(pathToUnsafePropagator); - byte[] instrumentedUnsafe = EmbeddedPhosphorPatcher.transformUnsafePropagator(sunMiscUnsafeIn, - "sun/misc/Unsafe", false); - Files.write(Paths.get(pathToUnsafePropagator), instrumentedUnsafe); - for (String clazz : CLASSES) { String classLocation = outputDir + '/' + clazz.replace('.', '/') + ".class"; - ClassReader cr = new ClassReader(new FileInputStream(classLocation)); + ClassReader cr = new ClassReader(InstrumentUtil.readAllBytes(new File(classLocation))); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); cr.accept( new CheckClassAdapter( new ClassVisitor(Configuration.ASM_VERSION, cw) { @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + public MethodVisitor visitMethod( + int access, + String name, + String descriptor, + String signature, + String[] exceptions) { + MethodVisitor mv = + super.visitMethod(access, name, descriptor, signature, exceptions); GeneratorAdapter ga = new GeneratorAdapter(mv, access, name, descriptor); ga.visitCode(); if (name.equals("")) { } else if (name.equals("")) { ga.visitVarInsn(Opcodes.ALOAD, 0); - ga.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + ga.visitMethodInsn( + Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); } else if (name.equals("_crash")) { ga.visitInsn(Opcodes.ACONST_NULL); } else if (clazz.endsWith("FieldHelper")) { @@ -55,7 +54,9 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str ga.visitMaxs(0, 0); return ga; } - }, false), ClassReader.SKIP_CODE); + }, + false), + ClassReader.SKIP_CODE); byte[] ret = cw.toByteArray(); Files.write(Paths.get(classLocation), ret); } @@ -68,19 +69,14 @@ public static void generateFieldHelper(GeneratorAdapter ga, String name, String name = name.substring(6); } String fieldName = name.substring(3); - Type actualFieldType = null; - if (name.startsWith("get")) { ga.visitVarInsn(Opcodes.ALOAD, 0); - ga.visitFieldInsn(Opcodes.GETFIELD, fieldOwner, fieldName, (actualFieldType != null ? actualFieldType.getDescriptor() : returnType.getDescriptor())); + ga.visitFieldInsn(Opcodes.GETFIELD, fieldOwner, fieldName, returnType.getDescriptor()); } else { Type argType = Type.getArgumentTypes(descriptor)[1]; ga.visitVarInsn(Opcodes.ALOAD, 0); ga.visitVarInsn(argType.getOpcode(Opcodes.ILOAD), 1); - if (actualFieldType != null) { - ga.visitTypeInsn(Opcodes.CHECKCAST, actualFieldType.getInternalName()); - } - ga.visitFieldInsn(Opcodes.PUTFIELD, fieldOwner, fieldName, (actualFieldType != null ? actualFieldType.getDescriptor() : argType.getDescriptor())); + ga.visitFieldInsn(Opcodes.PUTFIELD, fieldOwner, fieldName, argType.getDescriptor()); } } @@ -106,7 +102,7 @@ public static void generateMethodHelper(GeneratorAdapter ga, String name, String if (isInstanceMethod) { descriptorToInvoke = "(" + descriptor.substring(descriptor.indexOf(';') + 1); try { - Class c = Class.forName(owner.replace('/', '.')); + Class c = Class.forName(owner.replace('/', '.')); if (c.isInterface()) { isIface = true; opcode = Opcodes.INVOKEVIRTUAL; @@ -115,12 +111,11 @@ public static void generateMethodHelper(GeneratorAdapter ga, String name, String e.printStackTrace(); } } - Type[] args = Type.getArgumentTypes(descriptor); int argIdx = 0; - for (int i = 0; i < args.length; i++) { - ga.visitVarInsn(args[i].getOpcode(Opcodes.ILOAD), argIdx); - argIdx += args[i].getSize(); + for (Type arg : args) { + ga.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), argIdx); + argIdx += arg.getSize(); } ga.visitMethodInsn(opcode, owner, methodName, descriptorToInvoke, isIface); } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/JdkUnsafeAdapterPatchingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/JdkUnsafeAdapterPatchingCV.java new file mode 100644 index 000000000..ec66f94a9 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/JdkUnsafeAdapterPatchingCV.java @@ -0,0 +1,34 @@ +package edu.columbia.cs.psl.phosphor.agent; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.runtime.mask.JdkUnsafeAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +public class JdkUnsafeAdapterPatchingCV extends ClassVisitor { + private final String UNSAFE_INTERNAL_NAME = "jdk/internal/misc/Unsafe"; + + public JdkUnsafeAdapterPatchingCV(ClassVisitor cv) { + super(Configuration.ASM_VERSION, cv); + } + + public static boolean isApplicable(String className, boolean patchUnsafeNames) { + return Type.getInternalName(JdkUnsafeAdapter.class).equals(className) && !patchUnsafeNames; + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + return new MethodVisitor(api, mv) { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + if (UNSAFE_INTERNAL_NAME.equals(owner)) { + name = name.replace("Object", "Reference"); + } + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + }; + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/MaskRegistryPatchingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/MaskRegistryPatchingCV.java new file mode 100644 index 000000000..19f5574e2 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/MaskRegistryPatchingCV.java @@ -0,0 +1,91 @@ +package edu.columbia.cs.psl.phosphor.agent; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.instrumenter.MethodRecordImpl; +import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; +import edu.columbia.cs.psl.phosphor.mask.MaskRegistry; +import edu.columbia.cs.psl.phosphor.runtime.mask.Mask; +import edu.columbia.cs.psl.phosphor.runtime.mask.SunUnsafeMasker; +import edu.columbia.cs.psl.phosphor.struct.harmony.util.HashMap; +import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.lang.reflect.Method; + +public class MaskRegistryPatchingCV extends ClassVisitor { + private static final String MASK_REGISTRY_INTERNAL_NAME = Type.getInternalName(MaskRegistry.class); + private static final String TARGET_METHOD_NAME = "initialize"; + private static final Class[] MASKERS = new Class[] {SunUnsafeMasker.class}; + + public MaskRegistryPatchingCV(ClassVisitor cv) { + super(Configuration.ASM_VERSION, cv); + } + + public static Map readMasks() { + Map map = new HashMap<>(); + for (Class clazz : MASKERS) { + for (Method method : clazz.getDeclaredMethods()) { + for (Mask mask : method.getAnnotationsByType(Mask.class)) { + MethodRecordImpl record = new MethodRecordImpl( + Opcodes.INVOKEVIRTUAL, + Type.getInternalName(clazz), + method.getName(), + Type.getMethodDescriptor(method), + false); + String key = createKey(record, mask); + map.put(key, new MaskRegistry.MaskInfo(record)); + } + } + } + return map; + } + + private static String createKey(MethodRecordImpl record, Mask mask) { + String descriptor = mask.isStatic() ? record.getDescriptor() : removeFirstParameter(record.getDescriptor()); + return MaskRegistry.getKey(mask.owner(), record.getName(), descriptor); + } + + private static String removeFirstParameter(String descriptor) { + return '(' + descriptor.substring(descriptor.indexOf(';') + 1); + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + return !name.equals(TARGET_METHOD_NAME) ? mv : new MaskRegistryPatchingMV(mv); + } + + public static boolean isApplicable(String className) { + return className.equals(MASK_REGISTRY_INTERNAL_NAME); + } + + private static class MaskRegistryPatchingMV extends MethodVisitor { + private final MethodVisitor target; + + public MaskRegistryPatchingMV(MethodVisitor mv) { + super(Configuration.ASM_VERSION, null); + target = mv; + } + + @Override + public void visitCode() { + target.visitCode(); + Map masks = readMasks(); + for (String key : masks.keySet()) { + MaskRegistry.MaskInfo mask = masks.get(key); + target.visitLdcInsn(key); + target.visitLdcInsn(mask.getRecord().getOwner()); + target.visitLdcInsn(mask.getRecord().getName()); + target.visitLdcInsn(mask.getRecord().getDescriptor()); + TaintMethodRecord.ADD_MASK.delegateVisit(target); + } + target.visitInsn(Opcodes.RETURN); + target.visitMaxs(-1, -1); + target.visitEnd(); + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/PhosphorPatcher.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/PhosphorPatcher.java index eeb834e50..49c728e38 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/PhosphorPatcher.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/PhosphorPatcher.java @@ -1,8 +1,13 @@ package edu.columbia.cs.psl.phosphor.agent; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; + import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.function.Function; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -28,13 +33,6 @@ public static void main(String[] args) throws IOException { } } - private static byte[] patch(String name, byte[] classFileBuffer) { - if (AsmPatcher.isApplicable(name)) { - return AsmPatcher.patch(classFileBuffer); - } - return classFileBuffer; - } - private static void writeEntry(ZipOutputStream zos, ZipEntry entry, byte[] content) throws IOException { ZipEntry outEntry = new ZipEntry(entry.getName()); outEntry.setMethod(entry.getMethod()); @@ -50,4 +48,24 @@ private static void writeEntry(ZipOutputStream zos, ZipEntry entry, byte[] conte zos.write(content); zos.closeEntry(); } + + private static byte[] patch(String name, byte[] classFileBuffer) { + name = name.replace(".class", ""); + if (AsmPatchingCV.isApplicable(name)) { + return apply(classFileBuffer, AsmPatchingCV::new); + } else if (MaskRegistryPatchingCV.isApplicable(name)) { + return apply(classFileBuffer, MaskRegistryPatchingCV::new); + } else if (UnsafeAdapterPatchingCV.isApplicable(name)) { + return apply(classFileBuffer, UnsafeAdapterPatchingCV::new); + } + return classFileBuffer; + } + + public static byte[] apply(byte[] classFileBuffer, Function visitorFactory) { + ClassReader cr = new ClassReader(classFileBuffer); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); + ClassVisitor cv = visitorFactory.apply(cw); + cr.accept(cv, ClassReader.EXPAND_FRAMES); + return cw.toByteArray(); + } } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/UnsafeAdapterPatchingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/UnsafeAdapterPatchingCV.java new file mode 100644 index 000000000..764b9a359 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/UnsafeAdapterPatchingCV.java @@ -0,0 +1,49 @@ +package edu.columbia.cs.psl.phosphor.agent; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.runtime.mask.JdkUnsafeAdapter; +import edu.columbia.cs.psl.phosphor.runtime.mask.SunUnsafeAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.util.regex.Pattern; + +public class UnsafeAdapterPatchingCV extends ClassVisitor { + private String className; + + public UnsafeAdapterPatchingCV(ClassVisitor cv) { + super(Configuration.ASM_VERSION, cv); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + className = name; + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + return new MethodVisitor(api, mv) { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + if (owner.equals(className) && opcode == Opcodes.INVOKESTATIC) { + Type[] args = Type.getArgumentTypes(descriptor); + owner = args[0].getInternalName(); + descriptor = descriptor.replaceFirst(Pattern.quote(args[0].getDescriptor()), ""); + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, false); + } else { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + } + }; + } + + public static boolean isApplicable(String className) { + return Type.getInternalName(SunUnsafeAdapter.class).equals(className) + || Type.getInternalName(JdkUnsafeAdapter.class).equals(className); + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/UnsafePatchingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/UnsafePatchingCV.java new file mode 100644 index 000000000..e4ad8e622 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/UnsafePatchingCV.java @@ -0,0 +1,81 @@ +package edu.columbia.cs.psl.phosphor.agent; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.runtime.mask.UnsafeProxy; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +class UnsafePatchingCV extends ClassVisitor { + private static final String UNSAFE_PROXY_INTERNAL_NAME = Type.getInternalName(UnsafeProxy.class); + private static final String UNSAFE_PROXY_DESC = Type.getDescriptor(UnsafeProxy.class); + private final boolean patchNames; + private final String UNSAFE_INTERNAL_NAME = "jdk/internal/misc/Unsafe"; + + public UnsafePatchingCV(ClassVisitor cv, boolean patchNames) { + super(Configuration.ASM_VERSION, cv); + this.patchNames = patchNames; + } + + private String patchInternalName(String name) { + return UNSAFE_PROXY_INTERNAL_NAME.equals(name) ? UNSAFE_INTERNAL_NAME : name; + } + + private String patchDesc(String desc) { + String UNSAFE_DESCRIPTOR = "L" + UNSAFE_INTERNAL_NAME + ";"; + return desc == null ? null : desc.replace(UNSAFE_PROXY_DESC, UNSAFE_DESCRIPTOR); + } + + private String patchMethodName(String owner, String name) { + return patchNames && owner.equals(UNSAFE_PROXY_INTERNAL_NAME) ? name.replace("Reference", "Object") : name; + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, patchDesc(descriptor), patchDesc(signature), exceptions); + return new MethodVisitor(api, mv) { + @Override + public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) { + for (int i = 0; i < numLocal; i++) { + if (local[i] instanceof String) { + local[i] = patchInternalName((String) local[i]); + } + } + for (int i = 0; i < numStack; i++) { + if (stack[i] instanceof String) { + stack[i] = patchInternalName((String) stack[i]); + } + } + super.visitFrame(type, numLocal, local, numStack, stack); + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + super.visitFieldInsn(opcode, patchInternalName(owner), name, patchDesc(descriptor)); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + super.visitMethodInsn( + opcode, + patchInternalName(owner), + patchMethodName(owner, name), + patchDesc(descriptor), + isInterface); + } + + @Override + public void visitTypeInsn(int opcode, String type) { + super.visitTypeInsn(opcode, patchInternalName(type)); + } + + @Override + public void visitLocalVariable( + String name, String descriptor, String signature, Label start, Label end, int index) { + super.visitLocalVariable(name, patchDesc(descriptor), signature, start, end, index); + } + }; + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ControlMethodRecord.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ControlMethodRecord.java index 7c066930e..4906671be 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ControlMethodRecord.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ControlMethodRecord.java @@ -93,11 +93,4 @@ public boolean isInterface() { return isInterface; } - /** - * {@inheritDoc} - */ - @Override - public Class getReturnType() { - return returnType; - } } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecord.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecord.java index e4fdf6771..097fa64bf 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecord.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecord.java @@ -33,11 +33,6 @@ public interface MethodRecord { */ boolean isInterface(); - /** - * @return this method's return type - */ - Class getReturnType(); - /** * Tells the specified method visitor to visit a method instruction for this method. * diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecordImpl.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecordImpl.java new file mode 100644 index 000000000..e826c977b --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecordImpl.java @@ -0,0 +1,57 @@ +package edu.columbia.cs.psl.phosphor.instrumenter; + +public final class MethodRecordImpl implements MethodRecord { + private final int opcode; + private final String owner; + private final String name; + private final String descriptor; + private final boolean isInterface; + + public MethodRecordImpl(int opcode, String owner, String name, String descriptor, boolean isInterface) { + this.opcode = opcode; + this.owner = owner; + this.name = name; + this.isInterface = isInterface; + this.descriptor = descriptor; + } + + /** + * {@inheritDoc} + */ + @Override + public int getOpcode() { + return opcode; + } + + /** + * {@inheritDoc} + */ + @Override + public String getOwner() { + return owner; + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + public String getDescriptor() { + return descriptor; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isInterface() { + return isInterface; + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/ReflectionHidingMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/ReflectionHidingMV.java deleted file mode 100644 index 484d244de..000000000 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/ReflectionHidingMV.java +++ /dev/null @@ -1,640 +0,0 @@ -package edu.columbia.cs.psl.phosphor.instrumenter; - -import edu.columbia.cs.psl.phosphor.Configuration; -import edu.columbia.cs.psl.phosphor.Phosphor; -import edu.columbia.cs.psl.phosphor.runtime.*; -import edu.columbia.cs.psl.phosphor.runtime.jdk.unsupported.RuntimeSunMiscUnsafePropagator; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.*; -import static edu.columbia.cs.psl.phosphor.instrumenter.TaintTrackingClassVisitor.CONTROL_STACK_DESC; - -public class ReflectionHidingMV extends MethodVisitor implements Opcodes { - - private final String className; - private final String methodName; - private final boolean disable; - private final boolean isEnumValueOf; - private final boolean patchAnonymousClasses; - private LocalVariableManager lvs; - - public ReflectionHidingMV(MethodVisitor mv, String className, String name, boolean isEnum) { - super(Configuration.ASM_VERSION, mv); - this.className = className; - this.methodName = name; - this.disable = shouldDisable(className, name); - this.patchAnonymousClasses = className.equals("java/lang/invoke/InnerClassLambdaMetafactory") || className.equals("sun/reflect/ClassDefiner"); - this.isEnumValueOf = isEnum && name.equals("valueOf"); - } - - public void setLvs(LocalVariableManager lvs) { - this.lvs = lvs; - } - - private int[] storeToLocals(int n) { - int[] ret = new int[n]; - for (int i = 0; i < n; i++) { - ret[i] = lvs.getTmpLV(); - super.visitVarInsn(ASTORE, ret[i]); - } - return ret; - } - - private void loadAndFree(int[] r) { - for (int i = r.length - 1; i >= 0; i--) { - super.visitVarInsn(ALOAD, r[i]); - lvs.freeTmpLV(r[i]); - } - } - - private void maskGetter(TaintMethodRecord mask, Type[] args) { - int[] tmps = storeToLocals(args.length); - visit(mask); - loadAndFree(tmps); - } - - /* Returns whether a method instruction with the specified information is for a method added to Unsafe by Phosphor - * that retrieves the value of a field of a Java heap object. */ - private boolean isUnsafeFieldGetter(int opcode, String owner, String name, Type[] args, String nameWithoutSuffix) { - if (opcode != INVOKEVIRTUAL || !Phosphor.isUnsafeClass(owner)) { - return false; - } else { - if (args.length < 1 || !args[0].equals(Type.getType(Object.class))) { - return false; - } - if (Configuration.IS_JAVA_8) { - switch (nameWithoutSuffix) { - case "getBoolean": - case "getByte": - case "getChar": - case "getDouble": - case "getFloat": - case "getInt": - case "getLong": - case "getObject": - case "getShort": - case "getBooleanVolatile": - case "getByteVolatile": - case "getCharVolatile": - case "getDoubleVolatile": - case "getFloatVolatile": - case "getLongVolatile": - case "getIntVolatile": - case "getObjectVolatile": - case "getShortVolatile": - return true; - default: - return false; - } - } - return false; - } - } - - /* Returns whether a method instruction with the specified information is for a method added to Unsafe by Phosphor - * that sets the value of a field of a Java heap object. */ - private boolean isUnsafeFieldSetter(int opcode, String owner, String name, Type[] args, String nameWithoutSuffix) { - if (opcode != INVOKEVIRTUAL || !Phosphor.isUnsafeClass(owner)) { - return false; - } else { - if (args.length < 1 || !args[0].equals(Type.getType(Object.class))) { - return false; - } - if (Configuration.IS_JAVA_8) { - switch (nameWithoutSuffix) { - case "putBoolean": - case "putByte": - case "putChar": - case "putDouble": - case "putFloat": - case "putInt": - case "putLong": - case "putObject": - case "putShort": - case "putBooleanVolatile": - case "putByteVolatile": - case "putCharVolatile": - case "putDoubleVolatile": - case "putFloatVolatile": - case "putIntVolatile": - case "putLongVolatile": - case "putObjectVolatile": - case "putShortVolatile": - case "putOrderedInt": - case "putOrderedLong": - case "putOrderedObject": - return true; - default: - return false; - } - } - return false; - } - } - - /* Returns whether a method instruction with the specified information is for a method added to Unsafe by Phosphor - * for a compareAndSwap method. */ - private boolean isUnsafeCAS(String owner, String name, String nameWithoutSuffix) { - if (!Phosphor.isUnsafeClass(owner)) { - return false; - } else { - if (Configuration.IS_JAVA_8) { - return "compareAndSwapInt".equals(nameWithoutSuffix) - || "compareAndSwapLong".equals(nameWithoutSuffix) - || "compareAndSwapObject".equals(nameWithoutSuffix); - } - return false; - } - } - - private boolean isUnsafeIntrinsic(String owner, String name, String desc) { - if(Configuration.IS_JAVA_8){ - return false; //These intrinsics are only for 9+ - } - if (!Phosphor.isUnsafeClass(owner)) { - return false; - } - // Java 11 uses get/putObject instead of Reference - name = name.replace("Object", "Reference"); - switch (desc) { - case "(Ljava/lang/Object;JLjava/lang/Object;)V": - switch (name) { - case "putReference": - case "putReferenceVolatile": - case "putReferenceOpaque": - case "putReferenceRelease": - return true; - } - case "(Ljava/lang/Object;JZ)V": - switch (name) { - case "putBoolean": - case "putBooleanVolatile": - case "putBooleanOpaque": - case "putBooleanRelease": - return true; - } - case "(Ljava/lang/Object;J)B": - switch (name) { - case "getByte": - case "getByteVolatile": - case "getByteOpaque": - case "getByteAcquire": - return true; - } - case "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z": - switch (name) { - case "compareAndSetReference": - case "weakCompareAndSetReferencePlain": - case "weakCompareAndSetReferenceAcquire": - case "weakCompareAndSetReferenceRelease": - case "weakCompareAndSetReference": - return true; - } - case "(Ljava/lang/Object;JJJ)J": - switch (name) { - case "compareAndExchangeLong": - case "compareAndExchangeLongAcquire": - case "compareAndExchangeLongRelease": - return true; - } - case "(Ljava/lang/Object;JB)B": - switch (name) { - case "getAndAddByte": - case "getAndSetByte": - return true; - } - case "(Ljava/lang/Object;JJJ)Z": - switch (name) { - case "compareAndSetLong": - case "weakCompareAndSetLongPlain": - case "weakCompareAndSetLongAcquire": - case "weakCompareAndSetLongRelease": - case "weakCompareAndSetLong": - return true; - } - case "(Ljava/lang/Object;JBB)Z": - switch (name) { - case "compareAndSetByte": - case "weakCompareAndSetBytePlain": - case "weakCompareAndSetByteAcquire": - case "weakCompareAndSetByteRelease": - case "weakCompareAndSetByte": - return true; - } - case "(Ljava/lang/Object;JI)I": - switch (name) { - case "getAndAddInt": - case "getAndSetInt": - return true; - } - case "(Ljava/lang/Object;JSS)S": - switch (name) { - case "compareAndExchangeShort": - case "compareAndExchangeShortAcquire": - case "compareAndExchangeShortRelease": - return true; - } - case "(Ljava/lang/Object;JSS)Z": - switch (name) { - case "compareAndSetShort": - case "weakCompareAndSetShortPlain": - case "weakCompareAndSetShortAcquire": - case "weakCompareAndSetShortRelease": - case "weakCompareAndSetShort": - return true; - } - case "(Ljava/lang/Object;JJ)J": - switch (name) { - case "getAndAddLong": - case "getAndSetLong": - return true; - } - case "(Ljava/lang/Object;J)Ljava/lang/Object;": - switch (name) { - case "getReference": - case "getReferenceVolatile": - case "getReferenceOpaque": - case "getReferenceAcquire": - return true; - } - case "(Ljava/lang/Object;JD)V": - switch (name) { - case "putDouble": - case "putDoubleVolatile": - case "putDoubleOpaque": - case "putDoubleRelease": - return true; - } - case "(Ljava/lang/Object;JII)I": - switch (name) { - case "compareAndExchangeInt": - case "compareAndExchangeIntAcquire": - case "compareAndExchangeIntRelease": - return true; - } - case "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;": - switch (name) { - case "getAndSetReference": - return true; - } - case "(Ljava/lang/Object;JC)V": - switch (name) { - case "putChar": - case "putCharVolatile": - case "putCharOpaque": - case "putCharRelease": - case "putCharUnaligned": - return true; - } - case "(Ljava/lang/Object;J)Z": - switch (name) { - case "getBoolean": - case "getBooleanVolatile": - case "getBooleanOpaque": - case "getBooleanAcquire": - return true; - } - case "(Ljava/lang/Object;JB)V": - switch (name) { - case "putByte": - case "putByteVolatile": - case "putByteOpaque": - case "putByteRelease": - return true; - } - case "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;": - switch (name) { - case "compareAndExchangeReference": - case "compareAndExchangeReferenceAcquire": - case "compareAndExchangeReferenceRelease": - return true; - } - case "(Ljava/lang/Object;J)S": - switch (name) { - case "getShort": - case "getShortVolatile": - case "getShortOpaque": - case "getShortAcquire": - case "getShortUnaligned": - return true; - } - case "(Ljava/lang/Object;JF)V": - switch (name) { - case "putFloat": - case "putFloatVolatile": - case "putFloatOpaque": - case "putFloatRelease": - return true; - } - case "(Ljava/lang/Object;JJ)V": - switch (name) { - case "putLong": - case "putLongVolatile": - case "putLongOpaque": - case "putLongRelease": - case "putLongUnaligned": - return true; - } - case "(Ljava/lang/Object;JI)V": - switch (name) { - case "putInt": - case "putIntVolatile": - case "putIntOpaque": - case "putIntRelease": - case "putIntUnaligned": - return true; - } - case "(Ljava/lang/Object;JBB)B": - switch (name) { - case "compareAndExchangeByte": - case "compareAndExchangeByteAcquire": - case "compareAndExchangeByteRelease": - return true; - } - case "(Ljava/lang/Object;JS)S": - switch (name) { - case "getAndAddShort": - case "getAndSetShort": - return true; - } - case "(Ljava/lang/Object;JS)V": - switch (name) { - case "putShort": - case "putShortVolatile": - case "putShortOpaque": - case "putShortRelease": - case "putShortUnaligned": - return true; - } - case "(Ljava/lang/Object;JII)Z": - switch (name) { - case "compareAndSetInt": - case "weakCompareAndSetIntPlain": - case "weakCompareAndSetIntAcquire": - case "weakCompareAndSetIntRelease": - case "weakCompareAndSetInt": - return true; - } - case "(Ljava/lang/Object;J)J": - switch (name) { - case "getLong": - case "getLongVolatile": - case "getLongOpaque": - case "getLongAcquire": - case "getLongUnaligned": - return true; - } - case "(Ljava/lang/Object;J)I": - switch (name) { - case "getInt": - case "getIntVolatile": - case "getIntOpaque": - case "getIntAcquire": - case "getIntUnaligned": - return true; - } - case "(Ljava/lang/Object;J)D": - switch (name) { - case "getDouble": - case "getDoubleVolatile": - case "getDoubleOpaque": - case "getDoubleAcquire": - return true; - } - case "(Ljava/lang/Object;J)C": - switch (name) { - case "getChar": - case "getCharVolatile": - case "getCharOpaque": - case "getCharAcquire": - case "getCharUnaligned": - return true; - } - case "(Ljava/lang/Object;J)F": - switch (name) { - case "getFloat": - case "getFloatVolatile": - case "getFloatOpaque": - case "getFloatAcquire": - return true; - } - } - return false; - } - - private boolean isUnsafeCopyMemory(String owner, String name, String nameWithoutSuffix) { - if (Phosphor.isUnsafeClass(owner)) { - switch (nameWithoutSuffix) { - case "copyMemory": - case "copySwapMemory": - return true; - } - - } - return false; - } - - @Override - public void visitCode() { - super.visitCode(); - if (this.className.equals("java/lang/invoke/MethodHandles$Lookup") && this.methodName.startsWith("defineHiddenClass")) { - super.visitVarInsn(ALOAD, 1); - INSTRUMENT_CLASS_BYTES.delegateVisit(mv); - super.visitVarInsn(ASTORE, 1); - } - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) { - Type[] args = Type.getArgumentTypes(desc); - String nameWithoutSuffix = name; - String descWithoutStackFrame = desc.replace(PhosphorStackFrame.DESCRIPTOR, ""); - if ((disable || className.equals("java/io/ObjectOutputStream") || className.equals("java/io/ObjectInputStream")) && owner.equals("java/lang/Class") && !owner.equals(className) && name.startsWith("isInstance")) { - // Even if we are ignoring other hiding here, we definitely need to do this. - visit(IS_INSTANCE); - } else if (disable) { - if (this.methodName.startsWith("setObjFieldValues") && owner.equals("sun/misc/Unsafe") && (name.startsWith("putObject") || name.startsWith("compareAndSwapObject"))) { - owner = getRuntimeUnsafePropogatorClassName(); - super.visitMethodInsn(INVOKESTATIC, owner, name, "(Lsun/misc/Unsafe;" + desc.substring(1), isInterface); - } else if (this.methodName.startsWith("getObjFieldValues") && owner.equals("sun/misc/Unsafe") && name.startsWith("getObject")) { - owner = getRuntimeUnsafePropogatorClassName(); - super.visitMethodInsn(INVOKESTATIC, owner, name, "(Lsun/misc/Unsafe;" + desc.substring(1), isInterface); - } else if ((this.methodName.startsWith("getPrimFieldValues") || this.methodName.startsWith("setPrimFieldValues")) && owner.equals("sun/misc/Unsafe") && (name.startsWith("put") || name.startsWith("get"))) { - //name = name + "$$NOUNBOX"; - //TODO - super.visitMethodInsn(opcode, owner, name, desc, isInterface); - } else { - super.visitMethodInsn(opcode, owner, name, desc, isInterface); - } - } else { - if (patchAnonymousClasses && name.equals("defineAnonymousClass") && Phosphor.isUnsafeClass(owner) && descWithoutStackFrame.equals("(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;")) { - super.visitInsn(POP); - super.visitInsn(SWAP); - INSTRUMENT_CLASS_BYTES_ANONYMOUS.delegateVisit(mv); - super.visitInsn(SWAP); - desc = descWithoutStackFrame; // Go directly to the native call - } else if (patchAnonymousClasses && name.equals("defineClass") - && Configuration.IS_JAVA_8 && "sun/misc/Unsafe".equals(owner) - && descWithoutStackFrame.equals("(Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;")) { - desc = "(L" + owner + ";" + desc.substring(1); - super.visitMethodInsn(Opcodes.INVOKESTATIC, getRuntimeUnsafePropogatorClassName(), name, desc, false); - return; - } - /* - * Fix for #188 - if we are in a wrapped method, and called by the wrapper, we need to get the caller class - * of the wrapper, not of this stack frame - */ - if(owner.equals("jdk/internal/reflect/Reflection") && name.equals("getCallerClass")){ - int phosphorStackFrame = lvs.getLocalVariableAdder().getIndexOfPhosphorStackData(); - super.visitVarInsn(ALOAD, phosphorStackFrame); - super.visitMethodInsn(opcode, owner, name, desc, isInterface); - super.visitLdcInsn(Type.getObjectType(className)); - GET_CALLER_CLASS_WRAPPER.delegateVisit(mv); - return; - } - if (owner.equals("java/lang/reflect/Array") && !owner.equals(className)) { - owner = Type.getInternalName(ArrayReflectionMasker.class); - } - if (name.equals("allocateUninitializedArray") && Phosphor.isUnsafeClass(owner)) { - desc = "(L" + owner + ";" + desc.substring(1); - super.visitMethodInsn(Opcodes.INVOKESTATIC, getRuntimeUnsafePropogatorClassName(), name, desc, false); - return; - } else if (isUnsafeIntrinsic(owner, name, descWithoutStackFrame) || isUnsafeFieldGetter(opcode, owner, name, args, nameWithoutSuffix)) { - if (Configuration.IMPLICIT_TRACKING || Configuration.IMPLICIT_HEADERS_NO_TRACKING) { - desc = desc.replace(CONTROL_STACK_DESC, ""); - //in control tracking mode, pop the control stack off of the stack to reuse the existing method - //but first, pop the null that's there for the erased return type. - if (isUnsafeReferenceFieldGetter(nameWithoutSuffix)) { - super.visitInsn(POP); - } - super.visitInsn(SWAP); - super.visitInsn(POP); - if (isUnsafeReferenceFieldGetter(nameWithoutSuffix)) { - super.visitInsn(ACONST_NULL); - } - } - desc = "(L" + owner + ";" + desc.substring(1); - if (isUnsafeIntrinsic(owner, name, descWithoutStackFrame)) { - // Java 11 uses get/putObject instead of Reference - name = name.replace("Object", "Reference"); - } - super.visitMethodInsn(Opcodes.INVOKESTATIC, getRuntimeUnsafePropogatorClassName(), name, desc, false); - return; - } else if (isUnsafeFieldSetter(opcode, owner, name, args, nameWithoutSuffix)) { - if (Configuration.IMPLICIT_TRACKING || Configuration.IMPLICIT_HEADERS_NO_TRACKING) { - desc = desc.replace(CONTROL_STACK_DESC, ""); - super.visitInsn(POP); - } - desc = "(L" + owner + ";" + desc.substring(1); - super.visitMethodInsn(Opcodes.INVOKESTATIC, getRuntimeUnsafePropogatorClassName(), name, desc, false); - return; - } else if (isUnsafeCAS(owner, name, nameWithoutSuffix) || isUnsafeCopyMemory(owner, name, nameWithoutSuffix)) { - if (Configuration.IMPLICIT_TRACKING || Configuration.IMPLICIT_HEADERS_NO_TRACKING) { - desc = desc.replace(CONTROL_STACK_DESC, ""); - super.visitInsn(SWAP); - super.visitInsn(POP); - } - desc = "(L" + owner + ";" + desc.substring(1); - owner = getRuntimeUnsafePropogatorClassName(); - opcode = INVOKESTATIC; - super.visitMethodInsn(opcode, owner, name, desc, isInterface); - return; - } else if (owner.equals(Type.getInternalName(Character.class)) && (name.equals("codePointAt") - || name.equals("toChars") || name.equals("codePointBefore") || name.equals("reverseBytes") - || name.equals("toLowerCase") || name.equals("toTitleCase") || name.equals("toUpperCase"))) { - owner = Type.getInternalName(CharacterUtils.class); - desc = lvs.patchDescToAcceptPhosphorStackFrameAndPushIt(desc, mv); - } else if ((owner.equals("sun/reflect/NativeMethodAccessorImpl") || owner.equals("jdk/internal/reflect/NativeMethodAccessorImpl")) && name.equals("invoke0")) { - //Stack: Method Receiver Args StackData - PREPARE_FOR_CALL_REFLECTIVE.delegateVisit(this); - String methodTupleInternalName = Type.getInternalName(ReflectionMasker.MethodInvocationTuple.class); - mv.visitInsn(DUP); - mv.visitFieldInsn(GETFIELD, methodTupleInternalName, "method", Type.getType(Method.class).getDescriptor()); - mv.visitInsn(SWAP); - mv.visitInsn(DUP); - mv.visitFieldInsn(GETFIELD, methodTupleInternalName, "receiver", "Ljava/lang/Object;"); - mv.visitInsn(SWAP); - mv.visitFieldInsn(GETFIELD, methodTupleInternalName, "args", "[Ljava/lang/Object;"); - mv.visitVarInsn(ALOAD, lvs.getLocalVariableAdder().getIndexOfPhosphorStackData()); - } else if ((owner.equals("sun/reflect/NativeConstructorAccessorImpl") || owner.equals("jdk/internal/reflect/NativeConstructorAccessorImpl")) && name.equals("newInstance0")) { - PREPARE_FOR_CALL_REFLECTIVE_CONSTRUCTOR.delegateVisit(this); - String constructorInvocationPairInternalName = Type.getInternalName(ReflectionMasker.ConstructorInvocationPair.class); - mv.visitInsn(DUP); - mv.visitFieldInsn(GETFIELD, constructorInvocationPairInternalName, "constructor", Type.getDescriptor(Constructor.class)); - mv.visitInsn(SWAP); - mv.visitFieldInsn(GETFIELD, constructorInvocationPairInternalName, "args", "[Ljava/lang/Object;"); - mv.visitVarInsn(ALOAD, lvs.getLocalVariableAdder().getIndexOfPhosphorStackData()); - } - super.visitMethodInsn(opcode, owner, name, desc, isInterface); - if (owner.equals("java/lang/Class") && nameWithoutSuffix.endsWith("Fields") && !className.equals("java/lang/Class")) { - if (!Configuration.WITHOUT_FIELD_HIDING) { - visit(REMOVE_TAINTED_FIELDS); - } - } else if (owner.equals("java/lang/Class") && nameWithoutSuffix.endsWith("Methods") && !className.equals(owner) && descWithoutStackFrame.equals("()" + Type.getDescriptor(Method[].class))) { - visit(REMOVE_TAINTED_METHODS); - } else if (owner.equals("java/lang/Class") && nameWithoutSuffix.endsWith("Constructors") && !className.equals(owner) && descWithoutStackFrame.equals("()" + Type.getDescriptor(Constructor[].class))) { - visit(REMOVE_TAINTED_CONSTRUCTORS); - } else if (owner.equals("java/lang/Class") && name.equals("getInterfaces")) { - visit(REMOVE_TAINTED_INTERFACES); - } else if (owner.equals("java/lang/Throwable") && (name.equals("getOurStackTrace") || name.equals("getStackTrace")) && descWithoutStackFrame.equals("()" + Type.getDescriptor(StackTraceElement[].class))) { - //if (className.equals("java/lang/Throwable")) { - // super.visitVarInsn(ALOAD, 0); - // super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - //} else { - // super.visitLdcInsn(Type.getObjectType(className)); - //} - //visit(REMOVE_EXTRA_STACK_TRACE_ELEMENTS); - } else if (owner.equals("java/lang/reflect/Method") && name.equals("invoke")) { - mv.visitVarInsn(ALOAD, lvs.getLocalVariableAdder().getIndexOfPhosphorStackData()); - UNWRAP_RETURN.delegateVisit(mv); - } - } - } - - private String controlTrackDescOrNone() { - return (Configuration.IMPLICIT_TRACKING || Configuration.IMPLICIT_HEADERS_NO_TRACKING ? CONTROL_STACK_DESC : ""); - } - - /** - * Visits a method instruction for the specified method. - * - * @param method the method to be visited - */ - private void visit(TaintMethodRecord method) { - super.visitMethodInsn(method.getOpcode(), method.getOwner(), method.getName(), method.getDescriptor(), method.isInterface()); - } - - private static boolean shouldDisable(String className, String methodName) { - if (className.equals("org/codehaus/groovy/vmplugin/v5/Java5") && methodName.equals("makeInterfaceTypes")) { - return true; - } else { - if (className.equals("jdk/internal/reflect/ReflectionFactory") || className.equals("java/lang/reflect/ReflectAccess")) { - //Java >= 9 - //TODO keep? - return true; - } - return Configuration.TAINT_THROUGH_SERIALIZATION && !methodName.equals("getDeclaredSerialFields$$PHOSPHORTAGGED") && - (className.startsWith("java/io/ObjectStreamClass") || className.equals("java/io/ObjectStreamField")); - } - } - - private static String getRuntimeUnsafePropogatorClassName() { - if (Configuration.IS_JAVA_8) { - return Type.getInternalName(RuntimeSunMiscUnsafePropagator.class); - } - return Type.getInternalName(RuntimeJDKInternalUnsafePropagator.class); - } - - private static boolean isUnsafeReferenceFieldGetter(String methodName) { - if (Configuration.IS_JAVA_8) { - return "getObject".equals(methodName) || "getObjectVolatile".equals(methodName); - } - // TODO Java 11? - return "getReference".equals(methodName) || "getReferenceVolatile".equals(methodName); - } -} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintMethodRecord.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintMethodRecord.java index c9670a594..784a83969 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintMethodRecord.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintMethodRecord.java @@ -3,6 +3,7 @@ import edu.columbia.cs.psl.phosphor.Phosphor; import edu.columbia.cs.psl.phosphor.TaintUtils; import edu.columbia.cs.psl.phosphor.control.ControlFlowStack; +import edu.columbia.cs.psl.phosphor.mask.MaskRegistry; import edu.columbia.cs.psl.phosphor.runtime.*; import edu.columbia.cs.psl.phosphor.struct.*; import edu.columbia.cs.psl.phosphor.struct.harmony.util.Set; @@ -124,14 +125,16 @@ public enum TaintMethodRecord implements MethodRecord { // TaggedReferenceArray TAINTED_REFERENCE_ARRAY_UNWRAP(INVOKESTATIC, TaggedReferenceArray.class, "unwrap", Object.class, false, Object.class), // Set - SET_ADD(INVOKEVIRTUAL, Set.class, "add", boolean.class, true, Object.class); + SET_ADD(INVOKEVIRTUAL, Set.class, "add", boolean.class, true, Object.class), + // MaskRegistry + ADD_MASK(INVOKESTATIC, MaskRegistry.class, "addMask", void.class, false, String.class, String.class, + String.class, String.class); private final int opcode; private final String owner; private final String name; private final String descriptor; private final boolean isInterface; - private final Class returnType; /** * Constructs a new method. @@ -149,7 +152,6 @@ public enum TaintMethodRecord implements MethodRecord { this.name = name; this.isInterface = isInterface; this.descriptor = MethodRecord.createDescriptor(returnType, parameterTypes); - this.returnType = returnType; } /** @@ -192,14 +194,6 @@ public boolean isInterface() { return isInterface; } - /** - * {@inheritDoc} - */ - @Override - public Class getReturnType() { - return returnType; - } - public static TaintMethodRecord getArgWrapperMethod(Type arrayType) { if (arrayType.getDimensions() > 1) { return GET_ARG_WRAPPER_OBJECT; diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintPassingMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintPassingMV.java index 9a9ba8c94..ed6c42077 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintPassingMV.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintPassingMV.java @@ -1157,7 +1157,8 @@ private void visitArrayLoad(int opcode) { loadStackTopShadowVar(); pushPhosphorStackFrame(); getMethod.delegateVisit(mv); - if (Object.class.equals(getMethod.getReturnType()) && referenceArrayTarget != null) { + Type returnType = Type.getReturnType(getMethod.getDescriptor()); + if (Type.getType(Object.class).equals(returnType) && referenceArrayTarget != null) { Type originalArrayType = Type.getType(referenceArrayTarget.getOriginalArrayType()); String castTo = Type.getType(originalArrayType.getDescriptor().substring(1)).getInternalName(); if (originalArrayType.getDimensions() == 2) { diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintTrackingClassVisitor.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintTrackingClassVisitor.java index 59666cc3f..1e0dc258e 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintTrackingClassVisitor.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintTrackingClassVisitor.java @@ -8,6 +8,8 @@ import edu.columbia.cs.psl.phosphor.control.ControlStackInitializingMV; import edu.columbia.cs.psl.phosphor.control.ControlStackRestoringMV; import edu.columbia.cs.psl.phosphor.instrumenter.analyzer.NeverNullArgAnalyzerAdapter; +import edu.columbia.cs.psl.phosphor.mask.ReflectionMV; +import edu.columbia.cs.psl.phosphor.mask.ReflectionMVFactory; import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; import edu.columbia.cs.psl.phosphor.runtime.TaintInstrumented; import edu.columbia.cs.psl.phosphor.runtime.TaintSourceWrapper; @@ -245,7 +247,7 @@ private MethodVisitor createInstrumentingMVChain(int access, String name, String controlStackRestoringMV = new ControlStackRestoringMV(next, rootmV, className, name, controlFlowPolicy); next = controlStackRestoringMV; } - ReflectionHidingMV reflectionMasker = new ReflectionHidingMV(next, className, name, isEnum); + ReflectionMV reflectionMasker = ReflectionMVFactory.create(next, className, name); PrimitiveBoxingFixer boxFixer = new PrimitiveBoxingFixer(access, className, name, instrumentedDesc, signature, _exceptions, reflectionMasker, analyzer); @@ -293,8 +295,7 @@ private MethodVisitor createInstrumentingMVChain(int access, String name, String } lvs.setPrimitiveArrayAnalyzer(primitiveArrayFixer); reflectionMasker.setLvs(lvs); - final MethodVisitor prev = preAnalyzer; - return prev; + return preAnalyzer; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] _exceptions) { diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/DisabledReflectionMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/DisabledReflectionMV.java new file mode 100644 index 000000000..52aa9e521 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/DisabledReflectionMV.java @@ -0,0 +1,39 @@ +package edu.columbia.cs.psl.phosphor.mask; + +import edu.columbia.cs.psl.phosphor.Configuration; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.IS_INSTANCE; + +class DisabledReflectionMV extends ReflectionMV implements Opcodes { + DisabledReflectionMV(MethodVisitor mv, String className, String methodName) { + super(Configuration.ASM_VERSION, mv); + if (!isApplicable(className, methodName)) { + throw new IllegalArgumentException(); + } + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) { + if (owner.equals("java/lang/Class") && name.startsWith("isInstance")) { + // Even if we are not masking other methods, this must be masked + IS_INSTANCE.delegateVisit(mv); + } else { + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + } + + public static boolean isApplicable(String className, String methodName) { + switch (className) { + case "org/codehaus/groovy/vmplugin/v5/Java5": + return methodName.equals("makeInterfaceTypes"); + case "jdk/internal/reflect/ReflectionFactory": + case "java/lang/reflect/ReflectAccess": + // Java >= 9 + // TODO keep? + default: + return false; + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/MaskRegistry.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/MaskRegistry.java new file mode 100644 index 000000000..41bbef3af --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/MaskRegistry.java @@ -0,0 +1,67 @@ +package edu.columbia.cs.psl.phosphor.mask; + +import edu.columbia.cs.psl.phosphor.Phosphor; +import edu.columbia.cs.psl.phosphor.agent.MaskRegistryPatchingCV; +import edu.columbia.cs.psl.phosphor.instrumenter.InvokedViaInstrumentation; +import edu.columbia.cs.psl.phosphor.instrumenter.MethodRecordImpl; +import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; +import edu.columbia.cs.psl.phosphor.struct.harmony.util.HashMap; +import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public final class MaskRegistry { + private static final Map masks = new HashMap<>(); + + private MaskRegistry() { + throw new AssertionError(); + } + + static { + initialize(); + } + + public static MaskInfo getMask(String className, String methodName, String descriptor) { + return masks.get(getKey(className, methodName, descriptor)); + } + + public static String getKey(String className, String methodName, String descriptor) { + return className + "." + methodName + descriptor; + } + + /** + * The body of this method is replaced by {@link MaskRegistryPatchingCV} when the Phosphor is + * JAR is patched. + */ + private static void initialize() { + masks.putAll(MaskRegistryPatchingCV.readMasks()); + if (Phosphor.RUNTIME_INST) { + throw new AssertionError("Calling unpatched method body"); + } + } + + @InvokedViaInstrumentation(record = TaintMethodRecord.ADD_MASK) + private static void addMask(String key, String owner, String name, String descriptor) { + MethodRecordImpl record = new MethodRecordImpl(Opcodes.INVOKESTATIC, owner, name, descriptor, false); + masks.put(key, new MaskInfo(record)); + } + + public static class MaskInfo { + private final MethodRecordImpl record; + + public MaskInfo(MethodRecordImpl record) { + if (record == null) { + throw new NullPointerException(); + } + this.record = record; + } + + public MethodRecordImpl getRecord() { + return record; + } + + public void accept(MethodVisitor mv) { + record.delegateVisit(mv); + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ObjectStreamReflectionMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ObjectStreamReflectionMV.java new file mode 100644 index 000000000..7079202d6 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ObjectStreamReflectionMV.java @@ -0,0 +1,53 @@ +package edu.columbia.cs.psl.phosphor.mask; + +import edu.columbia.cs.psl.phosphor.Configuration; +import org.objectweb.asm.MethodVisitor; + +import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.IS_INSTANCE; + +class ObjectStreamReflectionMV extends ReflectionMV { + private final String methodName; + + ObjectStreamReflectionMV(MethodVisitor mv, String className, String methodName) { + super(Configuration.ASM_VERSION, mv); + if (!isApplicable(className, methodName)) { + throw new IllegalArgumentException(); + } + this.methodName = methodName; + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) { + if (owner.equals("java/lang/Class") && name.startsWith("isInstance")) { + // Even if we are not masking other methods, this must be masked + IS_INSTANCE.delegateVisit(mv); + } else if (owner.equals("sun/misc/Unsafe") && shouldMask(name)) { + MaskRegistry.getMask(owner, name, desc).accept(mv); + } else { + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + } + + private boolean shouldMask(String name) { + switch (methodName) { + case "setObjFieldValues": + return name.startsWith("putObject") || name.startsWith("compareAndSwapObject"); + case "getObjFieldValues": + return name.startsWith("getObject"); + case "getPrimFieldValues": + case "setPrimFieldValues": + // Check for name.startsWith("put") || name.startsWith("get") was included but unhandled with a + // TODO and the note: name = name + "$$NOUNBOX" + // It is unclear if this needs to fixed + default: + return false; + } + } + + public static boolean isApplicable(String className, String methodName) { + return (className.startsWith("java/io/ObjectStreamClass") || className.equals("java/io/ObjectStreamField")) + && Configuration.TAINT_THROUGH_SERIALIZATION + // TODO FIX + && !methodName.equals("getDeclaredSerialFields$$PHOSPHORTAGGED"); + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionHidingMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionHidingMV.java new file mode 100644 index 000000000..779535b29 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionHidingMV.java @@ -0,0 +1,494 @@ +package edu.columbia.cs.psl.phosphor.mask; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.instrumenter.LocalVariableManager; +import edu.columbia.cs.psl.phosphor.mask.MaskRegistry.MaskInfo; +import edu.columbia.cs.psl.phosphor.runtime.*; +import edu.columbia.cs.psl.phosphor.runtime.mask.JdkUnsafeMasker; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.*; + +class ReflectionHidingMV extends ReflectionMV implements Opcodes { + private final String className; + private final String methodName; + private final boolean patchAnonymousClasses; + private LocalVariableManager lvs; + + ReflectionHidingMV(MethodVisitor mv, String className, String name) { + super(Configuration.ASM_VERSION, mv); + this.className = className; + this.methodName = name; + this.patchAnonymousClasses = className.equals("java/lang/invoke/InnerClassLambdaMetafactory") + || className.equals("sun/reflect/ClassDefiner"); + } + + @Override + public void setLvs(LocalVariableManager lvs) { + this.lvs = lvs; + } + + @Override + public void visitCode() { + super.visitCode(); + if (this.className.equals("java/lang/invoke/MethodHandles$Lookup") + && this.methodName.startsWith("defineHiddenClass")) { + super.visitVarInsn(ALOAD, 1); + INSTRUMENT_CLASS_BYTES.delegateVisit(mv); + super.visitVarInsn(ASTORE, 1); + } + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) { + String descWithoutStackFrame = desc.replace(PhosphorStackFrame.DESCRIPTOR, ""); + if ((className.equals("java/io/ObjectOutputStream") || className.equals("java/io/ObjectInputStream")) + && owner.equals("java/lang/Class") + && name.startsWith("isInstance")) { + IS_INSTANCE.delegateVisit(mv); + return; + } + switch (owner) { + case "jdk/internal/reflect/Reflection": + maskReflection(opcode, owner, name, desc, isInterface); + return; + case "java/lang/reflect/Array": + maskArray(opcode, owner, name, desc, isInterface); + return; + case "java/lang/Character": + maskCharacter(opcode, owner, name, desc, isInterface); + return; + case "sun/reflect/NativeMethodAccessorImpl": + case "jdk/internal/reflect/NativeMethodAccessorImpl": + maskMethodAccessor(opcode, owner, name, desc, isInterface); + return; + case "sun/reflect/NativeConstructorAccessorImpl": + case "jdk/internal/reflect/NativeConstructorAccessorImpl": + maskConstructorAccessor(opcode, owner, name, desc, isInterface); + return; + case "jdk/internal/misc/Unsafe": + maskUnsafe(opcode, owner, name, desc, isInterface, descWithoutStackFrame); + return; + default: + MaskInfo mask = MaskRegistry.getMask(owner, name, desc); + if (mask != null) { + if ((!name.equals("defineAnonymousClass") && !name.equals("defineClass")) + || patchAnonymousClasses) { + mask.accept(mv); + return; + } + } + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + fixReturn(owner, name, name, descWithoutStackFrame); + } + } + + private void maskUnsafe( + int opcode, String owner, String name, String desc, boolean isInterface, String descWithoutStackFrame) { + if (patchAnonymousClasses + && name.equals("defineAnonymousClass") + && descWithoutStackFrame.equals("(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;")) { + super.visitInsn(POP); + super.visitInsn(SWAP); + INSTRUMENT_CLASS_BYTES_ANONYMOUS.delegateVisit(mv); + super.visitInsn(SWAP); + desc = descWithoutStackFrame; // Go directly to the native call + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } else if (shouldPatchUnsafe(name, descWithoutStackFrame)) { + name = name.replace("Object", "Reference"); + desc = "(L" + owner + ";" + desc.substring(1); + owner = Type.getInternalName(JdkUnsafeMasker.class); + super.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); + } else { + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + } + + private boolean shouldPatchUnsafe(String name, String originalDesc) { + // Java 11 uses get/putObject instead of Reference + name = name.replace("Object", "Reference"); + switch (name) { + case "allocateUninitializedArray": + case "copyMemory": + case "copySwapMemory": + return true; + default: + return isUnsafeIntrinsic(name, originalDesc); + } + } + + private boolean isUnsafeIntrinsic(String name, String originalDesc) { + switch (originalDesc) { + case "(Ljava/lang/Object;JLjava/lang/Object;)V": + switch (name) { + case "putReference": + case "putReferenceVolatile": + case "putReferenceOpaque": + case "putReferenceRelease": + return true; + } + case "(Ljava/lang/Object;JZ)V": + switch (name) { + case "putBoolean": + case "putBooleanVolatile": + case "putBooleanOpaque": + case "putBooleanRelease": + return true; + } + case "(Ljava/lang/Object;J)B": + switch (name) { + case "getByte": + case "getByteVolatile": + case "getByteOpaque": + case "getByteAcquire": + return true; + } + case "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z": + switch (name) { + case "compareAndSetReference": + case "weakCompareAndSetReferencePlain": + case "weakCompareAndSetReferenceAcquire": + case "weakCompareAndSetReferenceRelease": + case "weakCompareAndSetReference": + return true; + } + case "(Ljava/lang/Object;JJJ)J": + switch (name) { + case "compareAndExchangeLong": + case "compareAndExchangeLongAcquire": + case "compareAndExchangeLongRelease": + return true; + } + case "(Ljava/lang/Object;JB)B": + switch (name) { + case "getAndAddByte": + case "getAndSetByte": + return true; + } + case "(Ljava/lang/Object;JJJ)Z": + switch (name) { + case "compareAndSetLong": + case "weakCompareAndSetLongPlain": + case "weakCompareAndSetLongAcquire": + case "weakCompareAndSetLongRelease": + case "weakCompareAndSetLong": + return true; + } + case "(Ljava/lang/Object;JBB)Z": + switch (name) { + case "compareAndSetByte": + case "weakCompareAndSetBytePlain": + case "weakCompareAndSetByteAcquire": + case "weakCompareAndSetByteRelease": + case "weakCompareAndSetByte": + return true; + } + case "(Ljava/lang/Object;JI)I": + switch (name) { + case "getAndAddInt": + case "getAndSetInt": + return true; + } + case "(Ljava/lang/Object;JSS)S": + switch (name) { + case "compareAndExchangeShort": + case "compareAndExchangeShortAcquire": + case "compareAndExchangeShortRelease": + return true; + } + case "(Ljava/lang/Object;JSS)Z": + switch (name) { + case "compareAndSetShort": + case "weakCompareAndSetShortPlain": + case "weakCompareAndSetShortAcquire": + case "weakCompareAndSetShortRelease": + case "weakCompareAndSetShort": + return true; + } + case "(Ljava/lang/Object;JJ)J": + switch (name) { + case "getAndAddLong": + case "getAndSetLong": + return true; + } + case "(Ljava/lang/Object;J)Ljava/lang/Object;": + switch (name) { + case "getReference": + case "getReferenceVolatile": + case "getReferenceOpaque": + case "getReferenceAcquire": + return true; + } + case "(Ljava/lang/Object;JD)V": + switch (name) { + case "putDouble": + case "putDoubleVolatile": + case "putDoubleOpaque": + case "putDoubleRelease": + return true; + } + case "(Ljava/lang/Object;JII)I": + switch (name) { + case "compareAndExchangeInt": + case "compareAndExchangeIntAcquire": + case "compareAndExchangeIntRelease": + return true; + } + case "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;": + if (name.equals("getAndSetReference")) { + return true; + } + case "(Ljava/lang/Object;JC)V": + switch (name) { + case "putChar": + case "putCharVolatile": + case "putCharOpaque": + case "putCharRelease": + case "putCharUnaligned": + return true; + } + case "(Ljava/lang/Object;J)Z": + switch (name) { + case "getBoolean": + case "getBooleanVolatile": + case "getBooleanOpaque": + case "getBooleanAcquire": + return true; + } + case "(Ljava/lang/Object;JB)V": + switch (name) { + case "putByte": + case "putByteVolatile": + case "putByteOpaque": + case "putByteRelease": + return true; + } + case "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;": + switch (name) { + case "compareAndExchangeReference": + case "compareAndExchangeReferenceAcquire": + case "compareAndExchangeReferenceRelease": + return true; + } + case "(Ljava/lang/Object;J)S": + switch (name) { + case "getShort": + case "getShortVolatile": + case "getShortOpaque": + case "getShortAcquire": + case "getShortUnaligned": + return true; + } + case "(Ljava/lang/Object;JF)V": + switch (name) { + case "putFloat": + case "putFloatVolatile": + case "putFloatOpaque": + case "putFloatRelease": + return true; + } + case "(Ljava/lang/Object;JJ)V": + switch (name) { + case "putLong": + case "putLongVolatile": + case "putLongOpaque": + case "putLongRelease": + case "putLongUnaligned": + return true; + } + case "(Ljava/lang/Object;JI)V": + switch (name) { + case "putInt": + case "putIntVolatile": + case "putIntOpaque": + case "putIntRelease": + case "putIntUnaligned": + return true; + } + case "(Ljava/lang/Object;JBB)B": + switch (name) { + case "compareAndExchangeByte": + case "compareAndExchangeByteAcquire": + case "compareAndExchangeByteRelease": + return true; + } + case "(Ljava/lang/Object;JS)S": + switch (name) { + case "getAndAddShort": + case "getAndSetShort": + return true; + } + case "(Ljava/lang/Object;JS)V": + switch (name) { + case "putShort": + case "putShortVolatile": + case "putShortOpaque": + case "putShortRelease": + case "putShortUnaligned": + return true; + } + case "(Ljava/lang/Object;JII)Z": + switch (name) { + case "compareAndSetInt": + case "weakCompareAndSetIntPlain": + case "weakCompareAndSetIntAcquire": + case "weakCompareAndSetIntRelease": + case "weakCompareAndSetInt": + return true; + } + case "(Ljava/lang/Object;J)J": + switch (name) { + case "getLong": + case "getLongVolatile": + case "getLongOpaque": + case "getLongAcquire": + case "getLongUnaligned": + return true; + } + case "(Ljava/lang/Object;J)I": + switch (name) { + case "getInt": + case "getIntVolatile": + case "getIntOpaque": + case "getIntAcquire": + case "getIntUnaligned": + return true; + } + case "(Ljava/lang/Object;J)D": + switch (name) { + case "getDouble": + case "getDoubleVolatile": + case "getDoubleOpaque": + case "getDoubleAcquire": + return true; + } + case "(Ljava/lang/Object;J)C": + switch (name) { + case "getChar": + case "getCharVolatile": + case "getCharOpaque": + case "getCharAcquire": + case "getCharUnaligned": + return true; + } + case "(Ljava/lang/Object;J)F": + switch (name) { + case "getFloat": + case "getFloatVolatile": + case "getFloatOpaque": + case "getFloatAcquire": + return true; + } + } + return false; + } + + private void maskReflection(int opcode, String owner, String name, String desc, boolean isInterface) { + // If we in a wrapped method and called by the wrapper + // get the caller class of the wrapper not this stack frame + if (name.equals("getCallerClass")) { + int phosphorStackFrame = lvs.getLocalVariableAdder().getIndexOfPhosphorStackData(); + super.visitVarInsn(ALOAD, phosphorStackFrame); + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + super.visitLdcInsn(Type.getObjectType(className)); + GET_CALLER_CLASS_WRAPPER.delegateVisit(mv); + } else { + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + } + + private void maskArray(int opcode, String owner, String name, String desc, boolean isInterface) { + if (!owner.equals(className)) { + owner = Type.getInternalName(ArrayReflectionMasker.class); + } + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + + private void maskCharacter(int opcode, String owner, String name, String desc, boolean isInterface) { + switch (name) { + case "codePointAt": + case "toChars": + case "codePointBefore": + case "reverseBytes": + case "toLowerCase": + case "toTitleCase": + case "toUpperCase": + owner = Type.getInternalName(CharacterUtils.class); + desc = lvs.patchDescToAcceptPhosphorStackFrameAndPushIt(desc, mv); + } + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + + private void maskConstructorAccessor(int opcode, String owner, String name, String desc, boolean isInterface) { + if (name.equals("newInstance0")) { + PREPARE_FOR_CALL_REFLECTIVE_CONSTRUCTOR.delegateVisit(this); + String constructorInvocationPairInternalName = + Type.getInternalName(ReflectionMasker.ConstructorInvocationPair.class); + mv.visitInsn(DUP); + mv.visitFieldInsn( + GETFIELD, + constructorInvocationPairInternalName, + "constructor", + Type.getDescriptor(Constructor.class)); + mv.visitInsn(SWAP); + mv.visitFieldInsn(GETFIELD, constructorInvocationPairInternalName, "args", "[Ljava/lang/Object;"); + mv.visitVarInsn(ALOAD, lvs.getLocalVariableAdder().getIndexOfPhosphorStackData()); + } + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + + private void maskMethodAccessor(int opcode, String owner, String name, String desc, boolean isInterface) { + if (name.equals("invoke0")) { + // Stack: Method Receiver Args StackData + PREPARE_FOR_CALL_REFLECTIVE.delegateVisit(this); + String methodTupleInternalName = Type.getInternalName(ReflectionMasker.MethodInvocationTuple.class); + mv.visitInsn(DUP); + mv.visitFieldInsn( + GETFIELD, + methodTupleInternalName, + "method", + Type.getType(Method.class).getDescriptor()); + mv.visitInsn(SWAP); + mv.visitInsn(DUP); + mv.visitFieldInsn(GETFIELD, methodTupleInternalName, "receiver", "Ljava/lang/Object;"); + mv.visitInsn(SWAP); + mv.visitFieldInsn(GETFIELD, methodTupleInternalName, "args", "[Ljava/lang/Object;"); + mv.visitVarInsn(ALOAD, lvs.getLocalVariableAdder().getIndexOfPhosphorStackData()); + } + super.visitMethodInsn(opcode, owner, name, desc, isInterface); + } + + private void fixReturn(String owner, String name, String nameWithoutSuffix, String descWithoutStackFrame) { + if (owner.equals("java/lang/Class") && !className.equals("java/lang/Class")) { + if (nameWithoutSuffix.endsWith("Fields")) { + if (!Configuration.WITHOUT_FIELD_HIDING) { + REMOVE_TAINTED_FIELDS.delegateVisit(mv); + } + } else if (nameWithoutSuffix.endsWith("Methods") + && descWithoutStackFrame.equals("()" + Type.getDescriptor(Method[].class))) { + REMOVE_TAINTED_METHODS.delegateVisit(mv); + } else if (nameWithoutSuffix.endsWith("Constructors") + && descWithoutStackFrame.equals("()" + Type.getDescriptor(Constructor[].class))) { + REMOVE_TAINTED_CONSTRUCTORS.delegateVisit(mv); + } else if (name.equals("getInterfaces")) { + REMOVE_TAINTED_INTERFACES.delegateVisit(mv); + } + } else if (owner.equals("java/lang/Throwable")) { + if (name.equals("getOurStackTrace") || name.equals("getStackTrace")) { + if (descWithoutStackFrame.equals("()" + Type.getDescriptor(StackTraceElement[].class))) { + // TODO REMOVE_EXTRA_STACK_TRACE_ELEMENTS? + } + } + } else if (owner.equals("java/lang/reflect/Method")) { + if (name.equals("invoke")) { + mv.visitVarInsn(ALOAD, lvs.getLocalVariableAdder().getIndexOfPhosphorStackData()); + UNWRAP_RETURN.delegateVisit(mv); + } + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionMV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionMV.java new file mode 100644 index 000000000..605e0a29f --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionMV.java @@ -0,0 +1,13 @@ +package edu.columbia.cs.psl.phosphor.mask; + +import edu.columbia.cs.psl.phosphor.instrumenter.LocalVariableManager; +import org.objectweb.asm.MethodVisitor; + +public abstract class ReflectionMV extends MethodVisitor { + protected ReflectionMV(int api, MethodVisitor methodVisitor) { + super(api, methodVisitor); + } + + public void setLvs(LocalVariableManager lvs) { + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionMVFactory.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionMVFactory.java new file mode 100644 index 000000000..62e448506 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/ReflectionMVFactory.java @@ -0,0 +1,15 @@ +package edu.columbia.cs.psl.phosphor.mask; + +import org.objectweb.asm.MethodVisitor; + +public final class ReflectionMVFactory { + public static ReflectionMV create(MethodVisitor mv, String className, String methodName) { + if (ObjectStreamReflectionMV.isApplicable(className, methodName)) { + return new ObjectStreamReflectionMV(mv, className, methodName); + } else if (DisabledReflectionMV.isApplicable(className, methodName)) { + return new DisabledReflectionMV(mv, className, methodName); + } else { + return new ReflectionHidingMV(mv, className, methodName); + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/SerializationFixingCV.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/SerializationFixingCV.java similarity index 99% rename from Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/SerializationFixingCV.java rename to Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/SerializationFixingCV.java index f03b809a0..51198070e 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/SerializationFixingCV.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/mask/SerializationFixingCV.java @@ -1,7 +1,8 @@ -package edu.columbia.cs.psl.phosphor.instrumenter; +package edu.columbia.cs.psl.phosphor.mask; import edu.columbia.cs.psl.phosphor.Configuration; import edu.columbia.cs.psl.phosphor.control.OpcodesUtil; +import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; import edu.columbia.cs.psl.phosphor.runtime.Taint; import org.objectweb.asm.*; diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/RuntimeSunMiscUnsafePropagator.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/RuntimeSunMiscUnsafePropagator.java deleted file mode 100644 index 7c6d10864..000000000 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/RuntimeSunMiscUnsafePropagator.java +++ /dev/null @@ -1,805 +0,0 @@ -package edu.columbia.cs.psl.phosphor.runtime.jdk.unsupported; - -import edu.columbia.cs.psl.phosphor.Configuration; -import edu.columbia.cs.psl.phosphor.Phosphor; -import edu.columbia.cs.psl.phosphor.TaintUtils; -import edu.columbia.cs.psl.phosphor.runtime.MultiDArrayUtils; -import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; -import edu.columbia.cs.psl.phosphor.runtime.RuntimeJDKInternalUnsafePropagator.OffsetPair; -import edu.columbia.cs.psl.phosphor.runtime.Taint; -import edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREFieldHelper; -import edu.columbia.cs.psl.phosphor.struct.*; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.security.ProtectionDomain; - -/* Ensures that calls methods in Unsafe that set or retrieve the value of a field of a Java heap object set and - * retrieve both the original field and its associated taint field if it has one. */ -public class RuntimeSunMiscUnsafePropagator { - - private RuntimeSunMiscUnsafePropagator() { - // Prevents this class from being instantiated - } - - /* Used to disambiguate between a static field of a given type and an instance field of java.lang.Class */ - static long LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS = UnsafeProxy.INVALID_FIELD_OFFSET; - - /* Stores pairs containing the offset of an original, non-static primitive or primitive array field for the specified - * class and the offset of the tag field associated with that original field. */ - private static SinglyLinkedList getOffsetPairs(UnsafeProxy unsafe, Class targetClazz) { - SinglyLinkedList list = new SinglyLinkedList<>(); - for(Class clazz = targetClazz; clazz != null && !Object.class.equals(clazz); clazz = clazz.getSuperclass()) { - for(Field field : clazz.getDeclaredFields()) { - try { - Class fieldClazz = field.getType(); - boolean isStatic = Modifier.isStatic(field.getModifiers()); - long fieldOffset = (isStatic ? unsafe.staticFieldOffset(field) : unsafe.objectFieldOffset(field)); - long tagOffset = UnsafeProxy.INVALID_FIELD_OFFSET; - long wrapperOffset = UnsafeProxy.INVALID_FIELD_OFFSET; - try { - if(!field.getName().equals("SPECIES_DATA")) { - Field taintField = clazz.getField(field.getName() + TaintUtils.TAINT_FIELD); - if (taintField.getType().equals(Configuration.TAINT_TAG_OBJ_CLASS)) { - tagOffset = (isStatic ? unsafe.staticFieldOffset(taintField) : unsafe.objectFieldOffset(taintField)); - } - } - } catch(Exception e) { - // - } - if(fieldClazz.isArray()) { - try { - Field taintField = clazz.getField(field.getName() + TaintUtils.TAINT_WRAPPER_FIELD); - Class taintClazz = taintField.getType(); - if(taintClazz != null && TaggedArray.class.isAssignableFrom(taintClazz)) { - wrapperOffset = (isStatic ? unsafe.staticFieldOffset(taintField) : unsafe.objectFieldOffset(taintField)); - } - } catch(Exception e) { - // - } - } - list.enqueue(new OffsetPair(isStatic, fieldOffset, wrapperOffset, tagOffset)); - } catch(Exception e) { - // - } - } - } - return list; - } - - /* returns an offset pair for the specified object's class where either the original field offset or the tag field - * offset matches the specified offset or null if such an offset pair could not be found. */ - public static OffsetPair getOffsetPair(UnsafeProxy unsafe, Object o, long offset) { - try { - Class cl = null; - boolean isStatic = false; - if(o instanceof Class) { - /* We MIGHT be accessing a static field of this class, in which case we should take - the offset from *this* class instance (o). But, we might also be accessing an instance - field of the type Class, in which case we want to use the classes's class. - */ - if(LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS == UnsafeProxy.INVALID_FIELD_OFFSET) { - findLastInstanceFieldOnJavaLangClass(unsafe); - } - if(offset > LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS) { - /* We are not accessing an instance field of java.lang.Class, hence, we must be accessing - * a static field of type (Class) o */ - cl = (Class) o; - isStatic = true; - } - /* Otherwise, we are accessing an instance field of java.lang.Class */ - } - if(cl == null && o != null && o.getClass() != null) { - cl = o.getClass(); - } - if(cl != null) { - if(InstrumentedJREFieldHelper.get$$PHOSPHOR_OFFSET_CACHE(cl) == null) { - InstrumentedJREFieldHelper.set$$PHOSPHOR_OFFSET_CACHE(cl, getOffsetPairs(unsafe, cl)); - } - for(OffsetPair pair : InstrumentedJREFieldHelper.get$$PHOSPHOR_OFFSET_CACHE(cl)) { - if(pair.origFieldOffset == offset && pair.isStatic == isStatic) { - return pair; - } - } - } - return null; - } catch(Exception e) { - return null; - } - } - - private static void findLastInstanceFieldOnJavaLangClass(UnsafeProxy unsafe) { - for(Field field : Class.class.getDeclaredFields()) { - try { - Class fieldClazz = field.getType(); - boolean isStatic = Modifier.isStatic(field.getModifiers()); - if(isStatic) { - continue; - } - long fieldOffset = unsafe.objectFieldOffset(field); - if(fieldOffset > LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS) { - LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS = fieldOffset; - } - } catch(Exception e) { - // - } - } - } - - /* If prealloc is a wrapped primitive type, set it's taint to be the value of the field at the specified offset in the - * other specified object. Otherwise returns the value of the field at the specified offset in the specified object. */ - private static void getTag(UnsafeProxy unsafe, Object obj, long originalOffset, PhosphorStackFrame stackFrame, SpecialAccessPolicy policy) { - stackFrame.returnTaint = Taint.emptyTaint(); - OffsetPair pair = getOffsetPair(unsafe, obj, originalOffset); - if(pair != null && pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - Object result = (policy == SpecialAccessPolicy.VOLATILE) ? unsafe.getObjectVolatile(obj, pair.tagFieldOffset) : unsafe.getObject(obj, pair.tagFieldOffset); - if(result instanceof Taint) { - stackFrame.returnTaint = (Taint) result; - } - } - } - - /* If the specified Object value is a wrapped primitive type, puts it's taint into the field at the specified offset in the - * other specified object. Otherwise if the specified Object value is null or a lazy array wrapper put the specified Object - * value into the field at the specified offset in the other specified object. */ - private static void putTag(UnsafeProxy unsafe, Object obj, long offset, Taint tag, SpecialAccessPolicy policy) { - OffsetPair pair = null; - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null) { - switch(policy) { - case ORDERED: - unsafe.putOrderedObject(obj, pair.tagFieldOffset, tag); - break; - case VOLATILE: - unsafe.putObjectVolatile(obj, pair.tagFieldOffset, tag); - break; - default: - unsafe.putObject(obj, pair.tagFieldOffset, tag); - } - } - } - - /* If the specified TaintedPrimitiveWithObjTag and TaggedArray's component types match sets a tag - * in the specified TaggedArray at a calculated index. - * type's match. */ - private static void swapArrayElementTag(UnsafeProxy unsafe, TaggedArray tags, long offset, Taint valueTaint) { - if(tags.getVal() != null && tags.getVal().getClass().isArray()) { - Class clazz = tags.getVal().getClass(); - long baseOffset = unsafe.arrayBaseOffset(clazz); - long scale = unsafe.arrayIndexScale(clazz); - // Calculate the index based off the offset - int index = (int) ((offset - baseOffset) / scale); - if(tags.taints == null && valueTaint != null && !valueTaint.isEmpty()) { - tags.taints = new Taint[tags.getLength()]; - } - if(tags.taints != null) { - tags.taints[index] = valueTaint; - } - } - } - - public static void copyMemory(UnsafeProxy unsafe, Object src, long srcAddress, Object dest, long destAddress, long length, PhosphorStackFrame stackFrame) { - if(src instanceof TaggedArray) { - src = ((TaggedArray) src).getVal(); - } - if(dest instanceof TaggedArray) { - dest = ((TaggedArray) dest).getVal(); - } - unsafe.copyMemory(src, srcAddress, dest, destAddress, length); - } - - public static void copyMemory(UnsafeProxy unsafe, long srcAddress, long destAddress, long length, PhosphorStackFrame stackFrame) { - unsafe.copyMemory(srcAddress, destAddress, length); - } - - public static boolean compareAndSwapObject(UnsafeProxy unsafe, Object obj, long offset, Object expected, Object value, PhosphorStackFrame stackFrame) { - stackFrame.returnTaint = Taint.emptyTaint(); - boolean ret = false; - if(obj instanceof TaggedReferenceArray) { - Taint valueTaint = stackFrame.getArgTaint(4); - ret = unsafe.compareAndSwapObject(((TaggedReferenceArray) obj).val, offset, expected, value); - if(ret) { - swapArrayElementTag(unsafe, (TaggedArray) obj, offset, valueTaint); - } - } else { - OffsetPair pair = null; - boolean didCAS = false; - if(value instanceof TaggedArray || expected instanceof TaggedArray) { - //Need to be careful - maybe we are hitting a 1D primitive array field - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null && pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - //We are doing a CAS on a 1d primitive array field - ret = unsafe.compareAndSwapObject(obj, offset, MultiDArrayUtils.unbox1DOrNull(expected), MultiDArrayUtils.unbox1DOrNull(value)); - didCAS = true; - } - } - if(!didCAS) { - //Either this is not a wrapped array, or we are storing it to the place where it should be stored without unwrapping - ret = unsafe.compareAndSwapObject(obj, offset, expected, value); - if(pair == null && obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - } - - if(pair != null && ret) { - if(pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObjectVolatile(obj, pair.tagFieldOffset, stackFrame.getArgTaint(4)); - } - if(pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObjectVolatile(obj, pair.wrappedFieldOffset, value); - } - } - } - return ret; - } - - public static boolean compareAndSwapInt(UnsafeProxy unsafe, Object obj, long offset, int expected, int value, PhosphorStackFrame phosphorStackFrame) { - phosphorStackFrame.returnTaint = Taint.emptyTaint(); - boolean ret = false; - if(obj instanceof TaggedIntArray) { - ret = unsafe.compareAndSwapInt(((TaggedIntArray) obj).val, offset, expected, value); - if(ret) { - swapArrayElementTag(unsafe, (TaggedArray) obj, offset, phosphorStackFrame.getArgTaint(4)); - } - } else { - ret = unsafe.compareAndSwapInt(obj, offset, expected, value); - OffsetPair pair = null; - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null && ret) { - if(pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObjectVolatile(obj, pair.tagFieldOffset, phosphorStackFrame.getArgTaint(4)); - } - } - } - return ret; - } - - public static boolean compareAndSwapLong(UnsafeProxy unsafe, Object obj, long offset, long expected, long value, PhosphorStackFrame phosphorStackFrame) { - phosphorStackFrame.returnTaint = Taint.emptyTaint(); - boolean ret = false; - if(obj instanceof TaggedLongArray) { - ret = unsafe.compareAndSwapLong(((TaggedLongArray) obj).val, offset, expected, value); - if(ret) { - swapArrayElementTag(unsafe, (TaggedArray) obj, offset, phosphorStackFrame.getArgTaint(4)); - } - } else { - ret = unsafe.compareAndSwapLong(obj, offset, expected, value); - OffsetPair pair = null; - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null && ret) { - if(pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObjectVolatile(obj, pair.tagFieldOffset, phosphorStackFrame.getArgTaint(4)); - } - } - } - return ret; - } - - private static int unsafeIndexFor(UnsafeProxy unsafe, TaggedArray array, long offset) { - Class clazz = array.getVal().getClass(); - long baseOffset = unsafe.arrayBaseOffset(clazz); - long scale = unsafe.arrayIndexScale(clazz); - // Calculate the index based off the offset - int index = (int) ((offset - baseOffset) / scale); - return index; - } - - public static void putObject(UnsafeProxy unsafe, Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { - if(obj instanceof TaggedReferenceArray) { - ((TaggedReferenceArray) obj).set(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), val, phosphorStackFrame.getArgTaint(3)); - } else { - OffsetPair pair = null; - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null) { - if(pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObject(obj, pair.tagFieldOffset, phosphorStackFrame.getArgTaint(3)); - } - if(pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObject(obj, pair.wrappedFieldOffset, val); - unsafe.putObject(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - } else { - unsafe.putObject(obj, offset, val); - } - } else { - unsafe.putObject(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - } - } - } - - public static void putOrderedObject(UnsafeProxy unsafe, Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { - if(obj instanceof TaggedReferenceArray) { - ((TaggedReferenceArray) obj).set(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), val, phosphorStackFrame.getArgTaint(3)); - } else { - OffsetPair pair = null; - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null) { - if(pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putOrderedObject(obj, pair.tagFieldOffset, phosphorStackFrame.getArgTaint(3)); - } - if(pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putOrderedObject(obj, pair.wrappedFieldOffset, val); - unsafe.putOrderedObject(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - } else { - unsafe.putOrderedObject(obj, offset, val); - } - } else { - unsafe.putOrderedObject(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - } - } - } - - public static void putObjectVolatile(UnsafeProxy unsafe, Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { - if(obj instanceof TaggedReferenceArray) { - ((TaggedReferenceArray) obj).set(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), val, phosphorStackFrame.getArgTaint(3)); - } else { - unsafe.putObjectVolatile(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - OffsetPair pair = null; - if(obj != null) { - pair = getOffsetPair(unsafe, obj, offset); - } - if(pair != null) { - if(pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObjectVolatile(obj, pair.tagFieldOffset, phosphorStackFrame.getArgTaint(3)); - } - if(pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - unsafe.putObjectVolatile(obj, pair.wrappedFieldOffset, val); - unsafe.putObjectVolatile(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - } else { - unsafe.putObjectVolatile(obj, offset, val); - } - } else { - unsafe.putObjectVolatile(obj, offset, MultiDArrayUtils.unbox1DOrNull(val)); - } - } - } - - public static Object getObject(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedReferenceArray) { - //Push the taint from the `offset` argument to the `idx` argument for get - return ((TaggedReferenceArray) obj).get(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), stackFrame.getArgTaint(1), stackFrame); - } else { - //Is this trying to return a field that is wrapped? - OffsetPair pair = getOffsetPair(unsafe, obj, offset); - if(pair != null && pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - offset = pair.wrappedFieldOffset; - } - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getObject(obj, offset); - } - } - - public static Object getObjectVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedReferenceArray) { - //Push the taint from the `offset` argument to the `idx` argument for get - return ((TaggedReferenceArray) obj).get(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), stackFrame.getArgTaint(1), stackFrame); - } else { - //Is this trying to return a field that is wrapped? - OffsetPair pair = getOffsetPair(unsafe, obj, offset); - if(pair != null && pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { - offset = pair.wrappedFieldOffset; - } - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getObjectVolatile(obj, offset); - } - } - - public static void putByte(UnsafeProxy unsafe, Object obj, long offset, byte val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putByte(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putByte(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putByteVolatile(UnsafeProxy unsafe, Object obj, long offset, byte val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putByteVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putByte(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static byte getByte(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getByte(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getByte(obj, offset); - } - } - - public static byte getByteVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getByteVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getByteVolatile(obj, offset); - } - } - - public static void putBoolean(UnsafeProxy unsafe, Object obj, long offset, boolean val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putBoolean(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putBoolean(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putBooleanVolatile(UnsafeProxy unsafe, Object obj, long offset, boolean val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putBooleanVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putBoolean(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static boolean getBoolean(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getBoolean(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getBoolean(obj, offset); - } - } - - public static boolean getBooleanVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getBooleanVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getBooleanVolatile(obj, offset); - } - } - - public static void putChar(UnsafeProxy unsafe, Object obj, long offset, char val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putChar(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putChar(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putCharVolatile(UnsafeProxy unsafe, Object obj, long offset, char val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putCharVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putChar(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static char getChar(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getChar(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getChar(obj, offset); - } - } - - public static char getCharVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getCharVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getCharVolatile(obj, offset); - } - } - - public static void putFloat(UnsafeProxy unsafe, Object obj, long offset, float val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putFloat(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putFloat(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putFloatVolatile(UnsafeProxy unsafe, Object obj, long offset, float val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - - if(obj instanceof TaggedArray) { - unsafe.putFloatVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putFloat(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static float getFloat(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getFloat(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getFloat(obj, offset); - } - } - - public static float getFloatVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getFloatVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getFloatVolatile(obj, offset); - } - } - - public static void putOrderedInt(UnsafeProxy unsafe, Object obj, long offset, int val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putOrderedInt(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putOrderedInt(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.ORDERED); - } - } - - public static void putInt(UnsafeProxy unsafe, Object obj, long offset, int val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putInt(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putInt(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putIntVolatile(UnsafeProxy unsafe, Object obj, long offset, int val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putIntVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putInt(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static int getInt(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getInt(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getInt(obj, offset); - } - } - - public static int getIntVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getIntVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getIntVolatile(obj, offset); - } - } - - public static void putDouble(UnsafeProxy unsafe, Object obj, long offset, double val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putDouble(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putDouble(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putDoubleVolatile(UnsafeProxy unsafe, Object obj, long offset, double val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putDoubleVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putDouble(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static double getDouble(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getDouble(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getDouble(obj, offset); - } - } - - public static double getDoubleVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getDoubleVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getDoubleVolatile(obj, offset); - } - } - - public static void putShort(UnsafeProxy unsafe, Object obj, long offset, short val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putShort(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putShort(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putShortVolatile(UnsafeProxy unsafe, Object obj, long offset, short val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putShortVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putShort(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static short getShort(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getShort(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getShort(obj, offset); - } - } - - public static short getShortVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getShortVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getShortVolatile(obj, offset); - } - } - - public static void putLong(UnsafeProxy unsafe, Object obj, long offset, long val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putLong(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putLong(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static void putOrderedLong(UnsafeProxy unsafe, Object obj, long offset, long val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putOrderedLong(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putOrderedLong(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.ORDERED); - } - } - - public static void putLongVolatile(UnsafeProxy unsafe, Object obj, long offset, long val, PhosphorStackFrame stackFrame) { - Taint valTaint = stackFrame.getArgTaint(3); - if(obj instanceof TaggedArray) { - unsafe.putLongVolatile(((TaggedArray) obj).getVal(), offset, val); - if((valTaint != null && !valTaint.isEmpty()) || ((TaggedArray) obj).taints != null) { - ((TaggedArray) obj).setTaint(unsafeIndexFor(unsafe, (TaggedArray) obj, offset), valTaint); - } - } else { - unsafe.putLong(obj, offset, val); - putTag(unsafe, obj, offset, valTaint, SpecialAccessPolicy.NONE); - } - } - - public static long getLong(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getLong(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.NONE); - return unsafe.getLong(obj, offset); - } - } - - /* for static fields, obj is a class. for instance fields of a class object, obj is also a class. if we want static fields, we need - * offsets from *this* class's declared fields. for instance fields, we */ - public static long getLongVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame stackFrame) { - if(obj instanceof TaggedArray) { - stackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); - return unsafe.getLongVolatile(((TaggedArray) obj).getVal(), offset); - } else { - getTag(unsafe, obj, offset, stackFrame, SpecialAccessPolicy.VOLATILE); - return unsafe.getLongVolatile(obj, offset); - } - } - - public static Class defineClass(UnsafeProxy unsafe, String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6, PhosphorStackFrame phosphorStackFrame) { - byte[] instrumented = Phosphor.instrumentClassBytes(var2); - return unsafe.defineClass(var1, instrumented, 0, instrumented.length, var5, var6); - } - private enum SpecialAccessPolicy { - VOLATILE, - ORDERED, - NONE - } - -} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/JdkUnsafeAdapter.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/JdkUnsafeAdapter.java new file mode 100644 index 000000000..f40b5f16a --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/JdkUnsafeAdapter.java @@ -0,0 +1,302 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import jdk.internal.misc.Unsafe; + +import java.lang.reflect.Field; +import java.security.ProtectionDomain; + +@SuppressWarnings("unused") +public class JdkUnsafeAdapter implements UnsafeAdapter { + private final Unsafe unsafe = Unsafe.getUnsafe(); + + @Override + public long getInvalidFieldOffset() { + return Unsafe.INVALID_FIELD_OFFSET; + } + + @Override + public Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches) { + return unsafe.defineAnonymousClass(hostClass, data, cpPatches); + } + + @Override + public Class defineClass( + String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain) { + return unsafe.defineClass0(name, b, off, len, loader, protectionDomain); + } + + @Override + public int getInt(Object o, long offset) { + return unsafe.getInt(o, offset); + } + + @Override + public void putInt(Object o, long offset, int x) { + unsafe.putInt(o, offset, x); + } + + @Override + public Object getObject(Object o, long offset) { + return unsafe.getObject(o, offset); + } + + @Override + public void putObject(Object o, long offset, Object x) { + unsafe.putObject(o, offset, x); + } + + @Override + public boolean getBoolean(Object o, long offset) { + return unsafe.getBoolean(o, offset); + } + + @Override + public void putBoolean(Object o, long offset, boolean x) { + unsafe.putBoolean(o, offset, x); + } + + @Override + public byte getByte(Object o, long offset) { + return unsafe.getByte(o, offset); + } + + @Override + public void putByte(Object o, long offset, byte x) { + unsafe.putByte(o, offset, x); + } + + @Override + public short getShort(Object o, long offset) { + return unsafe.getShort(o, offset); + } + + @Override + public void putShort(Object o, long offset, short x) { + unsafe.putShort(o, offset, x); + } + + @Override + public char getChar(Object o, long offset) { + return unsafe.getChar(o, offset); + } + + @Override + public void putChar(Object o, long offset, char x) { + unsafe.putChar(o, offset, x); + } + + @Override + public long getLong(Object o, long offset) { + return unsafe.getLong(o, offset); + } + + @Override + public void putLong(Object o, long offset, long x) { + unsafe.putLong(o, offset, x); + } + + @Override + public float getFloat(Object o, long offset) { + return unsafe.getFloat(o, offset); + } + + @Override + public void putFloat(Object o, long offset, float x) { + unsafe.putFloat(o, offset, x); + } + + @Override + public double getDouble(Object o, long offset) { + return unsafe.getDouble(o, offset); + } + + @Override + public void putDouble(Object o, long offset, double x) { + unsafe.putDouble(o, offset, x); + } + + @Override + public byte getByte(long address) { + return unsafe.getByte(address); + } + + @Override + public short getShort(long address) { + return unsafe.getShort(address); + } + + @Override + public char getChar(long address) { + return unsafe.getChar(address); + } + + @Override + public int getInt(long address) { + return unsafe.getInt(address); + } + + @Override + public long getLong(long address) { + return unsafe.getLong(address); + } + + @Override + public float getFloat(long address) { + return unsafe.getFloat(address); + } + + @Override + public double getDouble(long address) { + return unsafe.getDouble(address); + } + + @Override + public void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) { + unsafe.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes); + } + + @Override + public void copyMemory(long srcAddress, long destAddress, long bytes) { + unsafe.copyMemory(srcAddress, destAddress, bytes); + } + + @Override + public long objectFieldOffset(Field f) { + return unsafe.objectFieldOffset(f); + } + + @Override + public long staticFieldOffset(Field f) { + return unsafe.staticFieldOffset(f); + } + + @Override + public int arrayBaseOffset(Class arrayClass) { + return unsafe.arrayBaseOffset(arrayClass); + } + + @Override + public int arrayIndexScale(Class arrayClass) { + return unsafe.arrayIndexScale(arrayClass); + } + + @Override + public Object getObjectVolatile(Object o, long offset) { + return unsafe.getObjectVolatile(o, offset); + } + + @Override + public void putObjectVolatile(Object o, long offset, Object x) { + unsafe.putObjectVolatile(o, offset, x); + } + + @Override + public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) { + return unsafe.compareAndSetObject(o, offset, expected, x); + } + + @Override + public int getIntVolatile(Object o, long offset) { + return unsafe.getIntVolatile(o, offset); + } + + @Override + public void putIntVolatile(Object o, long offset, int x) { + unsafe.putIntVolatile(o, offset, x); + } + + @Override + public boolean getBooleanVolatile(Object o, long offset) { + return unsafe.getBooleanVolatile(o, offset); + } + + @Override + public void putBooleanVolatile(Object o, long offset, boolean x) { + unsafe.putBooleanVolatile(o, offset, x); + } + + @Override + public byte getByteVolatile(Object o, long offset) { + return unsafe.getByteVolatile(o, offset); + } + + @Override + public void putByteVolatile(Object o, long offset, byte x) { + unsafe.putByteVolatile(o, offset, x); + } + + @Override + public short getShortVolatile(Object o, long offset) { + return unsafe.getShortVolatile(o, offset); + } + + @Override + public void putShortVolatile(Object o, long offset, short x) { + unsafe.putShortVolatile(o, offset, x); + } + + @Override + public char getCharVolatile(Object o, long offset) { + return unsafe.getCharVolatile(o, offset); + } + + @Override + public void putCharVolatile(Object o, long offset, char x) { + unsafe.putCharVolatile(o, offset, x); + } + + @Override + public long getLongVolatile(Object o, long offset) { + return unsafe.getLongVolatile(o, offset); + } + + @Override + public void putLongVolatile(Object o, long offset, long x) { + unsafe.putLongVolatile(o, offset, x); + } + + @Override + public float getFloatVolatile(Object o, long offset) { + return unsafe.getFloatVolatile(o, offset); + } + + @Override + public void putFloatVolatile(Object o, long offset, float x) { + unsafe.putFloatVolatile(o, offset, x); + } + + @Override + public double getDoubleVolatile(Object o, long offset) { + return unsafe.getDoubleVolatile(o, offset); + } + + @Override + public void putDoubleVolatile(Object o, long offset, double x) { + unsafe.putDoubleVolatile(o, offset, x); + } + + @Override + public void putOrderedObject(Object o, long offset, Object x) { + unsafe.putObjectVolatile(o, offset, x); + } + + @Override + public boolean compareAndSwapInt(Object o, long offset, int expected, int x) { + return unsafe.compareAndSetInt(o, offset, expected, x); + } + + @Override + public boolean compareAndSwapLong(Object o, long offset, long expected, long x) { + return unsafe.compareAndSetLong(o, offset, expected, x); + } + + @Override + public void putOrderedInt(Object o, long offset, int x) { + unsafe.putIntVolatile(o, offset, x); + } + + @Override + public void putOrderedLong(Object o, long offset, long x) { + unsafe.putLongVolatile(o, offset, x); + } +} \ No newline at end of file diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/RuntimeJDKInternalUnsafePropagator.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/JdkUnsafeMasker.java similarity index 78% rename from Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/RuntimeJDKInternalUnsafePropagator.java rename to Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/JdkUnsafeMasker.java index 75fe45a0e..a628b037c 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/RuntimeJDKInternalUnsafePropagator.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/JdkUnsafeMasker.java @@ -1,8 +1,10 @@ -package edu.columbia.cs.psl.phosphor.runtime; +package edu.columbia.cs.psl.phosphor.runtime.mask; import edu.columbia.cs.psl.phosphor.Configuration; import edu.columbia.cs.psl.phosphor.TaintUtils; -import edu.columbia.cs.psl.phosphor.runtime.jdk.unsupported.UnsafeProxy; +import edu.columbia.cs.psl.phosphor.runtime.MultiDArrayUtils; +import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; +import edu.columbia.cs.psl.phosphor.runtime.Taint; import edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREFieldHelper; import edu.columbia.cs.psl.phosphor.struct.*; import edu.columbia.cs.psl.phosphor.struct.harmony.util.StringBuilder; @@ -12,12 +14,7 @@ /* Ensures that calls methods in UnsafeProxy that set or retrieve the value of a field of a Java heap object set and * retrieve both the original field and its associated taint field if it has one. */ -public class RuntimeJDKInternalUnsafePropagator { - - private RuntimeJDKInternalUnsafePropagator() { - // Prevents this class from being instantiated - } - +public class JdkUnsafeMasker { /* Used to disambiguate between a static field of a given type and an instance field of java.lang.Class */ static long LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS = UnsafeProxy.INVALID_FIELD_OFFSET; @@ -190,14 +187,6 @@ private static void swapArrayElementTag(UnsafeProxy unsafe, TaggedArray tags, lo @SuppressWarnings("unused") public static void copyMemory(UnsafeProxy unsafe, Object src, long srcAddress, Object dest, long destAddress, long length, PhosphorStackFrame phosphorStackFrame) { - //Object srcWrapper = phosphorStackFrame.wrappedArgs[1]; - //if(srcWrapper != null){ - // src = srcWrapper; - //} - //Object destWrapper = phosphorStackFrame.wrappedArgs[3]; - //if(destWrapper != null){ - // dest = destWrapper; - //} if (src instanceof TaggedArray) { src = ((TaggedArray) src).getVal(); } @@ -212,6 +201,7 @@ public static void copyMemory(UnsafeProxy unsafe, long srcAddress, long destAddr unsafe.copyMemory(srcAddress, destAddress, length); } + @SuppressWarnings("unused") public static void copySwapMemory(UnsafeProxy unsafe, Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes, long elemSize, PhosphorStackFrame stackFrame) { if (srcBase instanceof TaggedArray) { @@ -223,6 +213,7 @@ public static void copySwapMemory(UnsafeProxy unsafe, Object srcBase, long srcOf unsafe.copySwapMemory(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); } + @SuppressWarnings("unused") public static void copySwapMemory(UnsafeProxy unsafe, long srcAddress, long destAddress, long bytes, long elemSize, PhosphorStackFrame stackFrame) { unsafe.copySwapMemory(srcAddress, destAddress, bytes, elemSize); } @@ -243,49 +234,16 @@ private enum SpecialAccessPolicy { NONE } - @SuppressWarnings("unused") - - public static class OffsetPair { - - public final long origFieldOffset; - public final long wrappedFieldOffset; - public final long tagFieldOffset; - public final boolean isStatic; - - public OffsetPair(boolean isStatic, long origFieldOffset, long wrappedFieldOffset, long tagFieldOffset) { - this.isStatic = isStatic; - this.origFieldOffset = origFieldOffset; - this.tagFieldOffset = tagFieldOffset; - this.wrappedFieldOffset = wrappedFieldOffset; - } - - @Override - public boolean equals(Object other) { - return other instanceof OffsetPair && this.origFieldOffset == ((OffsetPair) other).origFieldOffset && this.isStatic == ((OffsetPair) other).isStatic; - } - - @Override - public int hashCode() { - return (int) (origFieldOffset ^ (origFieldOffset >>> 32)); - } - - @Override - public String toString() { - return String.format("{field @ %d -> tag @ %d, wrapper @ %d}", origFieldOffset, tagFieldOffset, wrappedFieldOffset); - } - } - private static int unsafeIndexFor(UnsafeProxy unsafe, TaggedArray array, long offset) { Class clazz = array.getVal().getClass(); long baseOffset = unsafe.arrayBaseOffset(clazz); long scale = unsafe.arrayIndexScale(clazz); // Calculate the index based off the offset - int index = (int) ((offset - baseOffset) / scale); - return index; + return (int) ((offset - baseOffset) / scale); } @SuppressWarnings("unused") - public static int getIntUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static int getIntUnaligned(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { if ((offset & 3) == 0) { return getInt(unsafe, o, offset, phosphorStackFrame); } else if ((offset & 1) == 0) { @@ -300,7 +258,7 @@ public static int getIntUnaligned(UnsafeProxy unsafe, java.lang.Object o, long o } @SuppressWarnings("unused") - public static long getLongUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static long getLongUnaligned(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { if ((offset & 7) == 0) { return getLong(unsafe, o, offset, phosphorStackFrame); } else if ((offset & 3) == 0) { @@ -324,7 +282,7 @@ public static long getLongUnaligned(UnsafeProxy unsafe, java.lang.Object o, long } @SuppressWarnings("unused") - public static char getCharUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static char getCharUnaligned(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { if ((offset & 1) == 0) { return getChar(unsafe, o, offset, phosphorStackFrame); } else { @@ -334,7 +292,7 @@ public static char getCharUnaligned(UnsafeProxy unsafe, java.lang.Object o, long } @SuppressWarnings("unused") - public static short getShortUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static short getShortUnaligned(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { if ((offset & 1) == 0) { return getShort(unsafe, o, offset, phosphorStackFrame); } else { @@ -344,7 +302,7 @@ public static short getShortUnaligned(UnsafeProxy unsafe, java.lang.Object o, lo } @SuppressWarnings("unused") - public static void putIntUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, int x, PhosphorStackFrame phosphorStackFrame) { + public static void putIntUnaligned(UnsafeProxy unsafe, Object o, long offset, int x, PhosphorStackFrame phosphorStackFrame) { if ((offset & 3) == 0) { putInt(unsafe, o, offset, x, phosphorStackFrame); } else if ((offset & 1) == 0) { @@ -361,7 +319,7 @@ public static void putIntUnaligned(UnsafeProxy unsafe, java.lang.Object o, long } @SuppressWarnings("unused") - public static void putLongUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, long x, PhosphorStackFrame phosphorStackFrame) { + public static void putLongUnaligned(UnsafeProxy unsafe, Object o, long offset, long x, PhosphorStackFrame phosphorStackFrame) { if ((offset & 7) == 0) { putLong(unsafe, o, offset, x, phosphorStackFrame); } else if ((offset & 3) == 0) { @@ -388,12 +346,12 @@ public static void putLongUnaligned(UnsafeProxy unsafe, java.lang.Object o, long } @SuppressWarnings("unused") - public static void putCharUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, char x, PhosphorStackFrame phosphorStackFrame) { + public static void putCharUnaligned(UnsafeProxy unsafe, Object o, long offset, char x, PhosphorStackFrame phosphorStackFrame) { putShortUnaligned(unsafe, o, offset, (short) x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putShortUnaligned(UnsafeProxy unsafe, java.lang.Object o, long offset, short x, PhosphorStackFrame phosphorStackFrame) { + public static void putShortUnaligned(UnsafeProxy unsafe, Object o, long offset, short x, PhosphorStackFrame phosphorStackFrame) { if ((offset & 1) == 0) { putShort(unsafe, o, offset, x, phosphorStackFrame); } else { @@ -405,125 +363,125 @@ public static void putShortUnaligned(UnsafeProxy unsafe, java.lang.Object o, lon //Generated from Phosphor template for get$methodTypeOpaque(Ljava/lang/Object;J)LPlaceHolder; @SuppressWarnings("unused") - public static byte getByteOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static byte getByteOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getByteVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static int getIntOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static int getIntOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getIntVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static long getLongOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static long getLongOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getLongVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static float getFloatOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static float getFloatOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getFloatVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static Object getReferenceOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static Object getReferenceOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getReferenceVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static char getCharOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static char getCharOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getCharVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static short getShortOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static short getShortOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getShortVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static double getDoubleOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static double getDoubleOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getDoubleVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean getBooleanOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static boolean getBooleanOpaque(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getBooleanVolatile(unsafe, o, offset, phosphorStackFrame); } //Generated from Phosphor template for compareAndExchange$methodTypeAcquire(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)LPlaceHolder; @SuppressWarnings("unused") - public static int compareAndExchangeIntAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static int compareAndExchangeIntAcquire(UnsafeProxy unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeInt(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static byte compareAndExchangeByteAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static byte compareAndExchangeByteAcquire(UnsafeProxy unsafe, Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeByte(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static long compareAndExchangeLongAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static long compareAndExchangeLongAcquire(UnsafeProxy unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeLong(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static Object compareAndExchangeReferenceAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static Object compareAndExchangeReferenceAcquire(UnsafeProxy unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeReference(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static short compareAndExchangeShortAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static short compareAndExchangeShortAcquire(UnsafeProxy unsafe, Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeShort(unsafe, o, offset, expected, x, phosphorStackFrame); } //Generated from Phosphor template for get$methodTypeAcquire(Ljava/lang/Object;J)LPlaceHolder; @SuppressWarnings("unused") - public static byte getByteAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static byte getByteAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getByteVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static int getIntAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static int getIntAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getIntVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static long getLongAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static long getLongAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getLongVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static float getFloatAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static float getFloatAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getFloatVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static Object getReferenceAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static Object getReferenceAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getReferenceVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static char getCharAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static char getCharAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getCharVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static short getShortAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static short getShortAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getShortVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static double getDoubleAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static double getDoubleAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getDoubleVolatile(unsafe, o, offset, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean getBooleanAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, PhosphorStackFrame phosphorStackFrame) { + public static boolean getBooleanAcquire(UnsafeProxy unsafe, Object o, long offset, PhosphorStackFrame phosphorStackFrame) { return getBooleanVolatile(unsafe, o, offset, phosphorStackFrame); } //Generated from Phosphor template for getAndAdd$methodType(Ljava/lang/Object;JLPlaceHolder;)LPlaceHolder; @SuppressWarnings("unused") - public static int getAndAddInt(UnsafeProxy unsafe, java.lang.Object o, long offset, int delta, PhosphorStackFrame phosphorStackFrame) { + public static int getAndAddInt(UnsafeProxy unsafe, Object o, long offset, int delta, PhosphorStackFrame phosphorStackFrame) { int v; do { v = getIntVolatile(unsafe, o, offset, phosphorStackFrame); @@ -532,7 +490,7 @@ public static int getAndAddInt(UnsafeProxy unsafe, java.lang.Object o, long offs } @SuppressWarnings("unused") - public static byte getAndAddByte(UnsafeProxy unsafe, java.lang.Object o, long offset, byte delta, PhosphorStackFrame phosphorStackFrame) { + public static byte getAndAddByte(UnsafeProxy unsafe, Object o, long offset, byte delta, PhosphorStackFrame phosphorStackFrame) { byte v; do { v = getByteVolatile(unsafe, o, offset, phosphorStackFrame); @@ -541,7 +499,7 @@ public static byte getAndAddByte(UnsafeProxy unsafe, java.lang.Object o, long of } @SuppressWarnings("unused") - public static long getAndAddLong(UnsafeProxy unsafe, java.lang.Object o, long offset, long delta, PhosphorStackFrame phosphorStackFrame) { + public static long getAndAddLong(UnsafeProxy unsafe, Object o, long offset, long delta, PhosphorStackFrame phosphorStackFrame) { long v; do { v = getLongVolatile(unsafe, o, offset, phosphorStackFrame); @@ -550,7 +508,7 @@ public static long getAndAddLong(UnsafeProxy unsafe, java.lang.Object o, long of } @SuppressWarnings("unused") - public static short getAndAddShort(UnsafeProxy unsafe, java.lang.Object o, long offset, short delta, PhosphorStackFrame phosphorStackFrame) { + public static short getAndAddShort(UnsafeProxy unsafe, Object o, long offset, short delta, PhosphorStackFrame phosphorStackFrame) { short v; do { v = getShortVolatile(unsafe, o, offset, phosphorStackFrame); @@ -560,7 +518,7 @@ public static short getAndAddShort(UnsafeProxy unsafe, java.lang.Object o, long //Generated from Phosphor template for get$methodTypeVolatile(Ljava/lang/Object;J)LPlaceHolder; @SuppressWarnings("unused") - public static byte getByteVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static byte getByteVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getByteVolatile(((TaggedArray) obj).getVal(), offset); @@ -571,7 +529,7 @@ public static byte getByteVolatile(UnsafeProxy unsafe, java.lang.Object obj, lon } @SuppressWarnings("unused") - public static int getIntVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static int getIntVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getIntVolatile(((TaggedArray) obj).getVal(), offset); @@ -582,7 +540,7 @@ public static int getIntVolatile(UnsafeProxy unsafe, java.lang.Object obj, long } @SuppressWarnings("unused") - public static long getLongVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static long getLongVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getLongVolatile(((TaggedArray) obj).getVal(), offset); @@ -593,7 +551,7 @@ public static long getLongVolatile(UnsafeProxy unsafe, java.lang.Object obj, lon } @SuppressWarnings("unused") - public static float getFloatVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static float getFloatVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getFloatVolatile(((TaggedArray) obj).getVal(), offset); @@ -604,7 +562,7 @@ public static float getFloatVolatile(UnsafeProxy unsafe, java.lang.Object obj, l } @SuppressWarnings("unused") - public static Object getReferenceVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static Object getReferenceVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getReferenceVolatile(((TaggedArray) obj).getVal(), offset); @@ -619,7 +577,7 @@ public static Object getReferenceVolatile(UnsafeProxy unsafe, java.lang.Object o } @SuppressWarnings("unused") - public static char getCharVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static char getCharVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getCharVolatile(((TaggedArray) obj).getVal(), offset); @@ -630,7 +588,7 @@ public static char getCharVolatile(UnsafeProxy unsafe, java.lang.Object obj, lon } @SuppressWarnings("unused") - public static short getShortVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static short getShortVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getShortVolatile(((TaggedArray) obj).getVal(), offset); @@ -641,7 +599,7 @@ public static short getShortVolatile(UnsafeProxy unsafe, java.lang.Object obj, l } @SuppressWarnings("unused") - public static double getDoubleVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static double getDoubleVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getDoubleVolatile(((TaggedArray) obj).getVal(), offset); @@ -652,7 +610,7 @@ public static double getDoubleVolatile(UnsafeProxy unsafe, java.lang.Object obj, } @SuppressWarnings("unused") - public static boolean getBooleanVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static boolean getBooleanVolatile(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getBooleanVolatile(((TaggedArray) obj).getVal(), offset); @@ -664,105 +622,105 @@ public static boolean getBooleanVolatile(UnsafeProxy unsafe, java.lang.Object ob //Generated from Phosphor template for compareAndExchange$methodTypeRelease(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)LPlaceHolder; @SuppressWarnings("unused") - public static int compareAndExchangeIntRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static int compareAndExchangeIntRelease(UnsafeProxy unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeInt(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static byte compareAndExchangeByteRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static byte compareAndExchangeByteRelease(UnsafeProxy unsafe, Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeByte(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static long compareAndExchangeLongRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static long compareAndExchangeLongRelease(UnsafeProxy unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeLong(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static Object compareAndExchangeReferenceRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static Object compareAndExchangeReferenceRelease(UnsafeProxy unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeReference(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static short compareAndExchangeShortRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static short compareAndExchangeShortRelease(UnsafeProxy unsafe, Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { return compareAndExchangeShort(unsafe, o, offset, expected, x, phosphorStackFrame); } //Generated from Phosphor template for weakCompareAndSet$methodTypeAcquire(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)Z @SuppressWarnings("unused") - public static boolean weakCompareAndSetIntAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetIntAcquire(UnsafeProxy unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetInt(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetByteAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetByteAcquire(UnsafeProxy unsafe, Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetByte(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetLongAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetLongAcquire(UnsafeProxy unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetLong(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetReferenceAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetReferenceAcquire(UnsafeProxy unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetReference(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetShortAcquire(UnsafeProxy unsafe, java.lang.Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetShortAcquire(UnsafeProxy unsafe, Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetShort(unsafe, o, offset, expected, x, phosphorStackFrame); } //Generated from Phosphor template for put$methodTypeOpaque(Ljava/lang/Object;JLPlaceHolder;)V @SuppressWarnings("unused") - public static void putByteOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, byte x, PhosphorStackFrame phosphorStackFrame) { + public static void putByteOpaque(UnsafeProxy unsafe, Object o, long offset, byte x, PhosphorStackFrame phosphorStackFrame) { putByteVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putIntOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, int x, PhosphorStackFrame phosphorStackFrame) { + public static void putIntOpaque(UnsafeProxy unsafe, Object o, long offset, int x, PhosphorStackFrame phosphorStackFrame) { putIntVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putLongOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, long x, PhosphorStackFrame phosphorStackFrame) { + public static void putLongOpaque(UnsafeProxy unsafe, Object o, long offset, long x, PhosphorStackFrame phosphorStackFrame) { putLongVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putFloatOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, float x, PhosphorStackFrame phosphorStackFrame) { + public static void putFloatOpaque(UnsafeProxy unsafe, Object o, long offset, float x, PhosphorStackFrame phosphorStackFrame) { putFloatVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putReferenceOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, Object x, PhosphorStackFrame phosphorStackFrame) { + public static void putReferenceOpaque(UnsafeProxy unsafe, Object o, long offset, Object x, PhosphorStackFrame phosphorStackFrame) { putReferenceVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putCharOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, char x, PhosphorStackFrame phosphorStackFrame) { + public static void putCharOpaque(UnsafeProxy unsafe, Object o, long offset, char x, PhosphorStackFrame phosphorStackFrame) { putCharVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putShortOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, short x, PhosphorStackFrame phosphorStackFrame) { + public static void putShortOpaque(UnsafeProxy unsafe, Object o, long offset, short x, PhosphorStackFrame phosphorStackFrame) { putShortVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putDoubleOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, double x, PhosphorStackFrame phosphorStackFrame) { + public static void putDoubleOpaque(UnsafeProxy unsafe, Object o, long offset, double x, PhosphorStackFrame phosphorStackFrame) { putDoubleVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putBooleanOpaque(UnsafeProxy unsafe, java.lang.Object o, long offset, boolean x, PhosphorStackFrame phosphorStackFrame) { + public static void putBooleanOpaque(UnsafeProxy unsafe, Object o, long offset, boolean x, PhosphorStackFrame phosphorStackFrame) { putBooleanVolatile(unsafe, o, offset, x, phosphorStackFrame); } //Generated from Phosphor template for compareAndSet$methodType(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)Z @SuppressWarnings("unused") - public static boolean compareAndSetInt(UnsafeProxy unsafe, java.lang.Object obj, long offset, int expected, int value, PhosphorStackFrame phosphorStackFrame) { + public static boolean compareAndSetInt(UnsafeProxy unsafe, Object obj, long offset, int expected, int value, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); boolean ret = false; @@ -788,7 +746,7 @@ public static boolean compareAndSetInt(UnsafeProxy unsafe, java.lang.Object obj, } @SuppressWarnings("unused") - public static boolean compareAndSetByte(UnsafeProxy unsafe, java.lang.Object obj, long offset, byte expected, byte value, PhosphorStackFrame phosphorStackFrame) { + public static boolean compareAndSetByte(UnsafeProxy unsafe, Object obj, long offset, byte expected, byte value, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); boolean ret = false; @@ -813,7 +771,7 @@ public static boolean compareAndSetByte(UnsafeProxy unsafe, java.lang.Object obj } @SuppressWarnings("unused") - public static boolean compareAndSetLong(UnsafeProxy unsafe, java.lang.Object obj, long offset, long expected, long value, PhosphorStackFrame phosphorStackFrame) { + public static boolean compareAndSetLong(UnsafeProxy unsafe, Object obj, long offset, long expected, long value, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); boolean ret = false; @@ -838,7 +796,7 @@ public static boolean compareAndSetLong(UnsafeProxy unsafe, java.lang.Object obj } @SuppressWarnings("unused") - public static boolean compareAndSetReference(UnsafeProxy unsafe, java.lang.Object obj, long offset, Object expected, Object value, PhosphorStackFrame phosphorStackFrame) { + public static boolean compareAndSetReference(UnsafeProxy unsafe, Object obj, long offset, Object expected, Object value, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); boolean ret = false; @@ -881,7 +839,7 @@ public static boolean compareAndSetReference(UnsafeProxy unsafe, java.lang.Objec } @SuppressWarnings("unused") - public static boolean compareAndSetShort(UnsafeProxy unsafe, java.lang.Object obj, long offset, short expected, short value, PhosphorStackFrame phosphorStackFrame) { + public static boolean compareAndSetShort(UnsafeProxy unsafe, Object obj, long offset, short expected, short value, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); boolean ret = false; @@ -907,7 +865,7 @@ public static boolean compareAndSetShort(UnsafeProxy unsafe, java.lang.Object ob //Generated from Phosphor template for put$methodType(Ljava/lang/Object;JLPlaceHolder;)V @SuppressWarnings("unused") - public static void putByte(UnsafeProxy unsafe, java.lang.Object obj, long offset, byte val, PhosphorStackFrame phosphorStackFrame) { + public static void putByte(UnsafeProxy unsafe, Object obj, long offset, byte val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putByte(((TaggedArray) obj).getVal(), offset, val); @@ -921,7 +879,7 @@ public static void putByte(UnsafeProxy unsafe, java.lang.Object obj, long offset } @SuppressWarnings("unused") - public static void putInt(UnsafeProxy unsafe, java.lang.Object obj, long offset, int val, PhosphorStackFrame phosphorStackFrame) { + public static void putInt(UnsafeProxy unsafe, Object obj, long offset, int val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putInt(((TaggedArray) obj).getVal(), offset, val); @@ -935,7 +893,7 @@ public static void putInt(UnsafeProxy unsafe, java.lang.Object obj, long offset, } @SuppressWarnings("unused") - public static void putLong(UnsafeProxy unsafe, java.lang.Object obj, long offset, long val, PhosphorStackFrame phosphorStackFrame) { + public static void putLong(UnsafeProxy unsafe, Object obj, long offset, long val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putLong(((TaggedArray) obj).getVal(), offset, val); @@ -949,7 +907,7 @@ public static void putLong(UnsafeProxy unsafe, java.lang.Object obj, long offset } @SuppressWarnings("unused") - public static void putFloat(UnsafeProxy unsafe, java.lang.Object obj, long offset, float val, PhosphorStackFrame phosphorStackFrame) { + public static void putFloat(UnsafeProxy unsafe, Object obj, long offset, float val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putFloat(((TaggedArray) obj).getVal(), offset, val); @@ -963,7 +921,7 @@ public static void putFloat(UnsafeProxy unsafe, java.lang.Object obj, long offse } @SuppressWarnings("unused") - public static void putReference(UnsafeProxy unsafe, java.lang.Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { + public static void putReference(UnsafeProxy unsafe, Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putReference(((TaggedArray) obj).getVal(), offset, val); @@ -992,7 +950,7 @@ public static void putReference(UnsafeProxy unsafe, java.lang.Object obj, long o } @SuppressWarnings("unused") - public static void putChar(UnsafeProxy unsafe, java.lang.Object obj, long offset, char val, PhosphorStackFrame phosphorStackFrame) { + public static void putChar(UnsafeProxy unsafe, Object obj, long offset, char val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putChar(((TaggedArray) obj).getVal(), offset, val); @@ -1006,7 +964,7 @@ public static void putChar(UnsafeProxy unsafe, java.lang.Object obj, long offset } @SuppressWarnings("unused") - public static void putShort(UnsafeProxy unsafe, java.lang.Object obj, long offset, short val, PhosphorStackFrame phosphorStackFrame) { + public static void putShort(UnsafeProxy unsafe, Object obj, long offset, short val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putShort(((TaggedArray) obj).getVal(), offset, val); @@ -1020,7 +978,7 @@ public static void putShort(UnsafeProxy unsafe, java.lang.Object obj, long offse } @SuppressWarnings("unused") - public static void putDouble(UnsafeProxy unsafe, java.lang.Object obj, long offset, double val, PhosphorStackFrame phosphorStackFrame) { + public static void putDouble(UnsafeProxy unsafe, Object obj, long offset, double val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putDouble(((TaggedArray) obj).getVal(), offset, val); @@ -1034,7 +992,7 @@ public static void putDouble(UnsafeProxy unsafe, java.lang.Object obj, long offs } @SuppressWarnings("unused") - public static void putBoolean(UnsafeProxy unsafe, java.lang.Object obj, long offset, boolean val, PhosphorStackFrame phosphorStackFrame) { + public static void putBoolean(UnsafeProxy unsafe, Object obj, long offset, boolean val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putBoolean(((TaggedArray) obj).getVal(), offset, val); @@ -1049,7 +1007,7 @@ public static void putBoolean(UnsafeProxy unsafe, java.lang.Object obj, long off //Generated from Phosphor template for put$methodTypeVolatile(Ljava/lang/Object;JLPlaceHolder;)V @SuppressWarnings("unused") - public static void putByteVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, byte val, PhosphorStackFrame phosphorStackFrame) { + public static void putByteVolatile(UnsafeProxy unsafe, Object obj, long offset, byte val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putByteVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1063,7 +1021,7 @@ public static void putByteVolatile(UnsafeProxy unsafe, java.lang.Object obj, lon } @SuppressWarnings("unused") - public static void putIntVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, int val, PhosphorStackFrame phosphorStackFrame) { + public static void putIntVolatile(UnsafeProxy unsafe, Object obj, long offset, int val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putIntVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1077,7 +1035,7 @@ public static void putIntVolatile(UnsafeProxy unsafe, java.lang.Object obj, long } @SuppressWarnings("unused") - public static void putLongVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, long val, PhosphorStackFrame phosphorStackFrame) { + public static void putLongVolatile(UnsafeProxy unsafe, Object obj, long offset, long val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putLongVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1091,7 +1049,7 @@ public static void putLongVolatile(UnsafeProxy unsafe, java.lang.Object obj, lon } @SuppressWarnings("unused") - public static void putFloatVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, float val, PhosphorStackFrame phosphorStackFrame) { + public static void putFloatVolatile(UnsafeProxy unsafe, Object obj, long offset, float val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putFloatVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1105,7 +1063,7 @@ public static void putFloatVolatile(UnsafeProxy unsafe, java.lang.Object obj, lo } @SuppressWarnings("unused") - public static void putReferenceVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { + public static void putReferenceVolatile(UnsafeProxy unsafe, Object obj, long offset, Object val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putReferenceVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1134,7 +1092,7 @@ public static void putReferenceVolatile(UnsafeProxy unsafe, java.lang.Object obj } @SuppressWarnings("unused") - public static void putCharVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, char val, PhosphorStackFrame phosphorStackFrame) { + public static void putCharVolatile(UnsafeProxy unsafe, Object obj, long offset, char val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putCharVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1148,7 +1106,7 @@ public static void putCharVolatile(UnsafeProxy unsafe, java.lang.Object obj, lon } @SuppressWarnings("unused") - public static void putShortVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, short val, PhosphorStackFrame phosphorStackFrame) { + public static void putShortVolatile(UnsafeProxy unsafe, Object obj, long offset, short val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putShortVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1162,7 +1120,7 @@ public static void putShortVolatile(UnsafeProxy unsafe, java.lang.Object obj, lo } @SuppressWarnings("unused") - public static void putDoubleVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, double val, PhosphorStackFrame phosphorStackFrame) { + public static void putDoubleVolatile(UnsafeProxy unsafe, Object obj, long offset, double val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putDoubleVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1176,7 +1134,7 @@ public static void putDoubleVolatile(UnsafeProxy unsafe, java.lang.Object obj, l } @SuppressWarnings("unused") - public static void putBooleanVolatile(UnsafeProxy unsafe, java.lang.Object obj, long offset, boolean val, PhosphorStackFrame phosphorStackFrame) { + public static void putBooleanVolatile(UnsafeProxy unsafe, Object obj, long offset, boolean val, PhosphorStackFrame phosphorStackFrame) { Taint valTaint = phosphorStackFrame.getArgTaint(3); if (obj instanceof TaggedArray) { unsafe.putBooleanVolatile(((TaggedArray) obj).getVal(), offset, val); @@ -1191,7 +1149,7 @@ public static void putBooleanVolatile(UnsafeProxy unsafe, java.lang.Object obj, //Generated from Phosphor template for compareAndExchange$methodType(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)LPlaceHolder; @SuppressWarnings("unused") - public static int compareAndExchangeInt(UnsafeProxy unsafe, java.lang.Object obj, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static int compareAndExchangeInt(UnsafeProxy unsafe, Object obj, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); int ret; @@ -1216,7 +1174,7 @@ public static int compareAndExchangeInt(UnsafeProxy unsafe, java.lang.Object obj } @SuppressWarnings("unused") - public static byte compareAndExchangeByte(UnsafeProxy unsafe, java.lang.Object obj, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static byte compareAndExchangeByte(UnsafeProxy unsafe, Object obj, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); byte ret; @@ -1241,7 +1199,7 @@ public static byte compareAndExchangeByte(UnsafeProxy unsafe, java.lang.Object o } @SuppressWarnings("unused") - public static long compareAndExchangeLong(UnsafeProxy unsafe, java.lang.Object obj, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static long compareAndExchangeLong(UnsafeProxy unsafe, Object obj, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); long ret; @@ -1266,7 +1224,7 @@ public static long compareAndExchangeLong(UnsafeProxy unsafe, java.lang.Object o } @SuppressWarnings("unused") - public static Object compareAndExchangeReference(UnsafeProxy unsafe, java.lang.Object obj, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static Object compareAndExchangeReference(UnsafeProxy unsafe, Object obj, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); Object ret = null; @@ -1306,7 +1264,7 @@ public static Object compareAndExchangeReference(UnsafeProxy unsafe, java.lang.O } @SuppressWarnings("unused") - public static short compareAndExchangeShort(UnsafeProxy unsafe, java.lang.Object obj, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static short compareAndExchangeShort(UnsafeProxy unsafe, Object obj, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { Taint valueTaint = phosphorStackFrame.getArgTaint(4); Taint retTaint = Taint.emptyTaint(); short ret; @@ -1332,7 +1290,7 @@ public static short compareAndExchangeShort(UnsafeProxy unsafe, java.lang.Object //Generated from Phosphor template for getAndSet$methodType(Ljava/lang/Object;JLPlaceHolder;)LPlaceHolder; @SuppressWarnings("unused") - public static int getAndSetInt(UnsafeProxy unsafe, java.lang.Object o, long offset, int newValue, PhosphorStackFrame phosphorStackFrame) { + public static int getAndSetInt(UnsafeProxy unsafe, Object o, long offset, int newValue, PhosphorStackFrame phosphorStackFrame) { int v; do { v = getIntVolatile(unsafe, o, offset, phosphorStackFrame); @@ -1341,7 +1299,7 @@ public static int getAndSetInt(UnsafeProxy unsafe, java.lang.Object o, long offs } @SuppressWarnings("unused") - public static byte getAndSetByte(UnsafeProxy unsafe, java.lang.Object o, long offset, byte newValue, PhosphorStackFrame phosphorStackFrame) { + public static byte getAndSetByte(UnsafeProxy unsafe, Object o, long offset, byte newValue, PhosphorStackFrame phosphorStackFrame) { byte v; do { v = getByteVolatile(unsafe, o, offset, phosphorStackFrame); @@ -1350,7 +1308,7 @@ public static byte getAndSetByte(UnsafeProxy unsafe, java.lang.Object o, long of } @SuppressWarnings("unused") - public static long getAndSetLong(UnsafeProxy unsafe, java.lang.Object o, long offset, long newValue, PhosphorStackFrame phosphorStackFrame) { + public static long getAndSetLong(UnsafeProxy unsafe, Object o, long offset, long newValue, PhosphorStackFrame phosphorStackFrame) { long v; do { v = getLongVolatile(unsafe, o, offset, phosphorStackFrame); @@ -1359,7 +1317,7 @@ public static long getAndSetLong(UnsafeProxy unsafe, java.lang.Object o, long of } @SuppressWarnings("unused") - public static Object getAndSetReference(UnsafeProxy unsafe, java.lang.Object o, long offset, Object newValue, PhosphorStackFrame phosphorStackFrame) { + public static Object getAndSetReference(UnsafeProxy unsafe, Object o, long offset, Object newValue, PhosphorStackFrame phosphorStackFrame) { Object v; do { v = getReferenceVolatile(unsafe, o, offset, phosphorStackFrame); @@ -1368,7 +1326,7 @@ public static Object getAndSetReference(UnsafeProxy unsafe, java.lang.Object o, } @SuppressWarnings("unused") - public static short getAndSetShort(UnsafeProxy unsafe, java.lang.Object o, long offset, short newValue, PhosphorStackFrame phosphorStackFrame) { + public static short getAndSetShort(UnsafeProxy unsafe, Object o, long offset, short newValue, PhosphorStackFrame phosphorStackFrame) { short v; do { v = getShortVolatile(unsafe, o, offset, phosphorStackFrame); @@ -1378,7 +1336,7 @@ public static short getAndSetShort(UnsafeProxy unsafe, java.lang.Object o, long //Generated from Phosphor template for get$methodType(Ljava/lang/Object;J)LPlaceHolder; @SuppressWarnings("unused") - public static byte getByte(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static byte getByte(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getByte(((TaggedArray) obj).getVal(), offset); @@ -1389,7 +1347,7 @@ public static byte getByte(UnsafeProxy unsafe, java.lang.Object obj, long offset } @SuppressWarnings("unused") - public static int getInt(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static int getInt(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getInt(((TaggedArray) obj).getVal(), offset); @@ -1400,7 +1358,7 @@ public static int getInt(UnsafeProxy unsafe, java.lang.Object obj, long offset, } @SuppressWarnings("unused") - public static long getLong(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static long getLong(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getLong(((TaggedArray) obj).getVal(), offset); @@ -1411,7 +1369,7 @@ public static long getLong(UnsafeProxy unsafe, java.lang.Object obj, long offset } @SuppressWarnings("unused") - public static float getFloat(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static float getFloat(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getFloat(((TaggedArray) obj).getVal(), offset); @@ -1422,7 +1380,7 @@ public static float getFloat(UnsafeProxy unsafe, java.lang.Object obj, long offs } @SuppressWarnings("unused") - public static Object getReference(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static Object getReference(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getReference(((TaggedArray) obj).getVal(), offset); @@ -1431,13 +1389,13 @@ public static Object getReference(UnsafeProxy unsafe, java.lang.Object obj, long if (pair != null && pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { offset = pair.wrappedFieldOffset; } - getTag(unsafe, obj, offset, phosphorStackFrame, RuntimeJDKInternalUnsafePropagator.SpecialAccessPolicy.NONE); + getTag(unsafe, obj, offset, phosphorStackFrame, SpecialAccessPolicy.NONE); return unsafe.getReference(obj, offset); } } @SuppressWarnings("unused") - public static char getChar(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static char getChar(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getChar(((TaggedArray) obj).getVal(), offset); @@ -1448,7 +1406,7 @@ public static char getChar(UnsafeProxy unsafe, java.lang.Object obj, long offset } @SuppressWarnings("unused") - public static short getShort(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static short getShort(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getShort(((TaggedArray) obj).getVal(), offset); @@ -1459,7 +1417,7 @@ public static short getShort(UnsafeProxy unsafe, java.lang.Object obj, long offs } @SuppressWarnings("unused") - public static double getDouble(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static double getDouble(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getDouble(((TaggedArray) obj).getVal(), offset); @@ -1470,7 +1428,7 @@ public static double getDouble(UnsafeProxy unsafe, java.lang.Object obj, long of } @SuppressWarnings("unused") - public static boolean getBoolean(UnsafeProxy unsafe, java.lang.Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { + public static boolean getBoolean(UnsafeProxy unsafe, Object obj, long offset, PhosphorStackFrame phosphorStackFrame) { if (obj instanceof TaggedArray) { phosphorStackFrame.returnTaint = ((TaggedArray) obj).getTaintOrEmpty(unsafeIndexFor(unsafe, (TaggedArray) obj, offset)); return unsafe.getBoolean(((TaggedArray) obj).getVal(), offset); @@ -1482,126 +1440,125 @@ public static boolean getBoolean(UnsafeProxy unsafe, java.lang.Object obj, long //Generated from Phosphor template for weakCompareAndSet$methodTypePlain(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)Z @SuppressWarnings("unused") - public static boolean weakCompareAndSetIntPlain(UnsafeProxy unsafe, java.lang.Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetIntPlain(UnsafeProxy unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetInt(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetBytePlain(UnsafeProxy unsafe, java.lang.Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetBytePlain(UnsafeProxy unsafe, Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetByte(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetLongPlain(UnsafeProxy unsafe, java.lang.Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetLongPlain(UnsafeProxy unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetLong(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetReferencePlain(UnsafeProxy unsafe, java.lang.Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetReferencePlain(UnsafeProxy unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetReference(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetShortPlain(UnsafeProxy unsafe, java.lang.Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetShortPlain(UnsafeProxy unsafe, Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetShort(unsafe, o, offset, expected, x, phosphorStackFrame); } //Generated from Phosphor template for weakCompareAndSet$methodTypeRelease(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)Z @SuppressWarnings("unused") - public static boolean weakCompareAndSetIntRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetIntRelease(UnsafeProxy unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetInt(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetByteRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetByteRelease(UnsafeProxy unsafe, Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetByte(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetLongRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetLongRelease(UnsafeProxy unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetLong(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetReferenceRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetReferenceRelease(UnsafeProxy unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetReference(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetShortRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetShortRelease(UnsafeProxy unsafe, Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetShort(unsafe, o, offset, expected, x, phosphorStackFrame); } //Generated from Phosphor template for weakCompareAndSet$methodType(Ljava/lang/Object;JLPlaceHolder;LPlaceHolder;)Z @SuppressWarnings("unused") - public static boolean weakCompareAndSetInt(UnsafeProxy unsafe, java.lang.Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetInt(UnsafeProxy unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetInt(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetByte(UnsafeProxy unsafe, java.lang.Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetByte(UnsafeProxy unsafe, Object o, long offset, byte expected, byte x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetByte(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetLong(UnsafeProxy unsafe, java.lang.Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetLong(UnsafeProxy unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetLong(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetReference(UnsafeProxy unsafe, java.lang.Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetReference(UnsafeProxy unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetReference(unsafe, o, offset, expected, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static boolean weakCompareAndSetShort(UnsafeProxy unsafe, java.lang.Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { + public static boolean weakCompareAndSetShort(UnsafeProxy unsafe, Object o, long offset, short expected, short x, PhosphorStackFrame phosphorStackFrame) { return compareAndSetShort(unsafe, o, offset, expected, x, phosphorStackFrame); } //Generated from Phosphor template for put$methodTypeRelease(Ljava/lang/Object;JLPlaceHolder;)V @SuppressWarnings("unused") - public static void putByteRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, byte x, PhosphorStackFrame phosphorStackFrame) { + public static void putByteRelease(UnsafeProxy unsafe, Object o, long offset, byte x, PhosphorStackFrame phosphorStackFrame) { putByteVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putIntRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, int x, PhosphorStackFrame phosphorStackFrame) { + public static void putIntRelease(UnsafeProxy unsafe, Object o, long offset, int x, PhosphorStackFrame phosphorStackFrame) { putIntVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putLongRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, long x, PhosphorStackFrame phosphorStackFrame) { + public static void putLongRelease(UnsafeProxy unsafe, Object o, long offset, long x, PhosphorStackFrame phosphorStackFrame) { putLongVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putFloatRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, float x, PhosphorStackFrame phosphorStackFrame) { + public static void putFloatRelease(UnsafeProxy unsafe, Object o, long offset, float x, PhosphorStackFrame phosphorStackFrame) { putFloatVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putReferenceRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, Object x, PhosphorStackFrame phosphorStackFrame) { + public static void putReferenceRelease(UnsafeProxy unsafe, Object o, long offset, Object x, PhosphorStackFrame phosphorStackFrame) { putReferenceVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putCharRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, char x, PhosphorStackFrame phosphorStackFrame) { + public static void putCharRelease(UnsafeProxy unsafe, Object o, long offset, char x, PhosphorStackFrame phosphorStackFrame) { putCharVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putShortRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, short x, PhosphorStackFrame phosphorStackFrame) { + public static void putShortRelease(UnsafeProxy unsafe, Object o, long offset, short x, PhosphorStackFrame phosphorStackFrame) { putShortVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putDoubleRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, double x, PhosphorStackFrame phosphorStackFrame) { + public static void putDoubleRelease(UnsafeProxy unsafe, Object o, long offset, double x, PhosphorStackFrame phosphorStackFrame) { putDoubleVolatile(unsafe, o, offset, x, phosphorStackFrame); } @SuppressWarnings("unused") - public static void putBooleanRelease(UnsafeProxy unsafe, java.lang.Object o, long offset, boolean x, PhosphorStackFrame phosphorStackFrame) { + public static void putBooleanRelease(UnsafeProxy unsafe, Object o, long offset, boolean x, PhosphorStackFrame phosphorStackFrame) { putBooleanVolatile(unsafe, o, offset, x, phosphorStackFrame); } - } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/Mask.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/Mask.java new file mode 100644 index 000000000..a97a30e60 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/Mask.java @@ -0,0 +1,24 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import java.lang.annotation.*; + +/** + * Indicates that calls to the annotated method should be added during instrumentation to + * replace calls to replace compatible method calls. + * Methods with this annotation must be static. + * A method call is compatible with a mask if the method being called is owned by the mask's specified + * {@link Mask#owner}, has the same name as the method with the mask annotation, and it descriptor is compatible + * with that the of method with the mask annotation. + * If {@link Mask#isStatic()} is true then a descriptor is compatible if it is equal to descriptor of the method with + * the mask annotation. + * Otherwise, a descriptor is compatible if it is equal to the descriptor of the method with the mask annotation with + * the first parameter removed. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(Masks.class) +public @interface Mask { + String owner(); + + boolean isStatic() default false; +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/Masks.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/Masks.java new file mode 100644 index 000000000..3a115f546 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/Masks.java @@ -0,0 +1,12 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Masks { + Mask[] value(); +} \ No newline at end of file diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/OffsetPair.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/OffsetPair.java new file mode 100644 index 000000000..f52be2b4d --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/OffsetPair.java @@ -0,0 +1,33 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +@SuppressWarnings("unused") + +public class OffsetPair { + + public final long origFieldOffset; + public final long wrappedFieldOffset; + public final long tagFieldOffset; + public final boolean isStatic; + + public OffsetPair(boolean isStatic, long origFieldOffset, long wrappedFieldOffset, long tagFieldOffset) { + this.isStatic = isStatic; + this.origFieldOffset = origFieldOffset; + this.tagFieldOffset = tagFieldOffset; + this.wrappedFieldOffset = wrappedFieldOffset; + } + + @Override + public boolean equals(Object other) { + return other instanceof OffsetPair && this.origFieldOffset == ((OffsetPair) other).origFieldOffset && this.isStatic == ((OffsetPair) other).isStatic; + } + + @Override + public int hashCode() { + return (int) (origFieldOffset ^ (origFieldOffset >>> 32)); + } + + @Override + public String toString() { + return String.format("{field @ %d -> tag @ %d, wrapper @ %d}", origFieldOffset, tagFieldOffset, wrappedFieldOffset); + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SpecialAccessPolicy.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SpecialAccessPolicy.java new file mode 100644 index 000000000..ef1107a28 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SpecialAccessPolicy.java @@ -0,0 +1,41 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +public enum SpecialAccessPolicy { + VOLATILE { + @Override + public void putObject(UnsafeAdapter unsafe, Object o, long offset, Object x) { + unsafe.putObjectVolatile(o, offset, x); + } + + @Override + public Object getObject(UnsafeAdapter unsafe, Object o, long offset) { + return unsafe.getObjectVolatile(o, offset); + } + }, + ORDERED { + @Override + public void putObject(UnsafeAdapter unsafe, Object o, long offset, Object x) { + unsafe.putOrderedObject(o, offset, x); + } + + @Override + public Object getObject(UnsafeAdapter unsafe, Object o, long offset) { + throw new UnsupportedOperationException(); + } + }, + NONE { + @Override + public void putObject(UnsafeAdapter unsafe, Object o, long offset, Object x) { + unsafe.putObject(o, offset, x); + } + + @Override + public Object getObject(UnsafeAdapter unsafe, Object o, long offset) { + return unsafe.getObject(o, offset); + } + }; + + public abstract void putObject(UnsafeAdapter unsafe, Object o, long offset, Object x); + + public abstract Object getObject(UnsafeAdapter unsafe, Object o, long offset); +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SunUnsafeAdapter.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SunUnsafeAdapter.java new file mode 100644 index 000000000..97b3f5437 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SunUnsafeAdapter.java @@ -0,0 +1,314 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; +import java.security.ProtectionDomain; + +public class SunUnsafeAdapter implements UnsafeAdapter { + private final Unsafe unsafe = Unsafe.getUnsafe(); + + @Override + public long getInvalidFieldOffset() { + return Unsafe.INVALID_FIELD_OFFSET; + } + + @SuppressWarnings("unused") + private static Class defineClass( + Unsafe unsafe, + String name, + byte[] b, + int off, + int len, + ClassLoader loader, + ProtectionDomain protectionDomain) { + return null; + } + + @Override + public Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches) { + return unsafe.defineAnonymousClass(hostClass, data, cpPatches); + } + + @Override + public Class defineClass( + String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain) { + // This will be fixed by the patcher + return defineClass(unsafe, name, b, off, len, loader, protectionDomain); + } + + @Override + public int getInt(Object o, long offset) { + return unsafe.getInt(o, offset); + } + + @Override + public void putInt(Object o, long offset, int x) { + unsafe.putInt(o, offset, x); + } + + @Override + public Object getObject(Object o, long offset) { + return unsafe.getObject(o, offset); + } + + @Override + public void putObject(Object o, long offset, Object x) { + unsafe.putObject(o, offset, x); + } + + @Override + public boolean getBoolean(Object o, long offset) { + return unsafe.getBoolean(o, offset); + } + + @Override + public void putBoolean(Object o, long offset, boolean x) { + unsafe.putBoolean(o, offset, x); + } + + @Override + public byte getByte(Object o, long offset) { + return unsafe.getByte(o, offset); + } + + @Override + public void putByte(Object o, long offset, byte x) { + unsafe.putByte(o, offset, x); + } + + @Override + public short getShort(Object o, long offset) { + return unsafe.getShort(o, offset); + } + + @Override + public void putShort(Object o, long offset, short x) { + unsafe.putShort(o, offset, x); + } + + @Override + public char getChar(Object o, long offset) { + return unsafe.getChar(o, offset); + } + + @Override + public void putChar(Object o, long offset, char x) { + unsafe.putChar(o, offset, x); + } + + @Override + public long getLong(Object o, long offset) { + return unsafe.getLong(o, offset); + } + + @Override + public void putLong(Object o, long offset, long x) { + unsafe.putLong(o, offset, x); + } + + @Override + public float getFloat(Object o, long offset) { + return unsafe.getFloat(o, offset); + } + + @Override + public void putFloat(Object o, long offset, float x) { + unsafe.putFloat(o, offset, x); + } + + @Override + public double getDouble(Object o, long offset) { + return unsafe.getDouble(o, offset); + } + + @Override + public void putDouble(Object o, long offset, double x) { + unsafe.putDouble(o, offset, x); + } + + @Override + public byte getByte(long address) { + return unsafe.getByte(address); + } + + @Override + public short getShort(long address) { + return unsafe.getShort(address); + } + + @Override + public char getChar(long address) { + return unsafe.getChar(address); + } + + @Override + public int getInt(long address) { + return unsafe.getInt(address); + } + + @Override + public long getLong(long address) { + return unsafe.getLong(address); + } + + @Override + public float getFloat(long address) { + return unsafe.getFloat(address); + } + + @Override + public double getDouble(long address) { + return unsafe.getDouble(address); + } + + @Override + public void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) { + unsafe.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes); + } + + @Override + public void copyMemory(long srcAddress, long destAddress, long bytes) { + unsafe.copyMemory(srcAddress, destAddress, bytes); + } + + @Override + public long objectFieldOffset(Field f) { + return unsafe.objectFieldOffset(f); + } + + @Override + public long staticFieldOffset(Field f) { + return unsafe.staticFieldOffset(f); + } + + @Override + public int arrayBaseOffset(Class arrayClass) { + return unsafe.arrayBaseOffset(arrayClass); + } + + @Override + public int arrayIndexScale(Class arrayClass) { + return unsafe.arrayIndexScale(arrayClass); + } + + @Override + public Object getObjectVolatile(Object o, long offset) { + return unsafe.getObjectVolatile(o, offset); + } + + @Override + public void putObjectVolatile(Object o, long offset, Object x) { + unsafe.putObjectVolatile(o, offset, x); + } + + @Override + public boolean compareAndSwapObject(Object obj, long offset, Object expected, Object value) { + return unsafe.compareAndSwapObject(obj, offset, expected, value); + } + + @Override + public int getIntVolatile(Object o, long offset) { + return unsafe.getIntVolatile(o, offset); + } + + @Override + public void putIntVolatile(Object o, long offset, int x) { + unsafe.putIntVolatile(o, offset, x); + } + + @Override + public boolean getBooleanVolatile(Object o, long offset) { + return unsafe.getBooleanVolatile(o, offset); + } + + @Override + public void putBooleanVolatile(Object o, long offset, boolean x) { + unsafe.putBooleanVolatile(o, offset, x); + } + + @Override + public byte getByteVolatile(Object o, long offset) { + return unsafe.getByteVolatile(o, offset); + } + + @Override + public void putByteVolatile(Object o, long offset, byte x) { + unsafe.putByteVolatile(o, offset, x); + } + + @Override + public short getShortVolatile(Object o, long offset) { + return unsafe.getShortVolatile(o, offset); + } + + @Override + public void putShortVolatile(Object o, long offset, short x) { + unsafe.putShortVolatile(o, offset, x); + } + + @Override + public char getCharVolatile(Object o, long offset) { + return unsafe.getCharVolatile(o, offset); + } + + @Override + public void putCharVolatile(Object o, long offset, char x) { + unsafe.putCharVolatile(o, offset, x); + } + + @Override + public long getLongVolatile(Object o, long offset) { + return unsafe.getLongVolatile(o, offset); + } + + @Override + public void putLongVolatile(Object o, long offset, long x) { + unsafe.putLongVolatile(o, offset, x); + } + + @Override + public float getFloatVolatile(Object o, long offset) { + return unsafe.getFloatVolatile(o, offset); + } + + @Override + public void putFloatVolatile(Object o, long offset, float x) { + unsafe.putFloatVolatile(o, offset, x); + } + + @Override + public double getDoubleVolatile(Object o, long offset) { + return unsafe.getDoubleVolatile(o, offset); + } + + @Override + public void putDoubleVolatile(Object o, long offset, double x) { + unsafe.putDoubleVolatile(o, offset, x); + } + + @Override + public void putOrderedObject(Object o, long offset, Object x) { + unsafe.putOrderedObject(o, offset, x); + } + + @Override + public boolean compareAndSwapInt(Object val, long offset, int expected, int value) { + return unsafe.compareAndSwapInt(val, offset, expected, value); + } + + @Override + public boolean compareAndSwapLong(Object val, long offset, long expected, long value) { + return unsafe.compareAndSwapLong(val, offset, expected, value); + } + + @Override + public void putOrderedInt(Object o, long offset, int x) { + unsafe.putOrderedInt(o, offset, x); + } + + @Override + public void putOrderedLong(Object o, long offset, long x) { + unsafe.putOrderedLong(o, offset, x); + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SunUnsafeMasker.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SunUnsafeMasker.java new file mode 100644 index 000000000..af4cc71a2 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/SunUnsafeMasker.java @@ -0,0 +1,360 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import edu.columbia.cs.psl.phosphor.Phosphor; +import edu.columbia.cs.psl.phosphor.runtime.MultiDArrayUtils; +import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; +import edu.columbia.cs.psl.phosphor.runtime.Taint; +import edu.columbia.cs.psl.phosphor.struct.TaggedArray; +import edu.columbia.cs.psl.phosphor.struct.TaggedReferenceArray; + +import java.security.ProtectionDomain; + +import static edu.columbia.cs.psl.phosphor.runtime.mask.UnsafeMaskerHelper.*; + +@SuppressWarnings("unused") +public final class SunUnsafeMasker { + @Mask(owner = "sun/misc/Unsafe") + public static Class defineAnonymousClass(Object unsafe, Class hostClass, byte[] data, Object[] cpPatches, + PhosphorStackFrame frame) { + byte[] instrumented = Phosphor.instrumentClassBytesAnonymous(data); + return ADAPTER.defineAnonymousClass(hostClass, instrumented, cpPatches); + } + + @Mask(owner = "sun/misc/Unsafe") + public static Class defineClass( + Object unsafe, + String name, + byte[] b, + int off, + int len, + ClassLoader loader, + ProtectionDomain protectionDomain, + PhosphorStackFrame frame) { + if (b != null && off >= 0 && len >= 0 && off + len <= b.length) { + byte[] buffer = new byte[len]; + System.arraycopy(b, off, buffer, 0, len); + byte[] instrumented = Phosphor.instrumentClassBytes(buffer); + return ADAPTER.defineClass(name, instrumented, 0, instrumented.length, loader, protectionDomain); + } + return ADAPTER.defineClass(name, b, off, len, loader, protectionDomain); + } + + @Mask(owner = "sun/misc/Unsafe") + public static Object getObject(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + return getObjectAndTag(o, offset, frame, SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static Object getObjectVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + return getObjectAndTag(o, offset, frame, SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static boolean compareAndSwapInt( + Object unsafe, Object o, long offset, int expected, int x, PhosphorStackFrame frame) { + boolean result = ADAPTER.compareAndSwapInt(unwrap(o), offset, expected, x); + if (result) { + putTag(o, offset, frame.getArgTaint(4), SpecialAccessPolicy.VOLATILE); + } + frame.returnTaint = Taint.emptyTaint(); + return result; + } + + @Mask(owner = "sun/misc/Unsafe") + public static boolean compareAndSwapLong( + Object unsafe, Object o, long offset, long expected, long x, PhosphorStackFrame frame) { + boolean result = ADAPTER.compareAndSwapLong(unwrap(o), offset, expected, x); + if (result) { + putTag(o, offset, frame.getArgTaint(4), SpecialAccessPolicy.VOLATILE); + } + frame.returnTaint = Taint.emptyTaint(); + return result; + } + + @Mask(owner = "sun/misc/Unsafe") + public static boolean compareAndSwapObject( + Object unsafe, Object o, long offset, Object expected, Object x, PhosphorStackFrame frame) { + frame.returnTaint = Taint.emptyTaint(); + boolean ret = false; + if (o instanceof TaggedReferenceArray) { + Taint valueTaint = frame.getArgTaint(4); + TaggedReferenceArray array = (TaggedReferenceArray) o; + ret = ADAPTER.compareAndSwapObject(array.val, offset, expected, x); + if (ret) { + if (array.getVal() != null && array.getVal().getClass().isArray()) { + int index = getTaggedArrayIndex((TaggedArray) o, offset); + array.setTaint(index, valueTaint); + } + } + } else { + OffsetPair pair = null; + boolean didCAS = false; + if (x instanceof TaggedArray || expected instanceof TaggedArray) { + // Need to be careful - maybe we are hitting a 1D primitive array field + if (o != null) { + pair = getOffsetPair(o, offset); + } + if (pair != null && pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + // We are doing a CAS on a 1d primitive array field + ret = ADAPTER.compareAndSwapObject( + o, offset, MultiDArrayUtils.unbox1DOrNull(expected), MultiDArrayUtils.unbox1DOrNull(x)); + didCAS = true; + } + } + if (!didCAS) { + // Either this is not a wrapped array, or we are storing it to the place where it should be stored + // without unwrapping + ret = ADAPTER.compareAndSwapObject(o, offset, expected, x); + if (pair == null && o != null) { + pair = getOffsetPair(o, offset); + } + } + if (pair != null && ret) { + if (pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + ADAPTER.putObjectVolatile(o, pair.tagFieldOffset, frame.getArgTaint(4)); + } + if (pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + ADAPTER.putObjectVolatile(o, pair.wrappedFieldOffset, x); + } + } + } + return ret; + } + + @Mask(owner = "sun/misc/Unsafe") + public static boolean getBoolean(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getBoolean(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static boolean getBooleanVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getBooleanVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static byte getByte(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getByte(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static byte getByteVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getByteVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static char getChar(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getChar(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static char getCharVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getCharVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static double getDouble(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getDouble(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static double getDoubleVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getDoubleVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static float getFloat(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getFloat(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static float getFloatVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getFloatVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static int getInt(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getInt(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static int getIntVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getIntVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static long getLong(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getLong(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static long getLongVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getLongVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static short getShort(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.NONE); + return ADAPTER.getShort(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static short getShortVolatile(Object unsafe, Object o, long offset, PhosphorStackFrame frame) { + frame.returnTaint = getTagPrimitive(o, offset, SpecialAccessPolicy.VOLATILE); + return ADAPTER.getShortVolatile(unwrap(o), offset); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void copyMemory( + Object unsafe, + Object srcBase, + long srcOffset, + Object destBase, + long destOffset, + long bytes, + PhosphorStackFrame frame) { + ADAPTER.copyMemory(unwrap(srcBase), srcOffset, unwrap(destBase), destOffset, bytes); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void copyMemory( + Object unsafe, long srcAddress, long destAddress, long length, PhosphorStackFrame frame) { + ADAPTER.copyMemory(srcAddress, destAddress, length); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putBoolean(Object unsafe, Object o, long offset, boolean x, PhosphorStackFrame frame) { + ADAPTER.putBoolean(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putBooleanVolatile(Object unsafe, Object o, long offset, boolean x, PhosphorStackFrame frame) { + ADAPTER.putBooleanVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putByte(Object unsafe, Object o, long offset, byte x, PhosphorStackFrame frame) { + ADAPTER.putByte(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putByteVolatile(Object unsafe, Object o, long offset, byte x, PhosphorStackFrame frame) { + ADAPTER.putByteVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putChar(Object unsafe, Object o, long offset, char x, PhosphorStackFrame frame) { + ADAPTER.putChar(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putCharVolatile(Object unsafe, Object o, long offset, char x, PhosphorStackFrame frame) { + ADAPTER.putCharVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putDouble(Object unsafe, Object o, long offset, double x, PhosphorStackFrame frame) { + ADAPTER.putDouble(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putDoubleVolatile(Object unsafe, Object o, long offset, double x, PhosphorStackFrame frame) { + ADAPTER.putDoubleVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putFloat(Object unsafe, Object o, long offset, float x, PhosphorStackFrame frame) { + ADAPTER.putFloat(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putFloatVolatile(Object unsafe, Object o, long offset, float x, PhosphorStackFrame frame) { + ADAPTER.putFloatVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putInt(Object unsafe, Object o, long offset, int x, PhosphorStackFrame frame) { + ADAPTER.putInt(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putIntVolatile(Object unsafe, Object o, long offset, int x, PhosphorStackFrame frame) { + ADAPTER.putIntVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putLong(Object unsafe, Object o, long offset, long x, PhosphorStackFrame frame) { + ADAPTER.putLong(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putLongVolatile(Object unsafe, Object o, long offset, long x, PhosphorStackFrame frame) { + ADAPTER.putLongVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putObject(Object unsafe, Object o, long offset, Object x, PhosphorStackFrame frame) { + putObjectAndTag(o, offset, x, frame, SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putObjectVolatile(Object unsafe, Object o, long offset, Object x, PhosphorStackFrame frame) { + putObjectAndTag(o, offset, x, frame, SpecialAccessPolicy.VOLATILE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putOrderedInt(Object unsafe, Object o, long offset, int x, PhosphorStackFrame frame) { + ADAPTER.putOrderedInt(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.ORDERED); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putOrderedLong(Object unsafe, Object o, long offset, long x, PhosphorStackFrame frame) { + ADAPTER.putOrderedLong(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.ORDERED); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putOrderedObject(Object unsafe, Object o, long offset, Object x, PhosphorStackFrame frame) { + putObjectAndTag(o, offset, x, frame, SpecialAccessPolicy.ORDERED); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putShort(Object unsafe, Object o, long offset, short x, PhosphorStackFrame frame) { + ADAPTER.putShort(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.NONE); + } + + @Mask(owner = "sun/misc/Unsafe") + public static void putShortVolatile(Object unsafe, Object o, long offset, short x, PhosphorStackFrame frame) { + ADAPTER.putShortVolatile(unwrap(o), offset, x); + UnsafeMaskerHelper.putTag(o, offset, frame.getArgTaint(3), SpecialAccessPolicy.VOLATILE); + } +} \ No newline at end of file diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeAdapter.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeAdapter.java new file mode 100644 index 000000000..963364aec --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeAdapter.java @@ -0,0 +1,124 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import java.lang.reflect.Field; +import java.security.ProtectionDomain; + +@SuppressWarnings("unused") +public interface UnsafeAdapter { + long getInvalidFieldOffset(); + + int getInt(Object o, long offset); + + void putInt(Object o, long offset, int x); + + boolean getBoolean(Object o, long offset); + + void putBoolean(Object o, long offset, boolean x); + + byte getByte(Object o, long offset); + + void putByte(Object o, long offset, byte x); + + short getShort(Object o, long offset); + + void putShort(Object o, long offset, short x); + + char getChar(Object o, long offset); + + void putChar(Object o, long offset, char x); + + long getLong(Object o, long offset); + + void putLong(Object o, long offset, long x); + + float getFloat(Object o, long offset); + + void putFloat(Object o, long offset, float x); + + double getDouble(Object o, long offset); + + void putDouble(Object o, long offset, double x); + + byte getByte(long address); + + short getShort(long address); + + char getChar(long address); + + int getInt(long address); + + long getLong(long address); + + float getFloat(long address); + + double getDouble(long address); + + void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); + + void copyMemory(long srcAddress, long destAddress, long bytes); + + long objectFieldOffset(Field f); + + long staticFieldOffset(Field f); + + int arrayBaseOffset(Class arrayClass); + + int arrayIndexScale(Class arrayClass); + + Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches); + + Class defineClass( + String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain); + + int getIntVolatile(Object o, long offset); + + void putIntVolatile(Object o, long offset, int x); + + boolean getBooleanVolatile(Object o, long offset); + + void putBooleanVolatile(Object o, long offset, boolean x); + + byte getByteVolatile(Object o, long offset); + + void putByteVolatile(Object o, long offset, byte x); + + short getShortVolatile(Object o, long offset); + + void putShortVolatile(Object o, long offset, short x); + + char getCharVolatile(Object o, long offset); + + void putCharVolatile(Object o, long offset, char x); + + long getLongVolatile(Object o, long offset); + + void putLongVolatile(Object o, long offset, long x); + + float getFloatVolatile(Object o, long offset); + + void putFloatVolatile(Object o, long offset, float x); + + double getDoubleVolatile(Object o, long offset); + + void putDoubleVolatile(Object o, long offset, double x); + + Object getObject(Object o, long offset); + + Object getObjectVolatile(Object o, long offset); + + void putObject(Object o, long offset, Object x); + + void putObjectVolatile(Object o, long offset, Object x); + + boolean compareAndSwapObject(Object obj, long offset, Object expected, Object value); + + void putOrderedObject(Object obj, long offset, Object val); + + boolean compareAndSwapInt(Object val, long offset, int expected, int value); + + boolean compareAndSwapLong(Object val, long offset, long expected, long value); + + void putOrderedInt(Object obj, long offset, int val); + + void putOrderedLong(Object obj, long offset, long val); +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeMaskerHelper.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeMaskerHelper.java new file mode 100644 index 000000000..25e912403 --- /dev/null +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeMaskerHelper.java @@ -0,0 +1,226 @@ +package edu.columbia.cs.psl.phosphor.runtime.mask; + +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.TaintUtils; +import edu.columbia.cs.psl.phosphor.runtime.MultiDArrayUtils; +import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; +import edu.columbia.cs.psl.phosphor.runtime.Taint; +import edu.columbia.cs.psl.phosphor.runtime.proxied.InstrumentedJREFieldHelper; +import edu.columbia.cs.psl.phosphor.struct.SinglyLinkedList; +import edu.columbia.cs.psl.phosphor.struct.TaggedArray; +import edu.columbia.cs.psl.phosphor.struct.TaggedReferenceArray; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * + * Utility method for ensuring that method calls from {@link jdk.internal.misc.Unsafe} and + * {@link sun.misc.Unsafe} that set or retrieve values from fields or array operate on both the + * original value and its associated taint tag. + */ +public class UnsafeMaskerHelper { + private UnsafeMaskerHelper() { + // Prevents this class from being instantiated + } + + public static final UnsafeAdapter ADAPTER = + Configuration.IS_JAVA_8 ? new SunUnsafeAdapter() : new JdkUnsafeAdapter(); + /** + * Used to disambiguate between a static field of a given type and an instance field of java.lang.Class + */ + private static long LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS = ADAPTER.getInvalidFieldOffset(); + + private static SinglyLinkedList getOffsetPairs(Class targetClazz) { + SinglyLinkedList list = new SinglyLinkedList<>(); + for (Class clazz = targetClazz; + clazz != null && !Object.class.equals(clazz); + clazz = clazz.getSuperclass()) { + for (Field field : clazz.getDeclaredFields()) { + try { + boolean isStatic = Modifier.isStatic(field.getModifiers()); + long fieldOffset = (isStatic ? ADAPTER.staticFieldOffset(field) : ADAPTER.objectFieldOffset(field)); + long tagOffset = getTagOffset(clazz, field, isStatic); + long wrapperOffset = getWrapperOffset(clazz, field, isStatic); + list.enqueue(new OffsetPair(isStatic, fieldOffset, wrapperOffset, tagOffset)); + } catch (Exception e) { + // + } + } + } + return list; + } + + private static long getTagOffset(Class clazz, Field field, boolean isStatic) { + try { + if (!field.getName().equals("SPECIES_DATA")) { + Field taintField = clazz.getField(field.getName() + TaintUtils.TAINT_FIELD); + if (Configuration.TAINT_TAG_OBJ_CLASS.equals(taintField.getType())) { + return (isStatic ? ADAPTER.staticFieldOffset(taintField) : ADAPTER.objectFieldOffset(taintField)); + } + } + } catch (Exception e) { + // + } + return ADAPTER.getInvalidFieldOffset(); + } + + private static long getWrapperOffset(Class clazz, Field field, boolean isStatic) { + if (field.getType().isArray()) { + try { + Field wrapperField = clazz.getField(field.getName() + TaintUtils.TAINT_WRAPPER_FIELD); + if (TaggedArray.class.isAssignableFrom(wrapperField.getType())) { + return (isStatic + ? ADAPTER.staticFieldOffset(wrapperField) + : ADAPTER.objectFieldOffset(wrapperField)); + } + } catch (Exception e) { + // + } + } + return ADAPTER.getInvalidFieldOffset(); + } + + public static OffsetPair getOffsetPair(Object o, long offset) { + try { + Class cl = null; + boolean isStatic = false; + if (o == null) { + return null; + } else if (o instanceof Class) { + // We MIGHT be accessing a static field of this class, in which case we should take + // the offset from *this* class instance (o). + // But we might also be accessing an instance field of the type Class, in which case we want to use + // the class' class. + if (LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS == ADAPTER.getInvalidFieldOffset()) { + findLastInstanceFieldOnJavaLangClass(); + } + if (offset > LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS) { + /* We are not accessing an instance field of java.lang.Class, hence, we must be accessing + * a static field of type (Class) o */ + cl = (Class) o; + isStatic = true; + } + /* Otherwise, we are accessing an instance field of java.lang.Class */ + } + if (cl == null) { + cl = o.getClass(); + } + if (InstrumentedJREFieldHelper.get$$PHOSPHOR_OFFSET_CACHE(cl) == null) { + InstrumentedJREFieldHelper.set$$PHOSPHOR_OFFSET_CACHE(cl, getOffsetPairs(cl)); + } + for (OffsetPair pair : InstrumentedJREFieldHelper.get$$PHOSPHOR_OFFSET_CACHE(cl)) { + if (pair.origFieldOffset == offset && pair.isStatic == isStatic) { + return pair; + } + } + return null; + } catch (Exception e) { + return null; + } + } + + private static void findLastInstanceFieldOnJavaLangClass() { + for (Field field : Class.class.getDeclaredFields()) { + try { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + long fieldOffset = ADAPTER.objectFieldOffset(field); + if (fieldOffset > LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS) { + LAST_INSTANCE_OFFSET_JAVA_LANG_CLASS = fieldOffset; + } + } catch (Exception e) { + // + } + } + } + + public static int getTaggedArrayIndex(TaggedArray array, long offset) { + Class clazz = array.getVal().getClass(); + long baseOffset = ADAPTER.arrayBaseOffset(clazz); + long scale = ADAPTER.arrayIndexScale(clazz); + // Calculate the index based off the offset + return (int) ((offset - baseOffset) / scale); + } + + public static void putTag(Object o, long offset, Taint valTaint, SpecialAccessPolicy policy) { + if (o instanceof TaggedArray) { + TaggedArray array = (TaggedArray) o; + int index = getTaggedArrayIndex(array, offset); + array.setTaint(index, valTaint); + } else { + OffsetPair pair = getOffsetPair(o, offset); + if (pair != null && pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + policy.putObject(ADAPTER, o, pair.tagFieldOffset, valTaint); + } + } + } + + public static Taint getTag(Object o, long offset, SpecialAccessPolicy policy) { + OffsetPair pair = getOffsetPair(o, offset); + if (pair != null && pair.tagFieldOffset != ADAPTER.getInvalidFieldOffset()) { + return (Taint) policy.getObject(ADAPTER, o, pair.tagFieldOffset); + } + return Taint.emptyTaint(); + } + + public static Taint getTagPrimitive(Object o, long offset, SpecialAccessPolicy policy) { + if (o instanceof TaggedArray) { + TaggedArray array = (TaggedArray) o; + int index = getTaggedArrayIndex(array, offset); + return array.getTaintOrEmpty(index); + } else { + return getTag(o, offset, policy); + } + } + + public static Object getObjectAndTag(Object o, long offset, PhosphorStackFrame frame, SpecialAccessPolicy policy) { + if (o instanceof TaggedReferenceArray) { + TaggedReferenceArray array = (TaggedReferenceArray) o; + int index = getTaggedArrayIndex(array, offset); + // Propagate the offset taint tag to the index + return array.get(index, frame.getArgTaint(1), frame); + } else { + // Is this trying to return a field that is wrapped? + OffsetPair pair = getOffsetPair(o, offset); + // TODO check + if (pair != null && pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + offset = pair.wrappedFieldOffset; + } + frame.returnTaint = getTag(o, offset, policy); + return policy.getObject(ADAPTER, o, offset); + } + } + + public static Object unwrap(Object object) { + return object instanceof TaggedArray ? ((TaggedArray) object).getVal() : object; + } + + public static void putObjectAndTag( + Object o, long offset, Object x, PhosphorStackFrame frame, SpecialAccessPolicy policy) { + if (o instanceof TaggedReferenceArray) { + TaggedReferenceArray array = (TaggedReferenceArray) o; + int index = getTaggedArrayIndex(array, offset); + array.set(index, x, frame.getArgTaint(3)); + } else { + OffsetPair pair = getOffsetPair(o, offset); + if (pair != null) { + if (pair.tagFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + Object x1 = frame.getArgTaint(3); + policy.putObject(ADAPTER, o, pair.tagFieldOffset, x1); + } + if (pair.wrappedFieldOffset != UnsafeProxy.INVALID_FIELD_OFFSET) { + policy.putObject(ADAPTER, o, pair.wrappedFieldOffset, x); + Object x1 = MultiDArrayUtils.unbox1DOrNull(x); + policy.putObject(ADAPTER, o, offset, x1); + } else { + policy.putObject(ADAPTER, o, offset, x); + } + } else { + Object x1 = MultiDArrayUtils.unbox1DOrNull(x); + policy.putObject(ADAPTER, o, offset, x1); + } + } + } +} diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/UnsafeProxy.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeProxy.java similarity index 99% rename from Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/UnsafeProxy.java rename to Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeProxy.java index a2f98c7a0..d741a3452 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/jdk/unsupported/UnsafeProxy.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/mask/UnsafeProxy.java @@ -1,4 +1,4 @@ -package edu.columbia.cs.psl.phosphor.runtime.jdk.unsupported; +package edu.columbia.cs.psl.phosphor.runtime.mask; import java.lang.reflect.Field; import java.security.ProtectionDomain; diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/proxied/InstrumentedJREFieldHelper.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/proxied/InstrumentedJREFieldHelper.java index 5281dffb3..a77b08bd0 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/proxied/InstrumentedJREFieldHelper.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/proxied/InstrumentedJREFieldHelper.java @@ -1,7 +1,7 @@ package edu.columbia.cs.psl.phosphor.runtime.proxied; import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; -import edu.columbia.cs.psl.phosphor.runtime.RuntimeJDKInternalUnsafePropagator; +import edu.columbia.cs.psl.phosphor.runtime.mask.OffsetPair; import edu.columbia.cs.psl.phosphor.runtime.Taint; import edu.columbia.cs.psl.phosphor.struct.SinglyLinkedList; import edu.columbia.cs.psl.phosphor.struct.TaggedByteArray; @@ -47,11 +47,11 @@ public static byte[] getvalue(String str) { throw _crash(); } - public static SinglyLinkedList get$$PHOSPHOR_OFFSET_CACHE(Class cl) { + public static SinglyLinkedList get$$PHOSPHOR_OFFSET_CACHE(Class cl) { throw _crash(); } - public static void set$$PHOSPHOR_OFFSET_CACHE(Class cl, SinglyLinkedList offsetPairs) { + public static void set$$PHOSPHOR_OFFSET_CACHE(Class cl, SinglyLinkedList offsetPairs) { throw _crash(); } diff --git a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/TaggedArray.java b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/TaggedArray.java index bd2191890..aa4f8a2a1 100644 --- a/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/TaggedArray.java +++ b/Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/TaggedArray.java @@ -85,7 +85,10 @@ public Taint getTaintOrEmpty(int idx) { } public void setTaint(int idx, Taint valTaint) { - if(taints == null) { + if (Taint.isEmpty(valTaint) && taints == null) { + return; + } + if (taints == null) { taints = new Taint[getLength()]; } taints[idx] = valTaint; diff --git a/README.md b/README.md index b28da1e92..e8c2081ab 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Remaining tasks for this branch before promotion: A JDK can be downloaded from [Oracle](https://www.oracle.com/java/technologies/downloads/) or the [Adoptium Working Group](https://adoptium.net/temurin/releases/). 3. Set the JAVA_HOME environmental variable to the path of this JDK installation. - On Linux and Mac this can be done by running `export JAVA_HOME=`, where <PATH-TO-JDK> is the path + On Linux and Mac, this can be done by running `export JAVA_HOME=`, where <PATH-TO-JDK> is the path of the JDK installation. 4. Ensure that you have installed Apache Maven 3.6.0+. Directions for [downloading](https://maven.apache.org/download.cgi) @@ -161,7 +161,6 @@ If you choose, you can also use the Phosphor driver to instrument you applicatio application. This step is optional; Phosphor will dynamically instrument any classes not already instrumented at runtime as they are loaded by the JVM. -If you plan to run these classes in a Java 8 JVM, you **must** add `-java8` to the list of options passed to the driver. If you want to Phosphor to cache classes that are dynamically instrumented, then you can add the Java option `-DphosphorCacheDirectory=` when running your application, where <CACHE-DIRECTORY> is the file path to the directory where Phosphor should store the cached instrumented class files. diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 46b9f620a..fef0f7c5e 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -19,7 +19,6 @@ false ${edu.gmu.swe.phosphor:Phosphor:jar} ${edu.gmu.swe.phosphor:phosphor-driver:jar} - false @@ -108,15 +107,6 @@ - - java8 - - 1.8 - - - true - - dacapo @@ -148,7 +138,6 @@ ${phosphor.jar} ${phosphor.driver.jar} ${data.flow.java}/bin/java - ${isJava8} diff --git a/integration-tests/runDacapo.sh b/integration-tests/runDacapo.sh index 9e2e030a3..359c1a26c 100755 --- a/integration-tests/runDacapo.sh +++ b/integration-tests/runDacapo.sh @@ -4,7 +4,6 @@ readonly BUILD_DIR=$1 readonly PHOSPHOR_JAR=$2 readonly DRIVER_JAR=$3 readonly INST_JVM=$4 -readonly IS_JAVA_8=$5 readonly DACAPO_DIR=$BUILD_DIR/dacapo readonly INST_DACAPO_DIR=$BUILD_DIR/dacapo-inst readonly BENCHMARKS=(avrora fop h2 jython luindex pmd sunflow xalan) @@ -24,11 +23,6 @@ if [ ! -d "$DACAPO_DIR" ]; then fi cd "$BUILD_DIR" -phosphor_args="" -if [ "$IS_JAVA_8" == "true" ]; then - phosphor_args="-java8" -fi - if [ ! -d "$INST_DACAPO_DIR" ]; then echo "Creating data flow instrumented dacapo" java -Xmx8g -jar "$DRIVER_JAR" -q -forceUnboxAcmpEq -withEnumsByValue $phosphor_args "$DACAPO_DIR" "$INST_DACAPO_DIR" diff --git a/phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/PhosphorInstrumentation.java b/phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/PhosphorInstrumentation.java index 809485056..6ff8082fb 100644 --- a/phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/PhosphorInstrumentation.java +++ b/phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/PhosphorInstrumentation.java @@ -1,8 +1,11 @@ package edu.columbia.cs.psl.phosphor.driver; -import edu.columbia.cs.psl.phosphor.*; -import edu.columbia.cs.psl.phosphor.agent.InstrumentUtil; +import edu.columbia.cs.psl.phosphor.Configuration; +import edu.columbia.cs.psl.phosphor.PCLoggingTransformer; +import edu.columbia.cs.psl.phosphor.Phosphor; +import edu.columbia.cs.psl.phosphor.PhosphorOption; import edu.columbia.cs.psl.phosphor.agent.EmbeddedPhosphorPatcher; +import edu.columbia.cs.psl.phosphor.agent.InstrumentUtil; import edu.columbia.cs.psl.phosphor.instrumenter.TaintTrackingClassVisitor; import edu.columbia.cs.psl.phosphor.org.apache.commons.cli.CommandLine; @@ -46,9 +49,7 @@ public void initialize(CommandLine line) throws IOException { transformer = new PCLoggingTransformer(); classPathElements = new HashSet<>(); classPathElements.add(InstrumentUtil.getClassPathElement(Phosphor.class)); - configurationClasses.stream() - .map(InstrumentUtil::getClassPathElement) - .forEach(classPathElements::add); + configurationClasses.stream().map(InstrumentUtil::getClassPathElement).forEach(classPathElements::add); } @Override @@ -63,7 +64,7 @@ public byte[] apply(byte[] classFileBuffer) { @Override public Patcher createPatcher(Function entryLocator) { - String path = "/java.base/jdk/internal/misc/Unsafe.class"; + String path = "/java.base/jdk/internal/misc/Unsafe.class"; EmbeddedPhosphorPatcher patcher = new EmbeddedPhosphorPatcher(entryLocator.apply(path)); return patcher::patch; }