├── .github └── workflows │ └── main.yml ├── .gitignore ├── LICENSE.md ├── Phosphor ├── pom.xml └── src │ ├── main │ ├── java │ │ └── edu │ │ │ └── columbia │ │ │ └── cs │ │ │ └── psl │ │ │ └── phosphor │ │ │ ├── BasicSourceSinkManager.java │ │ │ ├── ClassNodeCache.java │ │ │ ├── ClassSupertypeReadingTransformer.java │ │ │ ├── Configuration.java │ │ │ ├── DebugPrinter.java │ │ │ ├── HackyClassWriter.java │ │ │ ├── InstrumentationAdaptor.java │ │ │ ├── LocalVariablePhosphorInstructionInfo.java │ │ │ ├── LoopHeaderInfo.java │ │ │ ├── NullSourceSinkManager.java │ │ │ ├── PCLoggingTransformer.java │ │ │ ├── Phosphor.java │ │ │ ├── PhosphorBaseTransformer.java │ │ │ ├── PhosphorInstructionInfo.java │ │ │ ├── PhosphorOption.java │ │ │ ├── SourceSinkManager.java │ │ │ ├── SourceSinkTransformer.java │ │ │ ├── TaintUtils.java │ │ │ ├── TransformationCache.java │ │ │ ├── agent │ │ │ ├── AsmPatcher.java │ │ │ ├── ConfigurationEmbeddingMV.java │ │ │ ├── EmbeddedPhosphorPatcher.java │ │ │ ├── InstrumentUtil.java │ │ │ ├── InstrumentedJREProxyGenerator.java │ │ │ ├── PhosphorAgent.java │ │ │ └── PhosphorPatcher.java │ │ │ ├── control │ │ │ ├── AbstractControlFlowPropagationPolicy.java │ │ │ ├── ControlFlowAnalyzer.java │ │ │ ├── ControlFlowManager.java │ │ │ ├── ControlFlowPropagationPolicy.java │ │ │ ├── ControlFlowStack.java │ │ │ ├── ControlStackInitializingMV.java │ │ │ ├── ControlStackRestoringMV.java │ │ │ ├── LocalVariable.java │ │ │ ├── OpcodesUtil.java │ │ │ ├── graph │ │ │ │ ├── BaseControlFlowGraphCreator.java │ │ │ │ ├── BasicBlock.java │ │ │ │ ├── ControlFlowGraphCreator.java │ │ │ │ ├── DummyBasicBlock.java │ │ │ │ ├── EntryPoint.java │ │ │ │ ├── ExitPoint.java │ │ │ │ ├── FlowGraph.java │ │ │ │ ├── FlowGraphBuilder.java │ │ │ │ ├── InstructionTextifier.java │ │ │ │ └── SimpleBasicBlock.java │ │ │ ├── standard │ │ │ │ ├── BranchEnd.java │ │ │ │ ├── BranchStart.java │ │ │ │ ├── ControlMethodRecord.java │ │ │ │ ├── ExceptionHandlerEnd.java │ │ │ │ ├── ExceptionHandlerStart.java │ │ │ │ ├── ExecuteForceControlStore.java │ │ │ │ ├── ForceControlStore.java │ │ │ │ ├── NoControlFlowAnalyzer.java │ │ │ │ ├── NoControlFlowPropagationPolicy.java │ │ │ │ ├── StandardControlFlowAnalyzer.java │ │ │ │ ├── StandardControlFlowManager.java │ │ │ │ ├── StandardControlFlowPropagationPolicy.java │ │ │ │ ├── StandardControlFlowStack.java │ │ │ │ ├── UnthrownException.java │ │ │ │ └── UnthrownExceptionCheck.java │ │ │ └── type │ │ │ │ ├── TypeInterpreter.java │ │ │ │ └── TypeValue.java │ │ │ ├── instrumenter │ │ │ ├── ClinitRetransformClassVisitor.java │ │ │ ├── ClinitRetransformMV.java │ │ │ ├── DataAndControlFlowTagFactory.java │ │ │ ├── DefaultTaintCheckingMethodVisitor.java │ │ │ ├── EclipseCompilerCV.java │ │ │ ├── InstOrUninstChoosingMV.java │ │ │ ├── InvokedViaInstrumentation.java │ │ │ ├── JettyBufferUtilCV.java │ │ │ ├── LegacyClassFixer.java │ │ │ ├── LocalVariableAdder.java │ │ │ ├── LocalVariableManager.java │ │ │ ├── MethodArgReindexer.java │ │ │ ├── MethodRecord.java │ │ │ ├── OgnlUtilCV.java │ │ │ ├── PhosphorTextifier.java │ │ │ ├── PopOptimizingMV.java │ │ │ ├── PowerMockUtilCV.java │ │ │ ├── PrimitiveArrayAnalyzer.java │ │ │ ├── PrimitiveBoxingFixer.java │ │ │ ├── ReflectionHidingMV.java │ │ │ ├── SerializationFixingCV.java │ │ │ ├── SinkTaintingMV.java │ │ │ ├── SourceSinkTaintingClassVisitor.java │ │ │ ├── SourceTaintingMV.java │ │ │ ├── SpecialOpcodeRemovingMV.java │ │ │ ├── TaintAdapter.java │ │ │ ├── TaintLoadCoercer.java │ │ │ ├── TaintMethodRecord.java │ │ │ ├── TaintPassingMV.java │ │ │ ├── TaintTagFactory.java │ │ │ ├── TaintTagFieldCastMV.java │ │ │ ├── TaintThroughTaintingMV.java │ │ │ ├── TaintTrackingClassVisitor.java │ │ │ ├── UninstrumentedCompatMV.java │ │ │ ├── analyzer │ │ │ │ ├── BasicArrayInterpreter.java │ │ │ │ ├── BasicArrayValue.java │ │ │ │ ├── InstMethodSinkInterpreter.java │ │ │ │ ├── MergeAwareInterpreter.java │ │ │ │ ├── NeverNullArgAnalyzerAdapter.java │ │ │ │ ├── PFrame.java │ │ │ │ ├── PhosphorOpcodeIgnoringAnalyzer.java │ │ │ │ ├── ReferenceArrayTarget.java │ │ │ │ ├── SinkableArrayValue.java │ │ │ │ └── TaggedValue.java │ │ │ └── asm │ │ │ │ ├── OffsetPreservingClassReader.java │ │ │ │ └── OffsetPreservingLabel.java │ │ │ ├── org │ │ │ └── objectweb │ │ │ │ └── asm │ │ │ │ ├── SignatureReWriter.java │ │ │ │ ├── analysis │ │ │ │ ├── Analyzer.java │ │ │ │ └── Subroutine.java │ │ │ │ ├── commons │ │ │ │ ├── OurJSRInlinerAdapter.java │ │ │ │ ├── OurLocalVariablesSorter.java │ │ │ │ └── OurSerialVersionUIDAdder.java │ │ │ │ └── tree │ │ │ │ └── FrameNode.java │ │ │ ├── runtime │ │ │ ├── ArrayHelper.java │ │ │ ├── ArrayReflectionMasker.java │ │ │ ├── AutoTaintLabel.java │ │ │ ├── CharacterUtils.java │ │ │ ├── DerivedTaintListener.java │ │ │ ├── HardcodedBypassStore.java │ │ │ ├── JDKUnsafeStubGenerator.java │ │ │ ├── MultiDArrayUtils.java │ │ │ ├── MultiTainter.java │ │ │ ├── NativeHelper.java │ │ │ ├── NonModifiableClassException.java │ │ │ ├── PhosphorStackFrame.java │ │ │ ├── ReflectionMasker.java │ │ │ ├── RuntimeBoxUnboxPropagator.java │ │ │ ├── RuntimeJDKInternalUnsafePropagator.java │ │ │ ├── StringUtils.java │ │ │ ├── Taint.java │ │ │ ├── TaintInstrumented.java │ │ │ ├── TaintSinkError.java │ │ │ ├── TaintSourceWrapper.java │ │ │ ├── UninstrumentedTaintSentinel.java │ │ │ ├── jdk │ │ │ │ └── unsupported │ │ │ │ │ ├── RuntimeSunMiscUnsafePropagator.java │ │ │ │ │ └── UnsafeProxy.java │ │ │ └── proxied │ │ │ │ ├── InstrumentedJREFieldHelper.java │ │ │ │ └── InstrumentedJREMethodHelper.java │ │ │ └── struct │ │ │ ├── BitSet.java │ │ │ ├── EnqueuedTaint.java │ │ │ ├── ExceptionalTaintData.java │ │ │ ├── Field.java │ │ │ ├── GarbageCollectedArrayList.java │ │ │ ├── IntObjectAMT.java │ │ │ ├── IntSinglyLinkedList.java │ │ │ ├── LinkedList.java │ │ │ ├── MaybeThrownException.java │ │ │ ├── MethodInvoke.java │ │ │ ├── PowerSetTree.java │ │ │ ├── RankPool.java │ │ │ ├── RankedElement.java │ │ │ ├── SinglyLinkedList.java │ │ │ ├── TaggedArray.java │ │ │ ├── TaggedBooleanArray.java │ │ │ ├── TaggedByteArray.java │ │ │ ├── TaggedCharArray.java │ │ │ ├── TaggedDoubleArray.java │ │ │ ├── TaggedFloatArray.java │ │ │ ├── TaggedIntArray.java │ │ │ ├── TaggedLongArray.java │ │ │ ├── TaggedReferenceArray.java │ │ │ ├── TaggedShortArray.java │ │ │ ├── Tainted.java │ │ │ ├── TaintedWithObjTag.java │ │ │ ├── WeakIdentityHashMap.java │ │ │ └── harmony │ │ │ └── util │ │ │ ├── AbstractCollection.java │ │ │ ├── AbstractList.java │ │ │ ├── AbstractMap.java │ │ │ ├── AbstractQueue.java │ │ │ ├── AbstractSequentialList.java │ │ │ ├── AbstractSet.java │ │ │ ├── AbstractStringBuilder.java │ │ │ ├── ArrayList.java │ │ │ ├── Arrays.java │ │ │ ├── Collection.java │ │ │ ├── Collections.java │ │ │ ├── Comparator.java │ │ │ ├── ConcurrentHashMap.java │ │ │ ├── ConcurrentMap.java │ │ │ ├── Dictionary.java │ │ │ ├── EnumMap.java │ │ │ ├── EnumSet.java │ │ │ ├── Enumeration.java │ │ │ ├── HashMap.java │ │ │ ├── HashSet.java │ │ │ ├── Hashtable.java │ │ │ ├── HugeEnumSet.java │ │ │ ├── IdentityHashMap.java │ │ │ ├── LinkedHashMap.java │ │ │ ├── LinkedHashSet.java │ │ │ ├── LinkedList.java │ │ │ ├── List.java │ │ │ ├── ListIterator.java │ │ │ ├── Map.java │ │ │ ├── MapEntry.java │ │ │ ├── MiniEnumSet.java │ │ │ ├── Pair.java │ │ │ ├── PriorityQueue.java │ │ │ ├── Queue.java │ │ │ ├── RandomAccess.java │ │ │ ├── Scanner.java │ │ │ ├── Set.java │ │ │ ├── SortedMap.java │ │ │ ├── SortedSet.java │ │ │ ├── Stack.java │ │ │ ├── StringBuffer.java │ │ │ ├── StringBuilder.java │ │ │ ├── StringTokenizer.java │ │ │ ├── TreeMap.java │ │ │ ├── TreeSet.java │ │ │ ├── UUID.java │ │ │ ├── Vector.java │ │ │ └── WeakHashMap.java │ └── resources │ │ └── unsafe-patterns │ └── test │ └── java │ └── edu │ └── columbia │ └── cs │ └── psl │ ├── phosphor │ ├── InstrumenterTest.java │ ├── TaintUtilsTest.java │ ├── TaintUtilsTestMethods.java │ ├── control │ │ ├── graph │ │ │ ├── ControlFlowGraphLoopsTest.java │ │ │ ├── ControlFlowGraphSuccessorsTest.java │ │ │ ├── ControlFlowGraphTestMethods.java │ │ │ ├── ControlFlowGraphTestUtil.java │ │ │ ├── ExceptionalControlFlowGraphTest.java │ │ │ ├── ExceptionalControlFlowTestMethods.java │ │ │ └── FlowGraphTest.java │ │ └── type │ │ │ ├── TypeInterpreterTest.java │ │ │ └── TypeInterpreterTestMethods.java │ └── struct │ │ ├── BitSetTest.java │ │ ├── IntObjectAMTTest.java │ │ ├── IntSinglyLinkedListTest.java │ │ ├── LazyArrayObjTagsTest.java │ │ ├── PowerSetTreeTaintTest.java │ │ ├── PowerSetTreeTest.java │ │ └── TaintTest.java │ └── test │ └── phopshor │ └── RuntimeAnnotation.java ├── README.md ├── checkstyle-configuration.xml ├── deployment ├── deploy.sh ├── settings.xml └── signingkey.asc.enc ├── generateMultiANewArray.php ├── integration-tests ├── README.md ├── pom.xml ├── runDacapo.sh └── src │ └── test │ ├── java │ ├── Foo.java │ ├── de │ │ └── ecspride │ │ │ ├── BaseClass.java │ │ │ ├── BaseClass2.java │ │ │ ├── ConcreteClass.java │ │ │ ├── ConcreteClass2.java │ │ │ ├── DataStore.java │ │ │ ├── Datacontainer.java │ │ │ ├── General.java │ │ │ ├── ReflectiveClass.java │ │ │ ├── VarA.java │ │ │ └── VarB.java │ └── edu │ │ └── columbia │ │ └── cs │ │ └── psl │ │ ├── phosphor │ │ └── util │ │ │ └── IgnoredTestUtil.java │ │ └── test │ │ └── phosphor │ │ ├── AnnotationInstCase.java │ │ ├── ArrayArgWrapperObjTagITCase.java │ │ ├── ArrayLengthObjTagITCase.java │ │ ├── ArrayOptimizationObjTagITCase.java │ │ ├── AtomicReferenceArrayObjTagITCase.java │ │ ├── AutoTaintConstructorsImplicitITCase.java │ │ ├── AutoTaintConstructorsObjTagITCase.java │ │ ├── AutoTaintImplicitITCase.java │ │ ├── AutoTaintObjTagITCase.java │ │ ├── BaseMultiTaintClass.java │ │ ├── BasePhosphorTest.java │ │ ├── CharacterCodePointObjTagITCase.java │ │ ├── ClassWithLargeMethod.java │ │ ├── DeepImplicitITCase.java │ │ ├── DroidBenchImplicitITCase.java │ │ ├── DroidBenchObjTagITCase.java │ │ ├── EnumObjTagITCase.java │ │ ├── ExceptionImplicitITCase.java │ │ ├── ExceptionalFlowImplicitITCase.java │ │ ├── FakeEnumTest.java │ │ ├── GeneralImplicitITCase.java │ │ ├── GetSetTaintObjTagITCase.java │ │ ├── InheritedAutoTaintObjTagITCase.java │ │ ├── LambdaImplicitITCase.java │ │ ├── LambdaObjTagITCase.java │ │ ├── LocalVariableInstCase.java │ │ ├── MultiArrayUninstInstCase.java │ │ ├── OrImplicitITCase.java │ │ ├── OverTaintingImplicitITCase.java │ │ ├── ParameterAnnotationObjTagITCase.java │ │ ├── PartiallyInstrumentedClass.java │ │ ├── PopAllCalledImplicitITCase.java │ │ ├── RuntimeAnnotationExample.java │ │ ├── RuntimeAnnotationImplicitITCase.java │ │ ├── StringConcatObjTagITCase.java │ │ ├── runtime │ │ ├── ArrayCopyImplicitITCase.java │ │ ├── ArrayReflectionImplicitITCase.java │ │ ├── ArrayReflectionObjTagITCase.java │ │ ├── CharacterPropagationImplicitITCase.java │ │ ├── CharacterPropagationObjTagITCase.java │ │ ├── FieldHolderBaseTest.java │ │ ├── FieldReflectionImplicitITCase.java │ │ ├── FieldReflectionObjTagITCase.java │ │ ├── GetCharsObjTagITCase.java │ │ ├── MaskingBaseTest.java │ │ ├── MethodHolder.java │ │ ├── MethodReflectionImplicitITCase.java │ │ ├── MethodReflectionObjTagITCase.java │ │ ├── ParsePrimitiveImplicitITCase.java │ │ ├── ParsePrimitiveObjTagITCase.java │ │ ├── PrimitiveSupplier.java │ │ ├── ReflectionImplicitITCase.java │ │ ├── ReflectionObjTagITCase.java │ │ ├── SerializationImplicitITCase.java │ │ ├── SerializationObjTagITCase.java │ │ ├── UnsafeImplicitITCase.java │ │ └── UnsafeObjTagITCase.java │ │ └── util │ │ └── TaintThroughExample.java │ └── resources │ ├── taint-sinks │ ├── taint-sources │ ├── taint-through │ └── test-methods ├── phosphor-driver ├── pom.xml └── src │ └── main │ └── java │ ├── edu │ └── columbia │ │ └── cs │ │ └── psl │ │ └── phosphor │ │ └── driver │ │ ├── DeletingFileVisitor.java │ │ ├── InstrumentJLinkPlugin.java │ │ ├── Instrumentation.java │ │ ├── Instrumenter.java │ │ ├── JLinkInvoker.java │ │ ├── JLinkRegistrationAgent.java │ │ ├── Packer.java │ │ ├── Patcher.java │ │ ├── PhosphorInstrumentation.java │ │ ├── PhosphorInstrumenter.java │ │ └── ResourcePoolPacker.java │ └── module-info.java ├── phosphor-instrument-maven-plugin ├── pom.xml └── src │ └── main │ └── java │ └── edu │ └── columbia │ └── cs │ └── psl │ └── phosphor │ └── plugin │ └── InstrumentMojo.java ├── phosphor-microbench ├── pom.xml └── src │ └── main │ └── java │ └── edu │ └── columbia │ └── cs │ └── psl │ └── phosphor │ └── bench │ └── set │ ├── AddBenchmark.java │ ├── CopyBenchmark.java │ └── UnionBenchmark.java └── pom.xml /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build Phosphor, run the integration test suite 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build-and-test: 7 | runs-on: self-hosted 8 | env: 9 | JAVA_HOME: /usr/lib/jvm/java-11-openjdk-amd64 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | java: [ '8', '11', '16' ] 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Build Phosphor 17 | run: mvn -B -ntp -DskipTests install 18 | - name: Setup java 19 | uses: actions/setup-java@v3 20 | with: 21 | distribution: 'temurin' 22 | java-version: ${{ matrix.java }} 23 | - name: Run tests 24 | run: mvn install -ntp -Pdacapo -pl :integration-tests 25 | deploy: 26 | runs-on: self-hosted 27 | needs: build-and-test 28 | if: github.ref == 'refs/heads/master' 29 | steps: 30 | - uses: actions/checkout@v3 31 | - name: Deploy 32 | env: 33 | DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} 34 | DEPLOY_KEY_PASSPHRASE: ${{ secrets.DEPLOY_KEY_PASSPHRASE }} 35 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 36 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 37 | JAVA_HOME: /usr/lib/jvm/java-11-openjdk-amd64 38 | run: bash ./deployment/deploy.sh 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | experiments/ 3 | /target 4 | .project 5 | .classpath 6 | .settings 7 | dacapo 8 | test.tmp.out 9 | 10 | # Remove dynamically generated pom 11 | dependency-reduced-pom.xml 12 | 13 | # Ignore vim .swp files 14 | **/*.swp 15 | 16 | 17 | # Ignore intellij files 18 | *.iml 19 | .idea 20 | 21 | # Compiled class files 22 | **/target/* 23 | *.class 24 | 25 | # Package files 26 | *.jar 27 | *.war 28 | *.ear 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Programming Systems Lab @ Columbia University 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/ClassSupertypeReadingTransformer.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.HashMap; 4 | import org.objectweb.asm.ClassReader; 5 | import org.objectweb.asm.ClassVisitor; 6 | import org.objectweb.asm.tree.ClassNode; 7 | 8 | import java.security.ProtectionDomain; 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | 12 | /* Creates a class node containing information about its supertypes for each loaded class. */ 13 | public class ClassSupertypeReadingTransformer extends PhosphorBaseTransformer { 14 | 15 | /* For classes that get loaded before Instrumenter is initialized, store those records here. */ 16 | public static HashMap classNodes = new HashMap<>(); 17 | 18 | @Override 19 | public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer, boolean isAnonymousClassDefinition) { 20 | ClassReader cr = new ClassReader(classfileBuffer); 21 | cr.accept(new ClassVisitor(Configuration.ASM_VERSION) { 22 | @Override 23 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 24 | super.visit(version, access, name, signature, superName, interfaces); 25 | ClassNode cn = new ClassNode(); 26 | cn.name = name; 27 | cn.superName = superName; 28 | cn.interfaces = new ArrayList<>(Arrays.asList(interfaces)); 29 | if(classNodes == null) { 30 | ClassNodeCache.classes.put(name, cn); 31 | } else { 32 | classNodes.put(name, cn); 33 | } 34 | } 35 | }, ClassReader.SKIP_CODE); 36 | return null; 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/HackyClassWriter.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import org.objectweb.asm.ClassReader; 4 | import org.objectweb.asm.ClassWriter; 5 | 6 | public final class HackyClassWriter extends ClassWriter { 7 | 8 | public HackyClassWriter(ClassReader classReader, int flags) { 9 | super(classReader, flags); 10 | } 11 | 12 | @Override 13 | protected String getCommonSuperClass(String type1, String type2) { 14 | if (Phosphor.RUNTIME_INST) { 15 | return "java/lang/Object"; 16 | } 17 | Class clazz1; 18 | Class clazz2; 19 | try { 20 | clazz1 = Class.forName(type1.replace('/', '.'), false, Phosphor.bigLoader); 21 | clazz2 = Class.forName(type2.replace('/', '.'), false, Phosphor.bigLoader); 22 | } catch (Throwable t) { 23 | return "java/lang/Object"; 24 | } 25 | if (clazz1.isAssignableFrom(clazz2)) { 26 | return type1; 27 | } else if (clazz2.isAssignableFrom(clazz1)) { 28 | return type2; 29 | } 30 | if (clazz1.isInterface() || clazz2.isInterface()) { 31 | return "java/lang/Object"; 32 | } else { 33 | do { 34 | clazz1 = clazz1.getSuperclass(); 35 | } while (!clazz1.isAssignableFrom(clazz2)); 36 | return clazz1.getName().replace('.', '/'); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/InstrumentationAdaptor.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.NonModifiableClassException; 4 | 5 | public interface InstrumentationAdaptor { 6 | void addTransformer(PhosphorBaseTransformer transformer); 7 | 8 | Class[] getAllLoadedClasses(); 9 | 10 | void addTransformer(PhosphorBaseTransformer transformer, boolean canRedefineClasses); 11 | 12 | void retransformClasses(Class clazz) throws NonModifiableClassException; 13 | } 14 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/LocalVariablePhosphorInstructionInfo.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import org.objectweb.asm.Type; 4 | 5 | public interface LocalVariablePhosphorInstructionInfo extends PhosphorInstructionInfo { 6 | int getLocalVariableIndex(); 7 | 8 | LocalVariablePhosphorInstructionInfo setLocalVariableIndex(int index); 9 | 10 | Type getType(); 11 | } 12 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/LoopHeaderInfo.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | public enum LoopHeaderInfo implements PhosphorInstructionInfo { 4 | LOOP_HEADER 5 | } 6 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/NullSourceSinkManager.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | public class NullSourceSinkManager extends SourceSinkManager { 4 | 5 | @Override 6 | public boolean isSourceOrSinkOrTaintThrough(Class clazz) { 7 | return false; 8 | } 9 | 10 | @Override 11 | public boolean isSource(String str) { 12 | return false; 13 | } 14 | 15 | @Override 16 | public boolean isSink(String str) { 17 | return false; 18 | } 19 | 20 | @Override 21 | public Object getLabel(String str) { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isTaintThrough(String str) { 27 | return false; 28 | } 29 | 30 | @Override 31 | public String getBaseSink(String str) { 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorBaseTransformer.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import java.security.ProtectionDomain; 4 | 5 | /* Provides appropriate phosphor tagged versions of transform. */ 6 | public abstract class PhosphorBaseTransformer { 7 | 8 | public static boolean INITED = false; 9 | protected static int isBusyTransforming = 0; 10 | 11 | public abstract byte[] transform( 12 | ClassLoader loader, 13 | final String className2, 14 | Class classBeingRedefined, 15 | ProtectionDomain protectionDomain, 16 | byte[] classfileBuffer, 17 | boolean isAnonymousClassDefinition); 18 | 19 | public byte[] signalAndTransform( 20 | ClassLoader loader, 21 | String className, 22 | Class classBeingRedefined, 23 | ProtectionDomain protectionDomain, 24 | byte[] classFileBuffer, 25 | boolean isAnonymousClassDefinition) { 26 | try { 27 | synchronized (PhosphorBaseTransformer.class) { 28 | isBusyTransforming++; 29 | } 30 | return transform( 31 | loader, 32 | className, 33 | classBeingRedefined, 34 | protectionDomain, 35 | classFileBuffer, 36 | isAnonymousClassDefinition); 37 | } finally { 38 | synchronized (PhosphorBaseTransformer.class) { 39 | isBusyTransforming--; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/PhosphorInstructionInfo.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | /** 4 | * Used as the constant value of LdcInsnNodes that are temporary instructions added by Phosphor to pass information 5 | * between different phases of the instrumentation process. 6 | */ 7 | public interface PhosphorInstructionInfo { 8 | } -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/SourceSinkManager.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import org.objectweb.asm.tree.MethodInsnNode; 4 | 5 | public abstract class SourceSinkManager { 6 | public abstract boolean isSourceOrSinkOrTaintThrough(Class clazz); 7 | 8 | public abstract boolean isSource(String str); 9 | 10 | public abstract boolean isTaintThrough(String str); 11 | 12 | public Object getLabel(String owner, String name, String taintedDesc) { 13 | return getLabel(owner + "." + name + TaintUtils.getOriginalDescrptor(taintedDesc)); 14 | } 15 | 16 | public abstract Object getLabel(String str); 17 | 18 | public boolean isSource(MethodInsnNode insn) { 19 | return isSource(insn.owner + "." + insn.name + insn.desc); 20 | } 21 | 22 | public abstract boolean isSink(String str); 23 | 24 | public boolean isSink(MethodInsnNode insn) { 25 | return isSink(insn.owner + "." + insn.name + insn.desc); 26 | } 27 | 28 | public boolean isTaintThrough(String owner, String name, String taintedDesc) { 29 | return isTaintThrough(owner + "." + name + TaintUtils.getOriginalDescrptor(taintedDesc)); 30 | } 31 | 32 | public boolean isSink(String owner, String name, String taintedDesc) { 33 | return isSink(owner + "." + name + TaintUtils.getOriginalDescrptor(taintedDesc)); 34 | } 35 | 36 | public boolean isSource(String owner, String name, String taintedDesc) { 37 | return isSource(owner + "." + name + TaintUtils.getOriginalDescrptor(taintedDesc)); 38 | } 39 | 40 | /* 41 | * Returns the name of sink method from which the specified method inherited its 42 | * sink property or null if the specified 43 | * method is not a sink. 44 | */ 45 | public String getBaseSink(String owner, String name, String taintedDesc) { 46 | return getBaseSink(owner + "." + name + TaintUtils.getOriginalDescrptor(taintedDesc)); 47 | } 48 | 49 | public abstract String getBaseSink(String str); 50 | } 51 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/AsmPatcher.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.agent; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; 5 | import org.objectweb.asm.*; 6 | 7 | public class AsmPatcher extends ClassVisitor { 8 | private static final String ASM_PREFIX = "edu/columbia/cs/psl/phosphor/org/objectweb/asm/"; 9 | private static final Type OBJECT_TYPE = Type.getType(Object.class); 10 | 11 | public AsmPatcher(ClassWriter cw) { 12 | super(Configuration.ASM_VERSION, cw); 13 | } 14 | 15 | @Override 16 | public MethodVisitor visitMethod( 17 | int access, String name, String descriptor, String signature, String[] exceptions) { 18 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 19 | return new MethodVisitor(api, mv) { 20 | 21 | @Override 22 | public void visitMethodInsn( 23 | int opcode, String owner, String name, String descriptor, boolean isInterface) { 24 | super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); 25 | // Ensure that the return value is unwrapped if necessary 26 | if (owner.startsWith("java/") && OBJECT_TYPE.equals(Type.getReturnType(descriptor))) { 27 | TaintMethodRecord.TAINTED_REFERENCE_ARRAY_UNWRAP.delegateVisit(mv); 28 | } 29 | } 30 | }; 31 | } 32 | 33 | public static byte[] patch(byte[] classFileBuffer) { 34 | ClassReader cr = new ClassReader(classFileBuffer); 35 | ClassWriter cw = new ClassWriter(cr, 0); 36 | ClassVisitor cv = new AsmPatcher(cw); 37 | cr.accept(cv, 0); 38 | return cw.toByteArray(); 39 | } 40 | 41 | public static boolean isApplicable(String className) { 42 | return className.startsWith(ASM_PREFIX); 43 | } 44 | } -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/ConfigurationEmbeddingMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.agent; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; 5 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Set; 6 | import org.objectweb.asm.MethodVisitor; 7 | import org.objectweb.asm.Opcodes; 8 | import org.objectweb.asm.Type; 9 | 10 | import java.lang.reflect.Field; 11 | import java.lang.reflect.Modifier; 12 | 13 | import static org.objectweb.asm.Opcodes.*; 14 | 15 | /** 16 | * Embeds the current values for the field of {@link Configuration} into the class file for {@link Configuration}. 17 | */ 18 | public class ConfigurationEmbeddingMV extends MethodVisitor { 19 | public ConfigurationEmbeddingMV(MethodVisitor mv) { 20 | super(Configuration.ASM_VERSION, mv); 21 | } 22 | 23 | @Override 24 | public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { 25 | if (opcode == Opcodes.PUTSTATIC) { 26 | try { 27 | Field f = Configuration.class.getField(name); 28 | f.setAccessible(true); 29 | if (Modifier.isPublic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers())) { 30 | replaceValue(Type.getType(descriptor), f.get(null)); 31 | } 32 | } catch (ReflectiveOperationException e) { 33 | throw new RuntimeException("Failed to access field owned by " + Configuration.class, e); 34 | } 35 | } 36 | super.visitFieldInsn(opcode, owner, name, descriptor); 37 | } 38 | 39 | public void replaceValue(Type type, Object newValue) { 40 | switch (type.getSort()) { 41 | case Type.VOID: 42 | case Type.ARRAY: 43 | case Type.METHOD: 44 | return; 45 | } 46 | // Pop the original value 47 | super.visitInsn(type.getSize() == 1 ? POP : POP2); 48 | // Push the new value 49 | if (type.getSort() != Type.OBJECT || newValue instanceof String) { 50 | super.visitLdcInsn(newValue); 51 | } else if (newValue == null) { 52 | super.visitInsn(ACONST_NULL); 53 | } else if (newValue instanceof Class) { 54 | mv.visitLdcInsn(Type.getType((Class) newValue)); 55 | } else if (newValue instanceof Set) { 56 | Set set = (Set) newValue; 57 | newInstance(newValue.getClass()); 58 | for (Object element : set) { 59 | super.visitInsn(DUP); 60 | super.visitLdcInsn(element); 61 | TaintMethodRecord.SET_ADD.delegateVisit(mv); 62 | super.visitInsn(POP); 63 | } 64 | } else { 65 | newInstance(newValue.getClass()); 66 | } 67 | } 68 | 69 | private void newInstance(Class clazz) { 70 | try { 71 | clazz.getConstructor(); 72 | } catch (NoSuchMethodException e) { 73 | throw new IllegalArgumentException("Public, zero-argument constructor not found for: " + clazz); 74 | } 75 | String className = Type.getInternalName(clazz); 76 | super.visitTypeInsn(Opcodes.NEW, className); 77 | super.visitInsn(DUP); 78 | super.visitMethodInsn(INVOKESPECIAL, className, "", "()V", false); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/agent/PhosphorPatcher.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.agent; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.util.zip.CRC32; 7 | import java.util.zip.ZipEntry; 8 | import java.util.zip.ZipInputStream; 9 | import java.util.zip.ZipOutputStream; 10 | 11 | public class PhosphorPatcher { 12 | public static void main(String[] args) throws IOException { 13 | File archive = new File(args[0]); 14 | File temp = InstrumentUtil.createTemporaryFile("patch-", ".jar"); 15 | try (ZipInputStream zin = new ZipInputStream(Files.newInputStream(archive.toPath())); 16 | ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(temp.toPath()))) { 17 | for (ZipEntry entry; (entry = zin.getNextEntry()) != null; ) { 18 | byte[] content = InstrumentUtil.readAllBytes(zin); 19 | if (entry.getName().endsWith(".class")) { 20 | content = patch(entry.getName(), content); 21 | } 22 | writeEntry(zos, entry, content); 23 | } 24 | } 25 | InstrumentUtil.deleteFile(archive); 26 | if (!temp.renameTo(archive)) { 27 | throw new IOException("Failed to move patched JAR: " + temp); 28 | } 29 | } 30 | 31 | private static byte[] patch(String name, byte[] classFileBuffer) { 32 | if (AsmPatcher.isApplicable(name)) { 33 | return AsmPatcher.patch(classFileBuffer); 34 | } 35 | return classFileBuffer; 36 | } 37 | 38 | private static void writeEntry(ZipOutputStream zos, ZipEntry entry, byte[] content) throws IOException { 39 | ZipEntry outEntry = new ZipEntry(entry.getName()); 40 | outEntry.setMethod(entry.getMethod()); 41 | if (entry.getMethod() == ZipEntry.STORED) { 42 | // Uncompressed entries require entry size and CRC 43 | outEntry.setSize(content.length); 44 | outEntry.setCompressedSize(content.length); 45 | CRC32 crc = new CRC32(); 46 | crc.update(content, 0, content.length); 47 | outEntry.setCrc(crc.getValue()); 48 | } 49 | zos.putNextEntry(outEntry); 50 | zos.write(content); 51 | zos.closeEntry(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/AbstractControlFlowPropagationPolicy.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | import edu.columbia.cs.psl.phosphor.instrumenter.LocalVariableManager; 5 | import edu.columbia.cs.psl.phosphor.instrumenter.analyzer.NeverNullArgAnalyzerAdapter; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | public abstract class AbstractControlFlowPropagationPolicy implements ControlFlowPropagationPolicy { 9 | 10 | /** 11 | * The analyzer used to annotate control flow information is the method being visited. 12 | */ 13 | protected final T flowAnalyzer; 14 | 15 | /** 16 | * Visitor to which instruction visiting is delegated. 17 | */ 18 | protected MethodVisitor delegate; 19 | 20 | /** 21 | * Tracks the current stack and local variable bindings. 22 | */ 23 | protected NeverNullArgAnalyzerAdapter analyzer; 24 | 25 | /** 26 | * Manager that handles freeing and allocating local variables. 27 | */ 28 | protected LocalVariableManager localVariableManager; 29 | 30 | public AbstractControlFlowPropagationPolicy(T flowAnalyzer) { 31 | this.flowAnalyzer = flowAnalyzer; 32 | } 33 | 34 | @Override 35 | public T getFlowAnalyzer() { 36 | return flowAnalyzer; 37 | } 38 | 39 | @Override 40 | public void initialize(MethodVisitor delegate, LocalVariableManager localVariableManager, NeverNullArgAnalyzerAdapter analyzer) { 41 | this.delegate = delegate; 42 | this.localVariableManager = localVariableManager; 43 | this.analyzer = analyzer; 44 | } 45 | 46 | @Override 47 | public void initializeLocalVariables(MethodVisitor mv) { 48 | 49 | } 50 | 51 | @Override 52 | public void visitingMaxs() { 53 | 54 | } 55 | 56 | @Override 57 | public void preparingFrame() { 58 | 59 | } 60 | 61 | @Override 62 | public void poppingFrame(MethodVisitor mv) { 63 | 64 | } 65 | 66 | @Override 67 | public LocalVariable[] createdLocalVariables() { 68 | return new LocalVariable[0]; 69 | } 70 | 71 | @Override 72 | public void visitingIncrement(int var, int shadowVar) { 73 | 74 | } 75 | 76 | @Override 77 | public void visitingLocalVariableStore(int opcode, int var) { 78 | 79 | } 80 | 81 | @Override 82 | public void visitingArrayStore(int opcode) { 83 | 84 | } 85 | 86 | @Override 87 | public void visitingArrayLoad(int opcode) { 88 | 89 | } 90 | 91 | @Override 92 | public void visitingFieldStore(int opcode, String owner, String name, String descriptor) { 93 | 94 | } 95 | 96 | @Override 97 | public void visitingInstanceFieldLoad(String owner, String name, String descriptor) { 98 | 99 | } 100 | 101 | @Override 102 | public void onMethodExit(int opcode) { 103 | 104 | } 105 | 106 | @Override 107 | public void visitingPhosphorInstructionInfo(PhosphorInstructionInfo info) { 108 | 109 | } 110 | 111 | @Override 112 | public void visitingInstanceOf() { 113 | 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/ControlFlowAnalyzer.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | import org.objectweb.asm.tree.LdcInsnNode; 5 | import org.objectweb.asm.tree.MethodNode; 6 | 7 | /** 8 | * Annotates a MethodNode's instruction list by inserting {@link LdcInsnNode LdcInsnNode} nodes containing 9 | * {@link PhosphorInstructionInfo PhosphorInstructionInfo} constants. These PhosphorInstructionInfo constants are used 10 | * to pass information to a {@link ControlFlowPropagationPolicy ControlFlowPropagationPolicy}. 11 | */ 12 | public interface ControlFlowAnalyzer { 13 | void annotate(String owner, MethodNode methodNode); 14 | } 15 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/ControlFlowManager.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | public interface ControlFlowManager { 7 | 8 | Class getControlStackClass(); 9 | 10 | void visitCreateStack(MethodVisitor mv, boolean disabled); 11 | 12 | ControlFlowStack getStack(boolean disabled); 13 | 14 | /** 15 | * @param access the access flags of the method 16 | * @param owner the internal name of the owner class of the method 17 | * @param name the name of the method 18 | * @param descriptor the descriptor of the method 19 | * @return a new ControlFlowPropagationPolicy for the specified method 20 | */ 21 | ControlFlowPropagationPolicy createPropagationPolicy(int access, String owner, String name, 22 | String descriptor); 23 | 24 | boolean isIgnoredFromControlTrack(String className, String methodName); 25 | 26 | /** 27 | * @param className the slash-separated, fully qualified name of a class (e.g., java/lang/Short) 28 | * @return true if the class with the specified name should not be instrumented by Phosphor 29 | */ 30 | default boolean isIgnoredClass(String className) { 31 | return false; 32 | } 33 | 34 | /** 35 | * Returns whether a class with the specified name is used by Phosphor for "internal" tainting 36 | * (e.g., {@link MultiTainter}. Calls to methods in internal tainting classes from instrumented classes are 37 | * remapped to the appropriate "$$PHOSPHORTAGGED" version even if the internal tainting class is not instrumented 38 | * by Phosphor. This requires internal tainting classes to provide instrumented versions of any method that may be 39 | * invoked by a classes that is instrumented by Phosphor. 40 | * 41 | * @param className the name of class being checking 42 | * @return true if a class with the specified name is used by Phosphor for internal tainting 43 | */ 44 | default boolean isInternalTaintingClass(String className) { 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/ControlFlowStack.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control; 2 | 3 | import edu.columbia.cs.psl.phosphor.instrumenter.InvokedViaInstrumentation; 4 | import edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord; 5 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 6 | 7 | import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.*; 8 | 9 | public abstract class ControlFlowStack { 10 | 11 | /** 12 | * 0 if copying and pushing tags is enabled for this stack, otherwise > 0 13 | */ 14 | private int disabled; 15 | 16 | public ControlFlowStack(boolean disabled) { 17 | this.disabled = disabled ? 1 : 0; 18 | } 19 | 20 | @InvokedViaInstrumentation(record = TaintMethodRecord.CONTROL_STACK_ENABLE) 21 | public void enable() { 22 | disabled--; 23 | } 24 | 25 | @InvokedViaInstrumentation(record = TaintMethodRecord.CONTROL_STACK_DISABLE) 26 | public void disable() { 27 | disabled++; 28 | } 29 | 30 | @InvokedViaInstrumentation(record = CONTROL_STACK_COPY_TOP) 31 | public abstract ControlFlowStack copyTop(); 32 | 33 | @InvokedViaInstrumentation(record = CONTROL_STACK_COPY_TOP) 34 | public abstract void reset(); 35 | 36 | @InvokedViaInstrumentation(record = CONTROL_STACK_PUSH_FRAME) 37 | public abstract void pushFrame(); 38 | 39 | @InvokedViaInstrumentation(record = CONTROL_STACK_POP_FRAME) 40 | public abstract void popFrame(); 41 | 42 | @InvokedViaInstrumentation(record = CONTROL_STACK_UNINSTRUMENTED_WRAPPER) 43 | public void enteringUninstrumentedWrapper() { 44 | 45 | } 46 | 47 | public boolean isDisabled() { 48 | return disabled != 0; 49 | } 50 | 51 | /** 52 | * Used by Phosphor masking classes to retrieve the control taint tag 53 | * 54 | * @return the current control taint tag 55 | */ 56 | public abstract Taint copyTag(); 57 | } 58 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/LocalVariable.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control; 2 | 3 | public final class LocalVariable { 4 | 5 | private final int index; 6 | private final String typeInternalName; 7 | 8 | public LocalVariable(int index, String typeInternalName) { 9 | if(typeInternalName == null) { 10 | throw new NullPointerException(); 11 | } 12 | this.index = index; 13 | this.typeInternalName = typeInternalName; 14 | } 15 | 16 | public int getIndex() { 17 | return index; 18 | } 19 | 20 | public String getTypeInternalName() { 21 | return typeInternalName; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if(this == o) { 27 | return true; 28 | } else if(!(o instanceof LocalVariable)) { 29 | return false; 30 | } 31 | LocalVariable that = (LocalVariable) o; 32 | if(index != that.index) { 33 | return false; 34 | } 35 | return typeInternalName.equals(that.typeInternalName); 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | int result = index; 41 | result = 31 * result + typeInternalName.hashCode(); 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/graph/BasicBlock.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.graph; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.HashMap; 4 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; 5 | import org.objectweb.asm.Label; 6 | import org.objectweb.asm.tree.AbstractInsnNode; 7 | import org.objectweb.asm.tree.InsnList; 8 | import org.objectweb.asm.tree.LabelNode; 9 | 10 | import java.util.Iterator; 11 | 12 | public interface BasicBlock { 13 | 14 | AbstractInsnNode getFirstInsn(); 15 | 16 | AbstractInsnNode getLastInsn(); 17 | 18 | String toDotString(Map labelNames); 19 | 20 | static Map getNumericLabelNames(InsnList instructions) { 21 | Map labelMap = new HashMap<>(); 22 | int i = 0; 23 | Iterator itr = instructions.iterator(); 24 | while(itr.hasNext()) { 25 | AbstractInsnNode insn = itr.next(); 26 | if(insn instanceof LabelNode) { 27 | Label label = ((LabelNode) insn).getLabel(); 28 | if(!labelMap.containsKey(label)) { 29 | labelMap.put(label, String.format("L%d", i++)); 30 | } 31 | } 32 | } 33 | return labelMap; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/graph/DummyBasicBlock.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.graph; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; 4 | import org.objectweb.asm.Label; 5 | import org.objectweb.asm.Opcodes; 6 | import org.objectweb.asm.tree.AbstractInsnNode; 7 | import org.objectweb.asm.tree.InsnNode; 8 | 9 | /** 10 | * A node in a control flow graph that does not contain any real instructions 11 | */ 12 | public class DummyBasicBlock implements BasicBlock { 13 | 14 | private final InsnNode insn = new InsnNode(Opcodes.NOP); 15 | 16 | @Override 17 | public AbstractInsnNode getFirstInsn() { 18 | return insn; 19 | } 20 | 21 | @Override 22 | public AbstractInsnNode getLastInsn() { 23 | return insn; 24 | } 25 | 26 | @Override 27 | public String toDotString(Map labelNames) { 28 | return "NOP"; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "DummyBasicBlock"; 34 | } 35 | } -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/graph/EntryPoint.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.graph; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; 4 | import org.objectweb.asm.Label; 5 | 6 | /** 7 | * Represents the single point of entry into a control flow graph. 8 | */ 9 | public class EntryPoint extends DummyBasicBlock { 10 | 11 | @Override 12 | public String toString() { 13 | return "EntryPoint"; 14 | } 15 | 16 | @Override 17 | public String toDotString(Map labelNames) { 18 | return "ENTRY"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/graph/ExitPoint.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.graph; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; 4 | import org.objectweb.asm.Label; 5 | 6 | /** 7 | * Represents the single point of exit in a control flow graph. 8 | */ 9 | public class ExitPoint extends DummyBasicBlock { 10 | 11 | @Override 12 | public String toString() { 13 | return "ExitPoint"; 14 | } 15 | 16 | @Override 17 | public String toDotString(Map labelNames) { 18 | return "EXIT"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/graph/InstructionTextifier.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.graph; 2 | 3 | import edu.columbia.cs.psl.phosphor.instrumenter.PhosphorTextifier; 4 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; 5 | import org.objectweb.asm.Label; 6 | import org.objectweb.asm.tree.AbstractInsnNode; 7 | import org.objectweb.asm.util.TraceMethodVisitor; 8 | 9 | public class InstructionTextifier extends PhosphorTextifier { 10 | 11 | public static final InstructionTextifier instance = new InstructionTextifier(); 12 | 13 | private TraceMethodVisitor tmv = new TraceMethodVisitor(this); 14 | private Map labelNames; 15 | 16 | private InstructionTextifier() { 17 | 18 | } 19 | 20 | public String convertInstructionToString(AbstractInsnNode insn, Map labelNames) { 21 | this.labelNames = labelNames; 22 | insn.accept(tmv); 23 | String result = stringBuilder.toString(); 24 | stringBuilder.delete(0, stringBuilder.length()); 25 | return result.trim(); 26 | } 27 | 28 | @Override 29 | protected void appendLabel(final Label label) { 30 | if(labelNames != null && labelNames.containsKey(label)) { 31 | stringBuilder.append(labelNames.get(label)); 32 | } else { 33 | stringBuilder.append(label.toString()); 34 | } 35 | } 36 | 37 | public static InstructionTextifier getInstance() { 38 | return instance; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/graph/SimpleBasicBlock.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.graph; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.Map; 4 | import edu.columbia.cs.psl.phosphor.struct.harmony.util.StringBuilder; 5 | import org.objectweb.asm.Label; 6 | import org.objectweb.asm.Opcodes; 7 | import org.objectweb.asm.tree.AbstractInsnNode; 8 | import org.objectweb.asm.tree.InsnNode; 9 | 10 | public class SimpleBasicBlock implements BasicBlock { 11 | 12 | /** 13 | * The first instruction in this block 14 | */ 15 | private final AbstractInsnNode firstInsn; 16 | 17 | /** 18 | * The last instruction in this block 19 | */ 20 | private final AbstractInsnNode lastInsn; 21 | 22 | /** 23 | * An identifying number for this basic block 24 | */ 25 | private final int identifier; 26 | 27 | /** 28 | * Constructs a new basic block that represents the specified instruction sequence. 29 | * 30 | * @param instructions the sequence of instructions in the basic block being constructed 31 | * @param identifier a number used to identify the basic block being constructed 32 | */ 33 | public SimpleBasicBlock(final AbstractInsnNode[] instructions, int identifier) { 34 | if(instructions.length == 0) { 35 | this.firstInsn = this.lastInsn = new InsnNode(Opcodes.NOP); 36 | } else { 37 | this.firstInsn = instructions[0]; 38 | this.lastInsn = instructions[instructions.length - 1]; 39 | } 40 | this.identifier = identifier; 41 | } 42 | 43 | @Override 44 | public AbstractInsnNode getFirstInsn() { 45 | return firstInsn; 46 | } 47 | 48 | @Override 49 | public AbstractInsnNode getLastInsn() { 50 | return lastInsn; 51 | } 52 | 53 | public int getIdentifier() { 54 | return identifier; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return String.format("BasicBlock{#%d: %s - %s}", identifier, firstInsn.getClass().getSimpleName(), lastInsn.getClass().getSimpleName()); 60 | } 61 | 62 | @Override 63 | public String toDotString(Map labelNames) { 64 | StringBuilder builder = new StringBuilder("\""); 65 | AbstractInsnNode insn = firstInsn; 66 | do { 67 | builder.append(InstructionTextifier.getInstance().convertInstructionToString(insn, labelNames)).append("\\n"); 68 | if(insn == lastInsn) { 69 | break; 70 | } 71 | insn = insn.getNext(); 72 | } while(insn != null); 73 | return builder.append('"').toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/BranchEnd.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class BranchEnd implements PhosphorInstructionInfo { 6 | 7 | private final int branchID; 8 | 9 | public BranchEnd(int branchID) { 10 | this.branchID = branchID; 11 | } 12 | 13 | public int getBranchID() { 14 | return branchID; 15 | } 16 | 17 | @Override 18 | public boolean equals(Object o) { 19 | if(this == o) { 20 | return true; 21 | } else if(!(o instanceof BranchEnd)) { 22 | return false; 23 | } 24 | BranchEnd that = (BranchEnd) o; 25 | return branchID == that.branchID; 26 | } 27 | 28 | @Override 29 | public int hashCode() { 30 | return branchID; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/BranchStart.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class BranchStart implements PhosphorInstructionInfo { 6 | 7 | private final int branchID; 8 | 9 | public BranchStart(int branchID) { 10 | this.branchID = branchID; 11 | } 12 | 13 | public int getBranchID() { 14 | return branchID; 15 | } 16 | 17 | @Override 18 | public boolean equals(Object o) { 19 | if(this == o) { 20 | return true; 21 | } else if(!(o instanceof BranchStart)) { 22 | return false; 23 | } 24 | BranchStart that = (BranchStart) o; 25 | return branchID == that.branchID; 26 | } 27 | 28 | @Override 29 | public int hashCode() { 30 | return branchID; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ExceptionHandlerEnd.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class ExceptionHandlerEnd implements PhosphorInstructionInfo { 6 | private final String exceptionType; 7 | 8 | public ExceptionHandlerEnd(String exceptionType) { 9 | this.exceptionType = exceptionType; 10 | } 11 | 12 | public String getExceptionType() { 13 | return exceptionType; 14 | } 15 | 16 | @Override 17 | public boolean equals(Object o) { 18 | if(this == o) { 19 | return true; 20 | } else if(!(o instanceof ExceptionHandlerEnd)) { 21 | return false; 22 | } 23 | ExceptionHandlerEnd that = (ExceptionHandlerEnd) o; 24 | return exceptionType != null ? exceptionType.equals(that.exceptionType) : that.exceptionType == null; 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | return exceptionType != null ? exceptionType.hashCode() : 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ExceptionHandlerStart.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class ExceptionHandlerStart implements PhosphorInstructionInfo { 6 | private final String exceptionType; 7 | 8 | public ExceptionHandlerStart(String exceptionType) { 9 | this.exceptionType = exceptionType; 10 | } 11 | 12 | public String getExceptionType() { 13 | return exceptionType; 14 | } 15 | 16 | @Override 17 | public boolean equals(Object o) { 18 | if(this == o) { 19 | return true; 20 | } else if(!(o instanceof ExceptionHandlerStart)) { 21 | return false; 22 | } 23 | ExceptionHandlerStart that = (ExceptionHandlerStart) o; 24 | return exceptionType != null ? exceptionType.equals(that.exceptionType) : that.exceptionType == null; 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | return exceptionType != null ? exceptionType.hashCode() : 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ExecuteForceControlStore.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public enum ExecuteForceControlStore implements PhosphorInstructionInfo { 6 | EXECUTE_FORCE_CONTROL_STORE 7 | } 8 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/ForceControlStore.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.LocalVariablePhosphorInstructionInfo; 4 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 5 | import edu.columbia.cs.psl.phosphor.struct.Field; 6 | import org.objectweb.asm.Type; 7 | 8 | public interface ForceControlStore extends PhosphorInstructionInfo { 9 | 10 | final class ForceControlStoreLocal implements ForceControlStore, LocalVariablePhosphorInstructionInfo { 11 | 12 | private final int index; 13 | private final Type type; 14 | 15 | public ForceControlStoreLocal(int index, Type type) { 16 | this.index = index; 17 | this.type = type; 18 | } 19 | 20 | @Override 21 | public int getLocalVariableIndex() { 22 | return index; 23 | } 24 | 25 | @Override 26 | public ForceControlStoreLocal setLocalVariableIndex(int index) { 27 | return new ForceControlStoreLocal(index, type); 28 | } 29 | 30 | @Override 31 | public Type getType() { 32 | return type; 33 | } 34 | 35 | @Override 36 | public boolean equals(Object o) { 37 | if(this == o) { 38 | return true; 39 | } else if(!(o instanceof ForceControlStoreLocal)) { 40 | return false; 41 | } 42 | ForceControlStoreLocal that = (ForceControlStoreLocal) o; 43 | return index == that.index; 44 | } 45 | 46 | @Override 47 | public int hashCode() { 48 | return index; 49 | } 50 | } 51 | 52 | final class ForceControlStoreField implements ForceControlStore { 53 | 54 | private final Field field; 55 | 56 | public ForceControlStoreField(Field field) { 57 | if(field == null) { 58 | throw new NullPointerException(); 59 | } 60 | this.field = field; 61 | } 62 | 63 | public Field getField() { 64 | return field; 65 | } 66 | 67 | @Override 68 | public boolean equals(Object o) { 69 | if(this == o) { 70 | return true; 71 | } else if(!(o instanceof ForceControlStoreField)) { 72 | return false; 73 | } 74 | ForceControlStoreField that = (ForceControlStoreField) o; 75 | return field.equals(that.field); 76 | } 77 | 78 | @Override 79 | public int hashCode() { 80 | return field.hashCode(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/NoControlFlowAnalyzer.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.control.ControlFlowAnalyzer; 4 | import org.objectweb.asm.tree.MethodNode; 5 | 6 | public class NoControlFlowAnalyzer implements ControlFlowAnalyzer { 7 | 8 | @Override 9 | public void annotate(String owner, MethodNode methodNode) { 10 | // No need to add any annotations 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/NoControlFlowPropagationPolicy.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.control.AbstractControlFlowPropagationPolicy; 4 | import org.objectweb.asm.Label; 5 | 6 | import static edu.columbia.cs.psl.phosphor.instrumenter.TaintMethodRecord.NEW_EMPTY_TAINT; 7 | 8 | /** 9 | * Specifies that control flow should not propagate. 10 | */ 11 | public class NoControlFlowPropagationPolicy extends AbstractControlFlowPropagationPolicy { 12 | 13 | public NoControlFlowPropagationPolicy(NoControlFlowAnalyzer flowAnalyzer) { 14 | super(flowAnalyzer); 15 | } 16 | 17 | @Override 18 | public void generateEmptyTaint() { 19 | NEW_EMPTY_TAINT.delegateVisit(delegate); 20 | } 21 | 22 | @Override 23 | public void visitingJump(int opcode, Label label) { 24 | 25 | } 26 | 27 | @Override 28 | public void visitTableSwitch(int min, int max, Label defaultLabel, Label[] labels) { 29 | } 30 | 31 | @Override 32 | public void visitLookupSwitch(Label defaultLabel, int[] keys, Label[] labels) { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/StandardControlFlowManager.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import edu.columbia.cs.psl.phosphor.control.ControlFlowManager; 5 | import edu.columbia.cs.psl.phosphor.control.ControlFlowPropagationPolicy; 6 | import edu.columbia.cs.psl.phosphor.control.ControlFlowStack; 7 | import edu.columbia.cs.psl.phosphor.instrumenter.TaintTrackingClassVisitor; 8 | import org.objectweb.asm.MethodVisitor; 9 | import org.objectweb.asm.Opcodes; 10 | 11 | import static edu.columbia.cs.psl.phosphor.control.standard.ControlMethodRecord.STANDARD_CONTROL_STACK_FACTORY; 12 | 13 | public class StandardControlFlowManager implements ControlFlowManager { 14 | 15 | @Override 16 | public Class getControlStackClass() { 17 | return StandardControlFlowStack.class; 18 | } 19 | 20 | @Override 21 | public void visitCreateStack(MethodVisitor mv, boolean disabled) { 22 | mv.visitInsn(disabled ? Opcodes.ICONST_1 : Opcodes.ICONST_0); 23 | STANDARD_CONTROL_STACK_FACTORY.delegateVisit(mv); 24 | } 25 | 26 | @Override 27 | public ControlFlowStack getStack(boolean disabled) { 28 | return StandardControlFlowStack.factory(disabled); 29 | } 30 | 31 | @Override 32 | public ControlFlowPropagationPolicy createPropagationPolicy(int access, String owner, String name, String descriptor) { 33 | boolean isImplicitLightTrackingMethod = TaintTrackingClassVisitor.isImplicitLightMethod(owner, name, descriptor); 34 | if((Configuration.IMPLICIT_TRACKING || isImplicitLightTrackingMethod) && !Configuration.WITHOUT_PROPAGATION) { 35 | StandardControlFlowAnalyzer flowAnalyzer = new StandardControlFlowAnalyzer(isImplicitLightTrackingMethod); 36 | boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; 37 | return new StandardControlFlowPropagationPolicy(flowAnalyzer, isStatic, descriptor); 38 | } else { 39 | return new NoControlFlowPropagationPolicy(new NoControlFlowAnalyzer()); 40 | } 41 | } 42 | 43 | @Override 44 | public boolean isIgnoredFromControlTrack(String className, String methodName) { 45 | return (className.equals("java/nio/charset/Charset") 46 | || className.equals("java/lang/StringCoding") 47 | || className.equals("java/nio/charset/CharsetEncoder") 48 | || className.equals("java/nio/charset/CharsetDecoder")) 49 | && !methodName.equals("") && !methodName.equals(""); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/UnthrownException.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class UnthrownException implements PhosphorInstructionInfo { 6 | private final String exceptionType; 7 | 8 | public UnthrownException(String exceptionType) { 9 | this.exceptionType = exceptionType; 10 | } 11 | 12 | public String getExceptionType() { 13 | return exceptionType; 14 | } 15 | 16 | @Override 17 | public boolean equals(Object o) { 18 | if(this == o) { 19 | return true; 20 | } else if(!(o instanceof UnthrownException)) { 21 | return false; 22 | } 23 | UnthrownException that = (UnthrownException) o; 24 | return exceptionType != null ? exceptionType.equals(that.exceptionType) : that.exceptionType == null; 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | return exceptionType != null ? exceptionType.hashCode() : 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/control/standard/UnthrownExceptionCheck.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.control.standard; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class UnthrownExceptionCheck implements PhosphorInstructionInfo { 6 | private final String exceptionType; 7 | 8 | public UnthrownExceptionCheck(String exceptionType) { 9 | this.exceptionType = exceptionType; 10 | } 11 | 12 | public String getExceptionType() { 13 | return exceptionType; 14 | } 15 | 16 | @Override 17 | public boolean equals(Object o) { 18 | if(this == o) { 19 | return true; 20 | } else if(!(o instanceof UnthrownExceptionCheck)) { 21 | return false; 22 | } 23 | UnthrownExceptionCheck that = (UnthrownExceptionCheck) o; 24 | return exceptionType != null ? exceptionType.equals(that.exceptionType) : that.exceptionType == null; 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | return exceptionType != null ? exceptionType.hashCode() : 0; 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/ClinitRetransformClassVisitor.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | /* Visits a Java class modifying the method to add code to retransform the class on class initialization. */ 9 | public class ClinitRetransformClassVisitor extends ClassVisitor { 10 | 11 | // Whether or not the has been visited 12 | private boolean visitedClassInitializer; 13 | // The name of the class being visited 14 | private String className; 15 | // Whether or not the version is at least the required version 1.5 for the ldc of a constant class 16 | private boolean fixLdcClass; 17 | // Whether this class should be skipped 18 | private boolean skip = false; 19 | 20 | public ClinitRetransformClassVisitor(ClassVisitor cv) { 21 | super(Configuration.ASM_VERSION, cv); 22 | this.visitedClassInitializer = false; 23 | } 24 | 25 | @Override 26 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 27 | super.visit(version, access, name, signature, superName, interfaces); 28 | this.fixLdcClass = (version & 0xFFFF) < Opcodes.V1_5; 29 | this.className = name; 30 | this.skip = className.contains("$$Lambda$") 31 | || className.startsWith("sun/reflect/Generated") 32 | || className.startsWith("jdk/internal/reflect/Generated") 33 | || className.equals("java/lang/ClassCircularityError") 34 | || className.equals("java/lang/LinkageError") 35 | || className.startsWith("java/util/concurrent/locks") 36 | || className.startsWith("java/lang/WeakPair") 37 | || className.startsWith("java/lang/CharSequence") 38 | || className.startsWith("java/lang/Throwable") 39 | || className.equals("java/lang/Error"); 40 | } 41 | 42 | @Override 43 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 44 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 45 | if(name.equals("")) { 46 | visitedClassInitializer = true; 47 | if(!skip) { 48 | mv = new ClinitRetransformMV(mv, className, fixLdcClass); 49 | } 50 | } 51 | return mv; 52 | } 53 | 54 | /* Checks if the method was visited. If it was not visited, makes calls to visit it. */ 55 | @Override 56 | public void visitEnd() { 57 | if(!visitedClassInitializer && !skip) { 58 | MethodVisitor mv = visitMethod(Opcodes.ACC_STATIC, "", "()V", null, null); 59 | mv.visitCode(); 60 | mv.visitInsn(Opcodes.RETURN); 61 | mv.visitMaxs(0, 0); 62 | mv.visitEnd(); 63 | } 64 | super.visitEnd(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/ClinitRetransformMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import edu.columbia.cs.psl.phosphor.SourceSinkTransformer; 5 | import edu.columbia.cs.psl.phosphor.control.OpcodesUtil; 6 | import edu.columbia.cs.psl.phosphor.runtime.PhosphorStackFrame; 7 | import org.objectweb.asm.MethodVisitor; 8 | import org.objectweb.asm.Opcodes; 9 | import org.objectweb.asm.Type; 10 | 11 | /* Visits the method to add code to retransform the class on class initialization. */ 12 | public class ClinitRetransformMV extends MethodVisitor { 13 | 14 | // The name of the class that owns the method being visited 15 | private final String className; 16 | // Whether or not the version is at least the required version 1.5 for the ldc of a constant class 17 | private final boolean fixLdcClass; 18 | 19 | public ClinitRetransformMV(MethodVisitor mv, String className, boolean fixLdcClass) { 20 | super(Configuration.ASM_VERSION, mv); 21 | this.className = className; 22 | this.fixLdcClass = fixLdcClass; 23 | } 24 | 25 | @Override 26 | public void visitInsn(int opcode) { 27 | if(OpcodesUtil.isReturnOpcode(opcode)) { 28 | if(fixLdcClass) { 29 | // Since the class is not at least the required version 1.5 for the ldc of a constant class, push the class 30 | // onto the stack by making a call to Class.forName 31 | super.visitLdcInsn(className.replace("/", ".")); 32 | super.visitInsn(Opcodes.ACONST_NULL); 33 | TaintMethodRecord.STACK_FRAME_FOR_METHOD_DEBUG.delegateVisit(mv); 34 | super.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;" + PhosphorStackFrame.DESCRIPTOR + ")Ljava/lang/Class;", false); 35 | } else { 36 | // Directly push the class onto the stack 37 | mv.visitLdcInsn(Type.getObjectType(className)); 38 | } 39 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(SourceSinkTransformer.class), "retransform", "(Ljava/lang/Class;)V", false); 40 | } 41 | super.visitInsn(opcode); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/EclipseCompilerCV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | import org.objectweb.asm.Type; 8 | 9 | /* Changes the error handling policies of an instance of the Compiler class used by the Eclipse Compiler for Java, ECJ, 10 | * to ignore all problems in the hopes that these issue will be resolved when Phosphor instruments the class compiled 11 | * class. */ 12 | public class EclipseCompilerCV extends ClassVisitor { 13 | 14 | public EclipseCompilerCV(ClassVisitor cv) { 15 | super(Configuration.ASM_VERSION, cv); 16 | } 17 | 18 | @Override 19 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 20 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 21 | if(name.equals("")) { 22 | // Visiting an instance initialization method for ECJ's compiler class 23 | mv = new ECJInitMV(mv, desc); 24 | } 25 | return mv; 26 | } 27 | 28 | /* Returns whether the class with the specified name is ECJ's compiler class. */ 29 | public static boolean isEclipseCompilerClass(String className) { 30 | return className != null && className.equals("org/eclipse/jdt/internal/compiler/Compiler"); 31 | } 32 | 33 | private static class ECJInitMV extends MethodVisitor { 34 | private final Type[] args; 35 | 36 | ECJInitMV(MethodVisitor mv, String desc) { 37 | super(Configuration.ASM_VERSION, mv); 38 | this.args = Type.getArgumentTypes(desc); 39 | } 40 | 41 | @Override 42 | public void visitCode() { 43 | super.visitCode(); 44 | int idx = 1; // Start at 1 to skip over the "this" argument 45 | for(Type arg : args) { 46 | if(arg.getInternalName().equals("org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy")) { 47 | // Make the replacement policy 48 | super.visitMethodInsn(Opcodes.INVOKESTATIC, "org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies", "ignoreAllProblems", "()Lorg/eclipse/jdt/internal/compiler/IErrorHandlingPolicy;", false); 49 | // Store the replacement policy into the old policy's local variable 50 | super.visitVarInsn(Opcodes.ASTORE, idx); 51 | } 52 | idx += arg.getSize(); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/InstOrUninstChoosingMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | public class InstOrUninstChoosingMV extends MethodVisitor { 7 | 8 | private UninstrumentedCompatMV umv; 9 | 10 | public InstOrUninstChoosingMV(TaintPassingMV tmv, UninstrumentedCompatMV umv) { 11 | super(Configuration.ASM_VERSION, tmv); 12 | this.umv = umv; 13 | } 14 | 15 | public void disableTainting() { 16 | umv.lvs.disable(); 17 | this.mv = umv; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/InvokedViaInstrumentation.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.SOURCE) 10 | public @interface InvokedViaInstrumentation { 11 | TaintMethodRecord record(); 12 | } 13 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/JettyBufferUtilCV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | /* Prevents Jetty's buffer utility class from creating direct buffers. */ 9 | public class JettyBufferUtilCV extends ClassVisitor implements Opcodes { 10 | 11 | public JettyBufferUtilCV(ClassVisitor cv) { 12 | super(Configuration.ASM_VERSION, cv); 13 | } 14 | 15 | @Override 16 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 17 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 18 | return new JettyBufferUtilMV(mv); 19 | } 20 | 21 | /* Returns whether this class visitor should be applied to the class with the specified name. */ 22 | public static boolean isApplicable(String className) { 23 | return className != null && className.equals("org/eclipse/jetty/util/BufferUtil"); 24 | } 25 | 26 | private static class JettyBufferUtilMV extends MethodVisitor { 27 | 28 | JettyBufferUtilMV(MethodVisitor mv) { 29 | super(Configuration.ASM_VERSION, mv); 30 | } 31 | 32 | @Override 33 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 34 | if(opcode == INVOKESTATIC && owner.equals("java/nio/ByteBuffer") && name.equals("allocateDirect") && desc.equals("(I)Ljava/nio/ByteBuffer;")) { 35 | super.visitMethodInsn(opcode, owner, "allocate", desc, itf); 36 | } else { 37 | super.visitMethodInsn(opcode, owner, name, desc, itf); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/MethodRecord.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | import org.objectweb.asm.Type; 5 | 6 | /** 7 | * Stores the information needed by an ASM method visitor to add a call to a method. 8 | */ 9 | public interface MethodRecord { 10 | 11 | /** 12 | * @return the opcode of the type instruction associated with this method 13 | */ 14 | int getOpcode(); 15 | 16 | /** 17 | * @return the internal name of this method's owner class 18 | */ 19 | String getOwner(); 20 | 21 | /** 22 | * @return this method's name 23 | */ 24 | String getName(); 25 | 26 | /** 27 | * @return this method's descriptor 28 | */ 29 | String getDescriptor(); 30 | 31 | /** 32 | * @return true if this method's owner class is an interface 33 | */ 34 | boolean isInterface(); 35 | 36 | /** 37 | * @return this method's return type 38 | */ 39 | Class getReturnType(); 40 | 41 | /** 42 | * Tells the specified method visitor to visit a method instruction for this method. 43 | * 44 | * @param methodVisitor the method visitor that should visit this method 45 | */ 46 | default void delegateVisit(MethodVisitor methodVisitor) { 47 | methodVisitor.visitMethodInsn(getOpcode(), getOwner(), getName(), getDescriptor(), isInterface()); 48 | } 49 | 50 | static String createDescriptor(Class returnType, Class... parameterTypes) { 51 | Type[] parameters = new Type[parameterTypes.length]; 52 | for(int i = 0; i < parameters.length; i++) { 53 | parameters[i] = Type.getType(parameterTypes[i]); 54 | } 55 | return Type.getMethodDescriptor(Type.getType(returnType), parameters); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/OgnlUtilCV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | /* Disables Ognl expression caching by changing reads of the enableExpressionCache field to return false. */ 9 | public class OgnlUtilCV extends ClassVisitor { 10 | 11 | // The name of field whose reads are being changed 12 | private static final String targetFieldName = "enableExpressionCache"; 13 | 14 | public OgnlUtilCV(ClassVisitor cv) { 15 | super(Configuration.ASM_VERSION, cv); 16 | } 17 | 18 | @Override 19 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 20 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 21 | return new OgnlUtilMV(mv); 22 | } 23 | 24 | /* Returns whether the class with the specified name is OgnlUtil. */ 25 | public static boolean isOgnlUtilClass(String className) { 26 | return className != null && className.equals("com/opensymphony/xwork2/ognl/OgnlUtil"); 27 | } 28 | 29 | private static class OgnlUtilMV extends MethodVisitor { 30 | 31 | OgnlUtilMV(MethodVisitor mv) { 32 | super(Configuration.ASM_VERSION, mv); 33 | } 34 | 35 | @Override 36 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 37 | if(isOgnlUtilClass(owner) && name.equals(targetFieldName)) { 38 | if(opcode == Opcodes.GETFIELD) { 39 | super.visitInsn(Opcodes.POP); 40 | super.visitInsn(Opcodes.ICONST_0); 41 | } else if(opcode == Opcodes.GETSTATIC) { 42 | super.visitInsn(Opcodes.ICONST_0); 43 | } 44 | } else { 45 | super.visitFieldInsn(opcode, owner, name, desc); 46 | } 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/PowerMockUtilCV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | public class PowerMockUtilCV extends ClassVisitor { 9 | public PowerMockUtilCV(ClassVisitor classVisitor) { 10 | super(Configuration.ASM_VERSION, classVisitor); 11 | } 12 | 13 | @Override 14 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 15 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 16 | 17 | if(name.equals("")) { 18 | mv = new MethodVisitor(Configuration.ASM_VERSION, mv) { 19 | @Override 20 | public void visitInsn(int opcode) { 21 | if(opcode == Opcodes.RETURN) { 22 | super.visitVarInsn(Opcodes.ALOAD, 0); 23 | super.visitInsn(Opcodes.ICONST_1); 24 | super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String"); 25 | super.visitInsn(Opcodes.DUP); 26 | super.visitInsn(Opcodes.ICONST_0); 27 | super.visitLdcInsn("edu.columbia.cs.psl.phosphor.*"); 28 | super.visitInsn(Opcodes.AASTORE); 29 | super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/powermock/core/classloader/DeferSupportingClassLoader", "addIgnorePackage", "([Ljava/lang/String;)V", false); 30 | 31 | } 32 | super.visitInsn(opcode); 33 | } 34 | }; 35 | } 36 | return mv; 37 | } 38 | 39 | /* Returns whether this class visitor should be applied to the class with the specified name. */ 40 | public static boolean isApplicable(String className) { 41 | return className != null && className.equals("org/powermock/core/classloader/DeferSupportingClassLoader"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/PrimitiveBoxingFixer.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.instrumenter.analyzer.NeverNullArgAnalyzerAdapter; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class PrimitiveBoxingFixer extends TaintAdapter implements Opcodes { 8 | 9 | // private boolean hackOnTaint = false; 10 | public PrimitiveBoxingFixer(int access, String className, String name, String desc, String signature, String[] exceptions, MethodVisitor mv, NeverNullArgAnalyzerAdapter analyzer) { 11 | super(access, className, name, desc, signature, exceptions, mv, analyzer, false); 12 | //TODO delete this class? 13 | // this.hackOnTaint = (className.equals("java/lang/Float") || className.equals("java/lang/Double") && name.equals("valueOf$$PHOSPHORTAGGED")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintTagFactory.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 5 | import org.objectweb.asm.Label; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | public interface TaintTagFactory { 9 | 10 | Taint getAutoTaint(String source); 11 | 12 | void instrumentationStarting(String className); 13 | 14 | void instrumentationStarting(int access, String methodName, String methodDesc); 15 | 16 | void instrumentationEnding(String className); 17 | 18 | /** 19 | * Returns whether a class with the specified name is used by Phosphor for "internal" tainting. Calls to methods in 20 | * internal tainting classes from instrumented classes are remapped to the appropriate "$$PHOSPHORTAGGED" version 21 | * even if the internal tainting class is not instrumented by Phosphor. This requires internal tainting classes to 22 | * provide instrumented versions of any method that may be invoked by a classes that is instrumented by Phosphor. 23 | * 24 | * @param className the name of class being checking 25 | * @return true if a class with the specified name is used by Phosphor for internal tainting 26 | * @see MultiTainter 27 | */ 28 | boolean isInternalTaintingClass(String className); 29 | 30 | void insnIndexVisited(int offset); 31 | 32 | boolean isIgnoredClass(String className); 33 | 34 | default boolean isIgnoredMethod(String owner, String name, String desc) { 35 | return false; 36 | } 37 | 38 | void generateEmptyTaint(MethodVisitor mv); 39 | 40 | void generateEmptyTaintArray(Object[] array, int dimensions); 41 | 42 | void methodOp(int opcode, String owner, String name, String desc, boolean isInterface, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 43 | 44 | void stackOp(int opcode, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 45 | 46 | void jumpOp(int opcode, Label label, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 47 | 48 | void typeOp(int opcode, String type, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 49 | 50 | void iincOp(int var, int increment, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 51 | 52 | void intOp(int opcode, int arg, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 53 | 54 | void signalOp(int signal, Object option); 55 | 56 | void fieldOp(int opcode, String owner, String name, String desc, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta, boolean trackedLoad); 57 | 58 | void methodEntered(String owner, String name, String desc, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV ta); 59 | 60 | void lineNumberVisited(int line); 61 | 62 | void lookupSwitch(Label defaultLabel, int[] keys, Label[] labels, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV taintPassingMV); 63 | 64 | void tableSwitch(int min, int max, Label defaultLabel, Label[] labels, MethodVisitor mv, LocalVariableManager lvs, TaintPassingMV taintPassingMV); 65 | 66 | void propagateTagNative(String className, int acc, String methodName, String newDesc, MethodVisitor mv); 67 | 68 | void generateSetTag(MethodVisitor mv, String className); 69 | } 70 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/TaintTagFieldCastMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import edu.columbia.cs.psl.phosphor.TaintUtils; 5 | import edu.columbia.cs.psl.phosphor.runtime.HardcodedBypassStore; 6 | import org.objectweb.asm.MethodVisitor; 7 | import org.objectweb.asm.Opcodes; 8 | import org.objectweb.asm.Type; 9 | 10 | public class TaintTagFieldCastMV extends MethodVisitor implements Opcodes { 11 | 12 | private String name; 13 | 14 | public TaintTagFieldCastMV(MethodVisitor mv, String name) { 15 | super(Configuration.ASM_VERSION, mv); 16 | this.name = name; 17 | } 18 | 19 | @Override 20 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 21 | 22 | boolean taintDesc = desc.equals(Configuration.TAINT_TAG_DESC) || desc.startsWith("Ledu/columbia/cs/psl/phosphor/struct/Tagged"); 23 | if((opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) && !TaintAdapter.canRawTaintAccess(owner) && name.endsWith(TaintUtils.TAINT_FIELD) && taintDesc) { 24 | super.visitFieldInsn(opcode, owner, name, "I"); 25 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(HardcodedBypassStore.class), "get", "(I)Ljava/lang/Object;", false); 26 | super.visitTypeInsn(CHECKCAST, Type.getType(desc).getInternalName()); 27 | } else if((opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) && !TaintAdapter.canRawTaintAccess(owner) && name.endsWith(TaintUtils.TAINT_FIELD) 28 | && taintDesc) { 29 | if(this.name.equals("set" + TaintUtils.TAINT_FIELD) && desc.equals(Configuration.TAINT_TAG_DESC)) { 30 | if(opcode == PUTFIELD) { 31 | super.visitInsn(POP2); 32 | } else { 33 | super.visitInsn(POP); 34 | } 35 | } else { 36 | if(opcode == Opcodes.PUTSTATIC) { 37 | super.visitInsn(ACONST_NULL); 38 | } else { 39 | super.visitInsn(SWAP); 40 | super.visitInsn(DUP_X1); 41 | } 42 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(HardcodedBypassStore.class), "add", "(Ljava/lang/Object;Ljava/lang/Object;)I", false); 43 | if(name.equals("valuePHOSPHOR_TAG")) { 44 | //Also set the object's taint tag 45 | super.visitInsn(DUP2); 46 | super.visitFieldInsn(opcode, owner, "PHOSPHOR_TAG", "I"); 47 | } 48 | super.visitFieldInsn(opcode, owner, name, "I"); 49 | } 50 | } else { 51 | super.visitFieldInsn(opcode, owner, name, desc); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/analyzer/BasicArrayValue.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter.analyzer; 2 | 3 | import org.objectweb.asm.Type; 4 | import org.objectweb.asm.tree.analysis.BasicValue; 5 | 6 | public class BasicArrayValue extends BasicValue { 7 | public static final BasicArrayValue INT_ARRAY = new BasicArrayValue(Type.getType("[I")); 8 | public static final BasicArrayValue FLOAT_ARRAY = new BasicArrayValue(Type.getType("[F")); 9 | public static final BasicArrayValue DOUBLE_ARRAY = new BasicArrayValue(Type.getType("[D")); 10 | public static final BasicArrayValue LONG_ARRAY = new BasicArrayValue(Type.getType("[J")); 11 | public static final BasicArrayValue BYTE_ARRAY = new BasicArrayValue(Type.getType("[B")); 12 | public static final BasicArrayValue CHAR_ARRAY = new BasicArrayValue(Type.getType("[C")); 13 | public static final BasicArrayValue BOOLEAN_ARRAY = new BasicArrayValue(Type.getType("[Z")); 14 | public static final BasicArrayValue SHORT_ARRAY = new BasicArrayValue(Type.getType("[S")); 15 | public static final BasicValue NULL_VALUE = new BasicArrayValue(Type.getType("Lnull;")); 16 | 17 | public BasicArrayValue(Type type) { 18 | super(type); 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | if(this == NULL_VALUE) { 24 | return "N"; 25 | } else { 26 | return super.toString(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/analyzer/MergeAwareInterpreter.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter.analyzer; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import org.objectweb.asm.tree.analysis.Interpreter; 5 | import org.objectweb.asm.tree.analysis.Value; 6 | 7 | public abstract class MergeAwareInterpreter extends Interpreter { 8 | 9 | public MergeAwareInterpreter() { 10 | super(Configuration.ASM_VERSION); 11 | } 12 | 13 | public abstract void mergingFrame(int instructionIndexOfNextMerge); 14 | 15 | public abstract void mergingLocalVariable(int localIndexOfNextMerge, int numLocals, int stackSize); 16 | 17 | public abstract void mergingStackElement(int stackIndexOfNextMerge, int numLocals, int stackSize); 18 | } 19 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/analyzer/ReferenceArrayTarget.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter.analyzer; 2 | 3 | import edu.columbia.cs.psl.phosphor.PhosphorInstructionInfo; 4 | 5 | public class ReferenceArrayTarget implements PhosphorInstructionInfo { 6 | private String originalArrayType; 7 | 8 | public ReferenceArrayTarget(String originalArrayType) { 9 | this.originalArrayType = originalArrayType; 10 | } 11 | 12 | public String getOriginalArrayType() { 13 | return originalArrayType; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return "ReferenceArrayTarget{" + 19 | "originalArrayType='" + originalArrayType + '\'' + 20 | '}'; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/analyzer/TaggedValue.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter.analyzer; 2 | 3 | public class TaggedValue { 4 | public Object v; 5 | 6 | public TaggedValue(Object v) { 7 | if(v instanceof TaggedValue) { 8 | this.v = ((TaggedValue) v).v; 9 | } else { 10 | this.v = v; 11 | } 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return "T:" + v; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/asm/OffsetPreservingClassReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ASM: a very small and fast Java bytecode manipulation framework 3 | * Copyright (c) 2000-2011 INRIA, France Telecom 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. Neither the name of the copyright holders nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | * THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package edu.columbia.cs.psl.phosphor.instrumenter.asm; 31 | 32 | import org.objectweb.asm.ClassReader; 33 | import org.objectweb.asm.Label; 34 | 35 | public class OffsetPreservingClassReader extends ClassReader { 36 | 37 | public OffsetPreservingClassReader(byte[] b) { 38 | super(b); 39 | } 40 | 41 | @Override 42 | protected Label readLabel(int offset, Label[] labels) { 43 | if(labels[offset] == null) { 44 | for(int i = 0; i < labels.length; i++) { 45 | labels[i] = new OffsetPreservingLabel(i); 46 | } 47 | } 48 | return labels[offset]; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/instrumenter/asm/OffsetPreservingLabel.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.instrumenter.asm; 2 | 3 | import org.objectweb.asm.Label; 4 | 5 | public class OffsetPreservingLabel extends Label { 6 | private int originalPosition; 7 | 8 | public OffsetPreservingLabel(int originalPosition) { 9 | this.originalPosition = originalPosition; 10 | } 11 | 12 | public int getOriginalPosition() { 13 | return originalPosition; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/ArrayHelper.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | public class ArrayHelper { 4 | 5 | public static int engaged = 0; 6 | 7 | private ArrayHelper() { 8 | // Prevents this class from being instantiated 9 | } 10 | 11 | private static native Taint _getTag(Object obj); 12 | 13 | private static native void _setTag(Object obj, Taint t); 14 | 15 | public static Taint getTag(Object obj) { 16 | if(engaged == 0) { 17 | throw new IllegalStateException("Attempting to use JVMTI features, but Phosphor native agent not loaded"); 18 | } 19 | return _getTag(obj); 20 | } 21 | 22 | public static void setTag(Object obj, Taint t) { 23 | if(engaged == 0) { 24 | throw new IllegalStateException("Attempting to use JVMTI features, but Phosphor native agent not loaded"); 25 | } 26 | _setTag(obj, t); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/AutoTaintLabel.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | import java.io.IOException; 4 | import java.io.ObjectInputStream; 5 | import java.io.ObjectOutputStream; 6 | import java.io.Serializable; 7 | import java.util.Arrays; 8 | 9 | public class AutoTaintLabel implements Serializable { 10 | private String source; 11 | private StackTraceElement[] trace; 12 | 13 | public AutoTaintLabel(String source, StackTraceElement[] stackTrace) { 14 | this.source = source; 15 | this.trace = stackTrace; 16 | } 17 | 18 | @Override 19 | public boolean equals(Object o) { 20 | if(this == o) { 21 | return true; 22 | } 23 | if(o == null || getClass() != o.getClass()) { 24 | return false; 25 | } 26 | AutoTaintLabel that = (AutoTaintLabel) o; 27 | if(source != null ? !source.equals(that.source) : that.source != null) { 28 | return false; 29 | } 30 | // Probably incorrect - comparing Object[] arrays with Arrays.equals 31 | return Arrays.equals(trace, that.trace); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | int result = source != null ? source.hashCode() : 0; 37 | result = 31 * result + Arrays.hashCode(trace); 38 | return result; 39 | } 40 | 41 | public String getSource() { 42 | return source; 43 | } 44 | 45 | public StackTraceElement[] getTrace() { 46 | return trace; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "AutoTaintLabel [source=" + source + ", trace=" + Arrays.toString(trace) + "]"; 52 | } 53 | 54 | private void writeObject(ObjectOutputStream stream) throws IOException { 55 | stream.writeObject(source); 56 | stream.writeInt(trace == null ? -1 : trace.length); 57 | if(trace != null) { 58 | for(StackTraceElement element : trace) { 59 | stream.writeObject(element); 60 | } 61 | } 62 | } 63 | 64 | private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 65 | source = (String) stream.readObject(); 66 | int len = stream.readInt(); 67 | if(len != -1) { 68 | trace = new StackTraceElement[len]; 69 | for(int i = 0; i < len; i++) { 70 | trace[i] = (StackTraceElement) stream.readObject(); 71 | } 72 | } else { 73 | trace = null; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/HardcodedBypassStore.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.GarbageCollectedArrayList; 4 | 5 | public class HardcodedBypassStore { 6 | 7 | private static final GarbageCollectedArrayList values = new GarbageCollectedArrayList<>(); 8 | 9 | static { 10 | synchronized(values) { 11 | values.add(null, null); 12 | } 13 | } 14 | 15 | private HardcodedBypassStore() { 16 | // Prevents this class from being instantiated 17 | } 18 | 19 | public static Object get(int i) { 20 | // if(i == -1 || i == 0) { 21 | // return null; 22 | // } 23 | // synchronized(values) { 24 | // return values.get(i); 25 | // } 26 | return null; 27 | } 28 | 29 | public static int add(Object taintObjectToPointTo, Object referent) { 30 | return -1; 31 | // if(taintObjectToPointTo == null) { 32 | // return -1; 33 | // } 34 | // synchronized(values) { 35 | // return values.add(referent, taintObjectToPointTo); 36 | // } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/NativeHelper.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.TaggedArray; 4 | import edu.columbia.cs.psl.phosphor.struct.TaggedReferenceArray; 5 | import org.objectweb.asm.Type; 6 | 7 | import java.util.Collection; 8 | 9 | public final class NativeHelper { 10 | 11 | private NativeHelper() { 12 | throw new AssertionError("Utility class should not be instantiated"); 13 | } 14 | 15 | public static Class getClassOrWrapped(Object in) { 16 | if(in instanceof TaggedReferenceArray) { 17 | return ((TaggedReferenceArray) in).getUnderlyingClass(); 18 | } 19 | if(in instanceof TaggedArray) { 20 | return ((TaggedArray) in).getVal().getClass(); 21 | } 22 | return in.getClass(); 23 | } 24 | 25 | @SuppressWarnings("rawtypes") 26 | public static Collection ensureIsBoxedObjTags(Collection in) { 27 | if(in != null) { 28 | Collection tmp = null; 29 | for(Object o : in) { 30 | if(o == null) { 31 | break; 32 | } 33 | Type t = Type.getType(o.getClass()); 34 | if(t.getSort() == Type.ARRAY && t.getElementType().getSort() != Type.OBJECT) { 35 | if(tmp == null) { 36 | try { 37 | tmp = in.getClass().getConstructor().newInstance(null); 38 | } catch(Exception ex) { 39 | ex.printStackTrace(); 40 | } 41 | } 42 | tmp.add(MultiDArrayUtils.boxIfNecessary(o)); 43 | } else { 44 | break; 45 | } 46 | } 47 | if(tmp != null) { 48 | in.clear(); 49 | tmp.add(tmp); 50 | } 51 | } 52 | return in; 53 | } 54 | 55 | public static Collection ensureIsUnBoxedObjTags(Collection in) { 56 | if(in != null) { 57 | Collection tmp = null; 58 | for(Object o : in) { 59 | if(o != null && MultiDArrayUtils.isPrimitiveBoxClass(o.getClass()) != null) { 60 | if(tmp == null) { 61 | try { 62 | tmp = in.getClass().getConstructor().newInstance(null); 63 | } catch(Exception ex) { 64 | ex.printStackTrace(); 65 | } 66 | } 67 | tmp.add(MultiDArrayUtils.unboxRaw(o)); 68 | } else { 69 | break; 70 | } 71 | } 72 | if(tmp != null) { 73 | in.clear(); 74 | tmp.add(tmp); 75 | } 76 | } 77 | return in; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/NonModifiableClassException.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | public class NonModifiableClassException extends Exception { 4 | public NonModifiableClassException(Throwable cause){ 5 | super(cause); 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/TaintInstrumented.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.CLASS) 7 | public @interface TaintInstrumented { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/TaintSinkError.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | public class TaintSinkError extends IllegalAccessError { 4 | 5 | private static final long serialVersionUID = 1162066978522069763L; 6 | 7 | private Taint taint; 8 | private Object obj; 9 | 10 | public TaintSinkError(Taint taint, Object val) { 11 | super(taint + " flowed to sink! Value: " + val); 12 | this.taint = taint; 13 | this.obj = val; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/UninstrumentedTaintSentinel.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime; 2 | 3 | public class UninstrumentedTaintSentinel { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/runtime/proxied/InstrumentedJREMethodHelper.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.runtime.proxied; 2 | 3 | public class InstrumentedJREMethodHelper { 4 | private static RuntimeException _crash() { 5 | return new IllegalStateException("InstrumentedJREHelper not initialized"); 6 | } 7 | 8 | public static Object java_lang_reflect_Array_newArray(Class componentType, int length) throws NegativeArraySizeException { 9 | throw _crash(); 10 | } 11 | 12 | public static int java_lang_Integer_parseInt(CharSequence sequence, int v1, int v2, int v3){ 13 | throw _crash(); 14 | } 15 | public static long java_lang_Long_parseLong(CharSequence sequence, int v1, int v2, int v3){ 16 | throw _crash(); 17 | } 18 | 19 | public static int java_lang_Character_codePointBeforeImpl(char[] val, int i, int i2) { 20 | throw _crash(); 21 | } 22 | 23 | public static int java_lang_Character_toUpperCaseEx(int cp) { 24 | throw _crash(); 25 | } 26 | 27 | public static char[] java_lang_Character_toUpperCaseCharArray(int c) { 28 | throw _crash(); 29 | } 30 | 31 | public static int java_lang_Character_codePointAtImpl(char[] val, int index, int limit) { 32 | throw _crash(); 33 | } 34 | 35 | public static void java_lang_Long_getChars(long l, int idx, char[] val) { 36 | throw _crash(); 37 | } 38 | 39 | public static void java_lang_Integer_getChars(int l, int idx, char[] val) { 40 | throw _crash(); 41 | } 42 | 43 | public static int java_lang_Long_getChars(long l, int idx, byte[] val) { 44 | throw _crash(); 45 | } 46 | 47 | public static int java_lang_Integer_getChars(int l, int idx, byte[] val) { 48 | throw _crash(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/EnqueuedTaint.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | public class EnqueuedTaint { 4 | public int activeCount; 5 | } 6 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/ExceptionalTaintData.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 4 | 5 | public class ExceptionalTaintData { 6 | 7 | private final SinglyLinkedList> taintHistory; 8 | 9 | public ExceptionalTaintData() { 10 | taintHistory = new SinglyLinkedList<>(); 11 | taintHistory.push(Taint.emptyTaint()); // starting taint is null/empty 12 | } 13 | 14 | public Taint getCurrentTaint() { 15 | return taintHistory.peek(); 16 | } 17 | 18 | public void reset() { 19 | taintHistory.clear(); 20 | taintHistory.push(Taint.emptyTaint()); // starting taint is null/empty 21 | } 22 | 23 | public void push(Taint tag) { 24 | taintHistory.push(tag.union(taintHistory.peek())); 25 | } 26 | 27 | public Taint pop() { 28 | return taintHistory.pop(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/Field.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import java.util.Objects; 4 | 5 | public class Field { 6 | public boolean isStatic; 7 | public String name; 8 | public String owner; 9 | public String description; 10 | 11 | public Field(boolean isStatic, String owner, String name, String description) { 12 | this.isStatic = isStatic; 13 | this.name = name; 14 | this.owner = owner; 15 | this.description = description; 16 | } 17 | 18 | @Override 19 | public boolean equals(Object o) { 20 | if(this == o) { 21 | return true; 22 | } 23 | if(o == null || getClass() != o.getClass()) { 24 | return false; 25 | } 26 | Field field = (Field) o; 27 | return isStatic == field.isStatic && 28 | Objects.equals(name, field.name) && 29 | Objects.equals(owner, field.owner) && 30 | Objects.equals(description, field.description); 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | return Objects.hash(isStatic, name, owner, description); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "Field{" + 41 | "isStatic=" + isStatic + 42 | ", name='" + name + '\'' + 43 | ", owner='" + owner + '\'' + 44 | ", description='" + description + '\'' + 45 | '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/MaybeThrownException.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 4 | 5 | public class MaybeThrownException { 6 | 7 | private final Class clazz; 8 | private Taint tag; 9 | 10 | public MaybeThrownException(Class clazz, Taint tag) { 11 | this.clazz = clazz; 12 | this.tag = tag; 13 | } 14 | 15 | @Override 16 | public boolean equals(Object o) { 17 | if(this == o) { 18 | return true; 19 | } else if(!(o instanceof MaybeThrownException)) { 20 | return false; 21 | } 22 | MaybeThrownException that = (MaybeThrownException) o; 23 | if(clazz != null ? !clazz.equals(that.clazz) : that.clazz != null) { 24 | return false; 25 | } 26 | return tag != null ? tag.equals(that.tag) : that.tag == null; 27 | } 28 | 29 | @Override 30 | public int hashCode() { 31 | int result = clazz != null ? clazz.hashCode() : 0; 32 | result = 31 * result + (tag != null ? tag.hashCode() : 0); 33 | return result; 34 | } 35 | 36 | public Class getClazz() { 37 | return clazz; 38 | } 39 | 40 | public Taint getTag() { 41 | return tag; 42 | } 43 | 44 | public void unionTag(Taint tag) { 45 | this.tag = Taint.combineTags(this.tag, tag); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/MethodInvoke.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 4 | 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.Method; 7 | 8 | public class MethodInvoke { 9 | public Constructor c; 10 | public Taint c_taint; 11 | public Method m; 12 | public Taint m_taint; 13 | public Object o; 14 | public Taint o_taint; 15 | public TaggedReferenceArray a; 16 | public Taint a_taint; 17 | } 18 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/RankedElement.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | /** 4 | * Record type that associates an element with a rank. 5 | */ 6 | final class RankedElement { 7 | private final Object element; 8 | private final int rank; 9 | 10 | RankedElement(Object element, int rank) { 11 | this.element = element; 12 | this.rank = rank; 13 | } 14 | 15 | public Object getElement() { 16 | return element; 17 | } 18 | 19 | public int getRank() { 20 | return rank; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/Tainted.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | public interface Tainted { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/TaintedWithObjTag.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | 4 | public interface TaintedWithObjTag extends Tainted { 5 | Object getPHOSPHOR_TAG(); 6 | 7 | void setPHOSPHOR_TAG(Object t); 8 | } 9 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/harmony/util/Enumeration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * From Apache Harmony (http://harmony.apache.org/) 18 | * Modification: package changed to one that is ignored (i.e., not instrumented) by Phosphor 19 | */ 20 | 21 | package edu.columbia.cs.psl.phosphor.struct.harmony.util; 22 | 23 | import java.util.Iterator; 24 | import java.util.NoSuchElementException; 25 | 26 | /** 27 | * An Enumeration is used to sequence over a collection of objects. 28 | *

29 | * Preferably an {@link Iterator} should be used. {@code Iterator} replaces the 30 | * enumeration interface and adds a way to remove elements from a collection. 31 | * 32 | * @see Hashtable 33 | * @see Vector 34 | * @version 1.0 35 | */ 36 | public interface Enumeration { 37 | 38 | /** 39 | * Returns whether this {@code Enumeration} has more elements. 40 | * 41 | * @return {@code true} if there are more elements, {@code false} otherwise. 42 | * @see #nextElement 43 | */ 44 | boolean hasMoreElements(); 45 | 46 | /** 47 | * Returns the next element in this {@code Enumeration}. 48 | * 49 | * @return the next element.. 50 | * @throws NoSuchElementException 51 | * if there are no more elements. 52 | * @see #hasMoreElements 53 | */ 54 | E nextElement(); 55 | } 56 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/harmony/util/MapEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * From Apache Harmony (http://harmony.apache.org/) 18 | * Modification: package changed to one that is ignored (i.e., not instrumented) by Phosphor 19 | */ 20 | 21 | package edu.columbia.cs.psl.phosphor.struct.harmony.util; 22 | 23 | /** 24 | * MapEntry is an internal class which provides an implementation of Map.Entry. 25 | */ 26 | class MapEntry implements Map.Entry, Cloneable { 27 | 28 | K key; 29 | V value; 30 | 31 | interface Type { 32 | RT get(MapEntry entry); 33 | } 34 | 35 | MapEntry(K theKey) { 36 | key = theKey; 37 | } 38 | 39 | MapEntry(K theKey, V theValue) { 40 | key = theKey; 41 | value = theValue; 42 | } 43 | 44 | @Override 45 | public Object clone() { 46 | try { 47 | return super.clone(); 48 | } catch (CloneNotSupportedException e) { 49 | return null; 50 | } 51 | } 52 | 53 | @Override 54 | public boolean equals(Object object) { 55 | if (this == object) { 56 | return true; 57 | } 58 | if (object instanceof Map.Entry) { 59 | Map.Entry entry = (Map.Entry) object; 60 | return (key == null ? entry.getKey() == null : key.equals(entry 61 | .getKey())) 62 | && (value == null ? entry.getValue() == null : value 63 | .equals(entry.getValue())); 64 | } 65 | return false; 66 | } 67 | 68 | public K getKey() { 69 | return key; 70 | } 71 | 72 | public V getValue() { 73 | return value; 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | return (key == null ? 0 : key.hashCode()) 79 | ^ (value == null ? 0 : value.hashCode()); 80 | } 81 | 82 | public V setValue(V object) { 83 | V result = value; 84 | value = object; 85 | return result; 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return key + "=" + value; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/harmony/util/Pair.java: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Licensed to the Apache Software Foundation (ASF) under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The ASF licenses this file to You under the Apache License, Version 2.0 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * From Apache Harmony (http://harmony.apache.org/) 19 | * Modification: package changed to one that is ignored (i.e., not instrumented) by Phosphor, change class visibility 20 | * to public 21 | */ 22 | package edu.columbia.cs.psl.phosphor.struct.harmony.util; 23 | 24 | /** 25 | * This class implements a generic pair. 26 | */ 27 | public final class Pair { 28 | private E comp1; 29 | 30 | private T comp2; 31 | 32 | /** 33 | * @param comp1 34 | * first component 35 | * @param comp2 36 | * second component 37 | */ 38 | public Pair(E comp1, T comp2) { 39 | this.comp1 = comp1; 40 | this.comp2 = comp2; 41 | } 42 | 43 | /** 44 | * @return the first component of pair 45 | */ 46 | public final E getFirst() { 47 | return comp1; 48 | } 49 | 50 | /** 51 | * @return the second component of pair 52 | */ 53 | public final T getSecond() { 54 | return comp2; 55 | } 56 | 57 | /** 58 | * @param o 59 | * the object that will be compared for equality. 60 | * @return true if obj is instance of the 61 | * class Pair, else return false 62 | */ 63 | public final boolean equals(Object o) { 64 | 65 | if (o == null) 66 | return false; 67 | if (o == this) 68 | return true; 69 | if (!(o instanceof Pair)) 70 | return false; 71 | Pair oPair = (Pair) o; 72 | return (this.comp1.equals(oPair.comp1) && this.comp2 73 | .equals(oPair.comp2)); 74 | } 75 | 76 | /** 77 | * @return the hash code for this object. 78 | */ 79 | public final int hashCode() { 80 | return this.comp1.hashCode() ^ this.comp2.hashCode(); 81 | } 82 | 83 | /** 84 | * @return a description of the contained of an object of this class 85 | */ 86 | public final String toString() { 87 | return "PAIR = first: " + comp1 + " | " + " second: " + comp2; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Phosphor/src/main/java/edu/columbia/cs/psl/phosphor/struct/harmony/util/RandomAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * From Apache Harmony (http://harmony.apache.org/) 18 | * Modification: package changed to one that is ignored (i.e., not instrumented) by Phosphor 19 | */ 20 | 21 | package edu.columbia.cs.psl.phosphor.struct.harmony.util; 22 | 23 | /** 24 | * RandomAccess is implemented by {@code List} implementations that support fast 25 | * (usually constant time) random access. 26 | */ 27 | public interface RandomAccess { 28 | /* empty */ 29 | } 30 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/TaintUtilsTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | import org.junit.experimental.theories.DataPoints; 4 | import org.junit.experimental.theories.Theories; 5 | import org.junit.experimental.theories.Theory; 6 | import org.junit.runner.RunWith; 7 | import org.objectweb.asm.Type; 8 | 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Modifier; 11 | import java.util.*; 12 | 13 | import static org.junit.Assert.assertTrue; 14 | 15 | @RunWith(Theories.class) 16 | public class TaintUtilsTest { 17 | 18 | /** 19 | * Checks that a method descriptor remapped with 20 | * TaintUtils.remapMethodDescAndIncludeReturnHolder 21 | * is restoring via TaintUtils.getOriginalMethodDesc. 22 | */ 23 | 24 | @Theory 25 | public void checkIsSource(Method method) { 26 | boolean isStatic = Modifier.isStatic(method.getModifiers()); 27 | String originalDesc = Type.getMethodDescriptor(method); 28 | String owner = Type.getInternalName(method.getDeclaringClass()); 29 | String originalSignature = owner + "." + method.getName() + originalDesc; 30 | String taintedName = method.getName(); 31 | List previousSources = BasicSourceSinkManager.replaceAutoTaintMethods( 32 | Collections.singleton(originalSignature), 33 | BasicSourceSinkManager.AutoTaint.SOURCE); 34 | assertTrue(BasicSourceSinkManager.getInstance().isSource(owner, taintedName, originalDesc)); 35 | // Restore the sources 36 | BasicSourceSinkManager.replaceAutoTaintMethods(previousSources, 37 | BasicSourceSinkManager.AutoTaint.SOURCE); 38 | } 39 | 40 | @DataPoints 41 | public static Method[] methods() { 42 | List methods = new LinkedList<>(); 43 | List> targetClasses = Arrays.asList(String.class, HashMap.class, LinkedList.class, 44 | GregorianCalendar.class, TaintUtilsTestMethods.class); 45 | for (Class targetClass : targetClasses) { 46 | methods.addAll(Arrays.asList(targetClass.getMethods())); 47 | } 48 | return methods.toArray(new Method[0]); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/TaintUtilsTestMethods.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor; 2 | 3 | public class TaintUtilsTestMethods { 4 | 5 | public static char example(char c) { 6 | return c; 7 | } 8 | 9 | public static char[] example(char[] c) { 10 | return c; 11 | } 12 | 13 | public static char[][] example(char[][] c) { 14 | return c; 15 | } 16 | 17 | public static char[][][] example(char[][][] c) { 18 | return c; 19 | } 20 | 21 | public static String[] example(String[] s) { 22 | return s; 23 | } 24 | 25 | public static String[][] example(String[][] s) { 26 | return s; 27 | } 28 | 29 | public static String[][][] example(String[][][] s) { 30 | return s; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/struct/IntSinglyLinkedListTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class IntSinglyLinkedListTest { 8 | 9 | @Test 10 | public void testSize() { 11 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 12 | int size = 5; 13 | for(int i = 0; i < size; i++) { 14 | list.enqueue(i); 15 | } 16 | assertEquals(size, list.size()); 17 | } 18 | 19 | @Test 20 | public void testSizeEmptyList() { 21 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 22 | assertEquals(0, list.size()); 23 | } 24 | 25 | @Test 26 | public void testContains() { 27 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 28 | list.enqueue(4); 29 | list.enqueue(77); 30 | list.enqueue(8); 31 | assertTrue(list.contains(77)); 32 | assertFalse(list.contains(-4)); 33 | } 34 | 35 | @Test 36 | public void testContainsEmptyList() { 37 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 38 | assertFalse(list.contains(0)); 39 | } 40 | 41 | @Test 42 | public void testAddLast() { 43 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 44 | list.addLast(0); 45 | list.addLast(1); 46 | assertEquals(0, list.peek()); 47 | } 48 | 49 | @Test 50 | public void testAddFirst() { 51 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 52 | list.addFirst(0); 53 | list.addFirst(1); 54 | assertEquals(1, list.peek()); 55 | } 56 | 57 | @Test 58 | public void testIsEmpty() { 59 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 60 | list.enqueue(0); 61 | list.enqueue(1); 62 | list.pop(); 63 | assertFalse(list.isEmpty()); 64 | } 65 | 66 | @Test 67 | public void testIsEmptyEmptyList() { 68 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 69 | list.enqueue(0); 70 | list.pop(); 71 | assertTrue(list.isEmpty()); 72 | } 73 | 74 | @Test 75 | public void testClear() { 76 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 77 | for(int i = 0; i < 5; i++) { 78 | list.enqueue(i); 79 | } 80 | list.clear(); 81 | assertTrue(list.isEmpty()); 82 | } 83 | 84 | @Test 85 | public void testPop() { 86 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 87 | for(int i = 0; i < 5; i++) { 88 | list.enqueue(i); 89 | } 90 | for(int i = 0; i < 5; i++) { 91 | list.pop(); 92 | } 93 | assertTrue(list.isEmpty()); 94 | } 95 | 96 | @Test 97 | public void peek() { 98 | IntSinglyLinkedList list = new IntSinglyLinkedList(); 99 | list.enqueue(45); 100 | assertEquals(45, list.peek()); 101 | assertFalse(list.isEmpty()); 102 | } 103 | } -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/struct/LazyArrayObjTagsTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | public class LazyArrayObjTagsTest { 4 | 5 | /** Equals method utilizes underlying array value **/ 6 | //TODO - disabled for now, unsure how to make this place nice when not instrumented, maybe better as an integration test. 7 | //@Test 8 | //public void deepEqualIfUnderlyingValIsDeepEqual() { 9 | // 10 | // long[] longs = {1, 3, 3, 7}; 11 | // LazyArrayObjTags lazyArrayObjTags1 = new LazyLongArrayObjTags(longs); 12 | // LazyArrayObjTags lazyArrayObjTags2 = new LazyLongArrayObjTags(longs); 13 | // 14 | // Assert.assertEquals(lazyArrayObjTags1, lazyArrayObjTags2); 15 | //} 16 | } 17 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/struct/PowerSetTreeTaintTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertTrue; 7 | 8 | @SuppressWarnings("unchecked") 9 | public class PowerSetTreeTaintTest extends TaintTest { 10 | 11 | /* Checks that resetting the PowerSetTree singleton instance, makes all existing Taints' label sets be considered to be empty. */ 12 | @Test 13 | public void testResetTree() { 14 | Taint t1 = Taint.withLabel(5); 15 | Taint t2 = Taint.withLabel(99); 16 | t1 = t1.union(Taint.withLabel(4)).union(t2); 17 | assertTrue(t1.containsOnlyLabels(new Object[]{4, 5, 99})); 18 | assertTrue(t2.containsOnlyLabels(new Object[]{99})); 19 | // Reset the tree 20 | PowerSetTree.getInstance().reset(); 21 | assertTrue(t1.isEmpty()); 22 | assertTrue(t2.isEmpty()); 23 | t1 = t1.union(Taint.withLabel(77)); 24 | assertTrue(t1.containsOnlyLabels(new Object[]{77})); 25 | Taint t3 = Taint.combineTags(t2, t1); 26 | assertTrue(t3.containsOnlyLabels(new Object[]{77})); 27 | t2 = t2.union(Taint.withLabel(4)); 28 | assertTrue(t2.containsOnlyLabels(new Object[]{4})); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/struct/PowerSetTreeTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | 11 | public class PowerSetTreeTest { 12 | @Before 13 | public void reset() { 14 | PowerSetTree.getInstance().reset(); 15 | } 16 | 17 | @Test(expected = NullPointerException.class) 18 | public void testFilterEmptySetNullPredicate() { 19 | PowerSetTree.SetNode set = PowerSetTree.getInstance().emptySet(); 20 | set.filter(null); 21 | } 22 | 23 | @Test 24 | public void testFilterEmptySet() { 25 | PowerSetTree.SetNode set = PowerSetTree.getInstance().emptySet(); 26 | PowerSetTree.SetNode result = set.filter((o) -> o instanceof Integer); 27 | Assert.assertTrue(result.isEmpty()); 28 | } 29 | 30 | @Test(expected = NullPointerException.class) 31 | public void testFilterNullPredicate() { 32 | PowerSetTree.SetNode set = PowerSetTree.getInstance().makeSingletonSet(5); 33 | set.filter(null); 34 | } 35 | 36 | @Test 37 | public void testFilterByInstanceOf() { 38 | Set expected = new HashSet<>(Arrays.asList(0, 10, 50, -4, 60)); 39 | PowerSetTree.SetNode set = PowerSetTree.getInstance().makeSingletonSet(new Object()) 40 | .add(10).add("Hello").add('l').add(50).add(-4).add(60).add("world").add(0); 41 | Set result = new HashSet<>(Arrays.asList(set.filter((o) -> o instanceof Integer).getLabels())); 42 | Assert.assertEquals(expected, result); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/phosphor/struct/TaintTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.struct; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertFalse; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | @SuppressWarnings("unchecked") 10 | public abstract class TaintTest { 11 | 12 | /* Checks that a Taint instance created via the zero-argument constructor is considered to be empty. */ 13 | @Test 14 | public void testConstructEmptyTaint() { 15 | Taint t = Taint.emptyTaint(); 16 | assertTrue(t.isEmpty()); 17 | } 18 | 19 | /* Checks that a Taint instance created with an initial int label contains only that label. */ 20 | @Test 21 | public void testConstructTaintFromIntLabel() { 22 | int label = 5; 23 | Taint t = Taint.withLabel(label); 24 | assertTrue(t.containsOnlyLabels(new Object[]{label})); 25 | } 26 | 27 | /* Checks that a Taint instance created with an initial Integer label contains only that label. */ 28 | @Test 29 | public void testConstructTaintFromObjectLabel() { 30 | Integer label = 5; 31 | Taint t = Taint.withLabel(label); 32 | assertTrue(t.containsOnlyLabels(new Object[]{label})); 33 | } 34 | 35 | /* Checks that a Taint instance created with an initial null label is considered to be empty. */ 36 | @Test 37 | public void testConstructTaintFromNullLabel() { 38 | Integer label = null; 39 | Taint t = Taint.withLabel(label); 40 | assertTrue(t.isEmpty()); 41 | } 42 | 43 | /* Checks that a Taint instance created from a null Taint is considered to be empty. */ 44 | @Test 45 | public void testConstructTaintFromNullTaint() { 46 | Taint other = null; 47 | Taint t = Taint.withLabel(other); 48 | assertTrue(t.isEmpty()); 49 | } 50 | 51 | /* Checks that an empty Taint instance is considered to contain a null taint instance. */ 52 | @Test 53 | public void testEmptyTaintContainsNullTaint() { 54 | Taint t = Taint.emptyTaint(); 55 | assertTrue(t.containsLabel(null)); 56 | } 57 | 58 | /* Checks that an empty Taint instance is considered to contain a different empty taint instance. */ 59 | @Test 60 | public void testEmptyTaintContainsEmptyTaint() { 61 | Taint t = Taint.emptyTaint(); 62 | Taint t2 = Taint.emptyTaint(); 63 | assertTrue(t.isSuperset(t2)); 64 | } 65 | 66 | /* Checks that a non-empty Taint instance is considered to contains an empty Taint instance and that the empty taint 67 | * instance is not considered to contain the non-empty Taint. */ 68 | @Test 69 | public void testTaintContainsEmptyTaint() { 70 | Taint t = Taint.withLabel(2); 71 | Taint t2 = Taint.emptyTaint(); 72 | assertTrue(t.isSuperset(t2)); 73 | assertFalse(t2.isSuperset(t)); 74 | } 75 | 76 | /* Checks that a Taint that is a superset of another taint contains that subset taint and that the subset taint does not 77 | * contain the superset taint. */ 78 | @Test 79 | public void testTaintContainsTaint() { 80 | Taint t = Taint.withLabel(2); 81 | t = t.union(Taint.withLabel(4)); 82 | Taint t2 = Taint.withLabel(4); 83 | assertTrue(t.isSuperset(t2)); 84 | assertFalse(t2.isSuperset(t)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Phosphor/src/test/java/edu/columbia/cs/psl/test/phopshor/RuntimeAnnotation.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phopshor; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.*; 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Retention(RUNTIME) 10 | @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, 11 | TYPE_USE}) 12 | public @interface RuntimeAnnotation { 13 | String value() default ""; 14 | } -------------------------------------------------------------------------------- /checkstyle-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /deployment/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export GPG_TTY=$(tty) 3 | echo $DEPLOY_KEY | base64 --decode > $GITHUB_WORKSPACE/deployment/signingkey.asc 4 | gpg --batch --keyring=$GITHUB_WORKSPACE/deployment/pubring.gpg --no-default-keyring --import $GITHUB_WORKSPACE/deployment/signingkey.asc; 5 | gpg --batch --allow-secret-key-import --keyring=$GITHUB_WORKSPACE/deployment/secring.gpg --no-default-keyring --import $GITHUB_WORKSPACE/deployment/signingkey.asc; 6 | mvn -DskipTests deploy --settings $GITHUB_WORKSPACE/deployment/settings.xml -Dgpg.keyname=77787D71ED65A50488D41B82E876C482DFB8D3EB -Dgpg.passphrase=$DEPLOY_KEY_PASSPHRASE -Dgpg.publicKeyring=$GITHUB_WORKSPACE/deployment/pubring.gpg -Dgpg.secretKeyring=$GITHUB_WORKSPACE/deployment/secring.gpg 7 | -------------------------------------------------------------------------------- /deployment/settings.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | ossrh 7 | ${env.SONATYPE_USERNAME} 8 | ${env.SONATYPE_PASSWORD} 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /deployment/signingkey.asc.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmu-swe/phosphor/e38e7d6792ce92db2b99c2d6e0e1056e97abf787/deployment/signingkey.asc.enc -------------------------------------------------------------------------------- /generateMultiANewArray.php: -------------------------------------------------------------------------------- 1 | 57 | -------------------------------------------------------------------------------- /integration-tests/README.md: -------------------------------------------------------------------------------- 1 | ## Tips 2 | 3 | To skip a set of tests add the option `-P-` to Maven commands. 4 | Where <TYPE> is one of "data-flow" or "instrument". 5 | This option will disable the profile which is used to run tests of the specified type. 6 | This is useful if you wish to rerun and debug a single test class. 7 | For example, if you wanted to run and debug only `ArrayLengthObjTagITCase`, you would run: 8 | 9 | ```bash 10 | mvn -P-instrument -Dmaven.failsafe.debug -Dit.test=ArrayLengthObjTagITCase verify 11 | ``` 12 | 13 | If an instrumented Java installation has already been created, and you want to run a minimal amount of plugins when 14 | running a test you have to invoke the maven-dependency-plugin before failsafe. 15 | For example, 16 | ```bash 17 | mvn -P-instrument -Dit.test=ArrayLengthObjTagITCase dependency:properties failsafe:integration-test@data-flow 18 | ``` 19 | 20 | Add the option `-Dphosphor.forceCreation` to Maven commands to force the phosphor-instrument-maven-plugin to create a 21 | new instrumented Java installation. 22 | This will also delete associated caches of dynamically instrumented classes. -------------------------------------------------------------------------------- /integration-tests/runDacapo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | readonly BUILD_DIR=$1 4 | readonly PHOSPHOR_JAR=$2 5 | readonly DRIVER_JAR=$3 6 | readonly INST_JVM=$4 7 | readonly IS_JAVA_8=$5 8 | readonly DACAPO_DIR=$BUILD_DIR/dacapo 9 | readonly INST_DACAPO_DIR=$BUILD_DIR/dacapo-inst 10 | readonly BENCHMARKS=(avrora fop h2 jython luindex pmd sunflow xalan) 11 | #tradebeans tradesoap are disabled in this script because of the difficulty with distributing the openjdk jce.jar file with everything, then switching it in... 12 | #we don't run batik anymore because it's an enormous pain to automatically set up oracle java... 13 | #tomcat started crashing on travis 14 | #if you want to run them, copy the jce.jar file from an openjdk distribution of the same version into your hotspot jvm that you are going to instrument before instrumenting it. 15 | # (export controls are annoying) 16 | # eclipse doesn't work without big hacks on travis 17 | # ..also disable lusearch because travis seems unhappy when we run it there 18 | if [ ! -d "$DACAPO_DIR" ]; then 19 | echo "Downloading dacapo jar" 20 | mkdir -p "$DACAPO_DIR" 21 | cd "$DACAPO_DIR" 22 | wget --quiet https://www.jonbell.net/dacapo-9.12-MR1-bach.jar 23 | unzip -qq dacapo-9.12-MR1-bach.jar 24 | fi 25 | cd "$BUILD_DIR" 26 | 27 | phosphor_args="" 28 | if [ "$IS_JAVA_8" == "true" ]; then 29 | phosphor_args="-java8" 30 | fi 31 | 32 | if [ ! -d "$INST_DACAPO_DIR" ]; then 33 | echo "Creating data flow instrumented dacapo" 34 | java -Xmx8g -jar "$DRIVER_JAR" -q -forceUnboxAcmpEq -withEnumsByValue $phosphor_args "$DACAPO_DIR" "$INST_DACAPO_DIR" 35 | else 36 | echo "Not regenerating data flow instrumented dacapo" 37 | fi 38 | errors=0 39 | echo "Trying data flow benchmarks, one iteration only" 40 | for bm in "${BENCHMARKS[@]}"; do 41 | $INST_JVM -Xmx4g \ 42 | -Xbootclasspath/a:"$PHOSPHOR_JAR" \ 43 | -javaagent:"$PHOSPHOR_JAR" \ 44 | -cp "$INST_DACAPO_DIR" \ 45 | -Declipse.java.home="$JAVA_HOME" \ 46 | -Djava.awt.headless=true \ 47 | Harness "$bm" 48 | if [ $? -ne 0 ]; then 49 | errors=var=$((errors + 1)) 50 | echo "ERROR!!!" 51 | fi 52 | done 53 | 54 | echo "Total errors: $errors" 55 | if [ $errors -ne 0 ]; then 56 | exit 255 57 | fi 58 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/Foo.java: -------------------------------------------------------------------------------- 1 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 2 | 3 | import java.io.*; 4 | import java.lang.reflect.Array; 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.util.Arrays; 8 | import java.util.concurrent.atomic.AtomicLong; 9 | import java.util.function.BiFunction; 10 | import java.util.function.DoubleSupplier; 11 | import java.util.function.UnaryOperator; 12 | 13 | public class Foo { 14 | public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ClassNotFoundException { 15 | // DoubleSupplier supplier = ((DoubleSupplier) Foo::getFloat); 16 | // double d = supplier.getAsDouble(); 17 | // Constructor constructor = Foo.class.getConstructor(new Class[0]); 18 | // for(int i = 0; i < 10000; i++) { 19 | // String[] arr = new String[]{"a", "b"}; 20 | //// String[] newArr = Arrays.copyOf(arr, 5); 21 | // String[] newArr = (String[]) Array.newInstance(arr.getClass().getComponentType(), 5); 22 | //// System.out.println(Arrays.toString(newArr)); 23 | // constructor.newInstance(); 24 | // System.out.println(i); 25 | // } 26 | // System.out.println(instances); 27 | 28 | // BiFunction func = (x1, x2) -> x1 + x2; 29 | // 30 | // Integer result = func.apply(2, 3); 31 | // 32 | // System.out.println(result); // 5 33 | 34 | //AtomicLong al = new AtomicLong(); 35 | //System.out.println(al.get()); 36 | // 37 | ////System.out.println(al.getAndIncrement()); 38 | ////System.out.println(al.getAndIncrement()); 39 | ////System.out.println(al.getAndIncrement()); 40 | //long l = 10; 41 | //System.out.println(Long.toString(l)); 42 | 43 | //ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 44 | //ObjectOutputStream outStream = new ObjectOutputStream(byteStream); 45 | ////outStream.writeInt(10); 46 | //outStream.writeObject(new int[10]); 47 | //outStream.close(); 48 | // 49 | //ObjectInputStream inStream = new ObjectInputStream(new ByteArrayInputStream(byteStream.toByteArray())); 50 | ////int outI = inStream.readInt(); 51 | //int[] ar = (int[]) inStream.readObject(); 52 | // 53 | //inStream.close(); 54 | //System.out.println(ar); 55 | int i = 0; 56 | 57 | String str = "Some tainted data " + (++i); 58 | System.out.println(str); 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/BaseClass.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public abstract class BaseClass { 4 | 5 | public String imei; 6 | 7 | public abstract String foo(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/BaseClass2.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public abstract class BaseClass2 { 4 | 5 | public abstract String fooMultiTaint(); 6 | 7 | public abstract void barMultiTaint(String s); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/ConcreteClass.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public class ConcreteClass extends BaseClass { 4 | 5 | @Override 6 | public String foo() { 7 | return imei; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/ConcreteClass2.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import edu.columbia.cs.psl.test.phosphor.DroidBenchObjTagITCase; 6 | 7 | 8 | public class ConcreteClass2 extends BaseClass2 { 9 | 10 | @Override 11 | public String fooMultiTaint() { 12 | return DroidBenchObjTagITCase.taintedString(); 13 | } 14 | 15 | @Override 16 | public void barMultiTaint(String s) { 17 | assertTrue(DroidBenchObjTagITCase.getTaint(s) != 0); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/DataStore.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public class DataStore { 4 | public String field; 5 | } 6 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/Datacontainer.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public class Datacontainer { 4 | private String secret; 5 | private String description; 6 | 7 | 8 | public String getSecret() { 9 | return secret; 10 | } 11 | public void setSecret(String secret) { 12 | this.secret = secret; 13 | } 14 | public String getDescription() { 15 | return description; 16 | } 17 | public void setDescription(String description) { 18 | this.description = description; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/General.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | 4 | public abstract class General { 5 | 6 | public abstract String getInfoMultiTaint(); 7 | } 8 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/ReflectiveClass.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public class ReflectiveClass { 4 | 5 | private String imei = ""; 6 | 7 | public void setImei(String imei) { 8 | this.imei = imei; 9 | } 10 | 11 | public String getImei() { 12 | return this.imei; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/VarA.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | import edu.columbia.cs.psl.test.phosphor.DroidBenchObjTagITCase; 4 | 5 | public class VarA extends General { 6 | 7 | @Override 8 | public String getInfoMultiTaint() { 9 | return DroidBenchObjTagITCase.taintedString("abcd"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/de/ecspride/VarB.java: -------------------------------------------------------------------------------- 1 | package de.ecspride; 2 | 3 | public class VarB extends General { 4 | 5 | @Override 6 | public String getInfoMultiTaint() { 7 | return "abc"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/phosphor/util/IgnoredTestUtil.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.util; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.AutoTaintLabel; 4 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 5 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 6 | import edu.columbia.cs.psl.phosphor.control.ControlFlowStack; 7 | import sun.misc.Unsafe; 8 | 9 | import java.lang.reflect.Field; 10 | 11 | /* Provides utility methods ignored by Phosphor. */ 12 | public class IgnoredTestUtil { 13 | 14 | private IgnoredTestUtil() { 15 | // Prevents this class from being instantiated 16 | } 17 | static Unsafe unsafe; 18 | private static Unsafe getUnsafe(){ 19 | if(unsafe == null){ 20 | try { 21 | Field f = Unsafe.class.getDeclaredField("theUnsafe"); 22 | f.setAccessible(true); 23 | unsafe = (Unsafe) f.get(null); 24 | } catch (NoSuchFieldException | IllegalAccessException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | return unsafe; 29 | } 30 | 31 | /* Replaces the taint tag for each character of the specified with a taint tag containing only the specified label. 32 | * If the specified label is null clears the specified String's characters' tags */ 33 | public static void setStringCharTaints(String str, Object label) { 34 | Taint tag = label == null ? Taint.emptyTaint() : Taint.withLabel(label); 35 | Taint[] tags = new Taint[str.length()]; 36 | for (int i = 0; i < tags.length; i++) { 37 | tags[i] = tag; 38 | } 39 | MultiTainter.setStringCharTaints(str, tags); 40 | } 41 | 42 | @SuppressWarnings("unused") 43 | public static void setStringCharTaints$$PHOSPHORTAGGED(String str, Object label, ControlFlowStack ctrl) { 44 | setStringCharTaints(str, label); 45 | } 46 | 47 | public static void setStringCharTaints(String str, Taint tag, Object label, Taint tag2) { 48 | setStringCharTaints(str, label); 49 | } 50 | 51 | public static AutoTaintLabel createAutoTaintLabel(String source, StackTraceElement[] trace) { 52 | return new AutoTaintLabel(source, trace); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/AnnotationInstCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | import java.lang.reflect.Method; 11 | 12 | public class AnnotationInstCase extends BasePhosphorTest{ 13 | @Test 14 | public void testEnum() throws ReflectiveOperationException { 15 | Method method = Example.class.getDeclaredMethod("x"); 16 | ExampleAnnotation annotation = method.getAnnotation(ExampleAnnotation.class); 17 | Assert.assertNotNull(annotation); 18 | Assert.assertEquals(ExampleAnnotation.Color.BLUE, annotation.color()); 19 | } 20 | 21 | public static class Example { 22 | @ExampleAnnotation(color = ExampleAnnotation.Color.BLUE) 23 | void x() {} 24 | } 25 | 26 | @Target(ElementType.METHOD) 27 | @Retention(RetentionPolicy.RUNTIME) 28 | public @interface ExampleAnnotation { 29 | Color color(); 30 | 31 | enum Color { 32 | RED, 33 | BLUE, 34 | GREEN; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/ArrayArgWrapperObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | import static org.junit.Assert.assertNull; 8 | 9 | public class ArrayArgWrapperObjTagITCase { 10 | 11 | @Test 12 | public void testArgWrapperTaintNotLeaked() { 13 | byte[] b = new byte[]{1, 2, 3}; 14 | Arrays.copyOf(b, 3); // `copyof` calls System.arraycopy which is not instrumented. 15 | checkNull(null); 16 | } 17 | 18 | @Test 19 | public void testNoUnwrapForNull() { 20 | checkNull(null); 21 | } 22 | 23 | public void checkNull(byte[] input) { 24 | assertNull(input); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/ArrayLengthObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class ArrayLengthObjTagITCase extends BaseMultiTaintClass { 12 | 13 | @Test 14 | public void testArrayLengthTaintedPrimArray() throws Exception { 15 | int i = MultiTainter.taintedInt(5, "foo"); 16 | Taint t = MultiTainter.getTaint(i); 17 | int[] ar = new int[i]; 18 | Taint r = MultiTainter.getTaint(ar.length); 19 | assertEquals(t, r); 20 | } 21 | 22 | @Test 23 | public void testArrayLengthTaintedObjArray() throws Exception { 24 | int i = MultiTainter.taintedInt(5, "foo"); 25 | Taint t = MultiTainter.getTaint(i); 26 | String[] ar = new String[i]; 27 | Taint r = MultiTainter.getTaint(ar.length); 28 | assertEquals(t, r); 29 | } 30 | 31 | @Test 32 | public void testArrayLengthTainted2DPrimArray() throws Exception { 33 | int i = MultiTainter.taintedInt(5, "foo"); 34 | Taint t = MultiTainter.getTaint(i); 35 | int[][] ar = new int[i][i]; 36 | Taint r = MultiTainter.getTaint(ar.length); 37 | assertEquals(t, r); 38 | r = MultiTainter.getTaint(ar[0].length); 39 | assertEquals(t, r); 40 | } 41 | 42 | @Test 43 | public void testArrayLengthTainted2DObjArray() throws Exception { 44 | int i = MultiTainter.taintedInt(5, "foo"); 45 | Taint t = MultiTainter.getTaint(i); 46 | String[][] ar = new String[i][i]; 47 | Taint r = MultiTainter.getTaint(ar.length); 48 | assertEquals(t, r); 49 | r = MultiTainter.getTaint(ar[0].length); 50 | assertEquals(t, r); 51 | } 52 | 53 | @Test 54 | public void testTaintedIndexLoad() throws Exception { 55 | int i = MultiTainter.taintedInt(5, "foo"); 56 | Taint t = MultiTainter.getTaint(i); 57 | 58 | int[] ar = new int[10]; 59 | int j = ar[i]; 60 | Taint r = MultiTainter.getTaint(ar[i]); 61 | assertEquals(t, r); 62 | String[] s = new String[10]; 63 | for (j = 0; j < s.length; j++) { 64 | s[j] = "b"; 65 | } 66 | r = MultiTainter.getTaint(s[i]); 67 | assertEquals(t, r); 68 | } 69 | 70 | @Test 71 | public void testTaintedIndexStore() throws Exception { 72 | int i = MultiTainter.taintedInt(5, "foo"); 73 | Taint t = MultiTainter.getTaint(i); 74 | 75 | int[] ar = new int[10]; 76 | ar[i] = 10; 77 | Taint r = MultiTainter.getTaint(ar[5]); 78 | assertEquals(t, r); 79 | 80 | String[] s = new String[10]; 81 | s[i] = "bar"; 82 | r = MultiTainter.getTaint(s[5]); 83 | assertEquals(t, r); 84 | } 85 | 86 | @Test 87 | public void testArrayListGet() throws Exception { 88 | ArrayList al = new ArrayList(); 89 | al.add("foo"); 90 | int i = MultiTainter.taintedInt(0, "foo"); 91 | System.out.println(MultiTainter.getTaint(al.get(i))); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/ArrayOptimizationObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 5 | import org.junit.Test; 6 | 7 | public class ArrayOptimizationObjTagITCase extends BaseMultiTaintClass{ 8 | 9 | @Test 10 | public void testNewArrayConstantClearsTaint(){ 11 | 12 | byte[] b = new byte[10]; 13 | b[0] = MultiTainter.taintedByte((byte)1,"Foo"); 14 | b[0] = 10; 15 | 16 | assertNullOrEmpty(MultiTainter.getTaint(b[0])); 17 | } 18 | 19 | @Test 20 | public void testHashCodeGetsTaint() { 21 | 22 | byte[] b = new byte[10]; 23 | b[0] = MultiTainter.taintedByte((byte)1,"Foo"); 24 | b[1] = MultiTainter.taintedByte((byte)1,"Bar"); 25 | int taggedHashCode = b.hashCode(); 26 | 27 | Taint taint = MultiTainter.getTaint(taggedHashCode); 28 | assertNullOrEmpty(taint); 29 | } 30 | 31 | @Test 32 | public void testEqualsResultGetsTag() { 33 | 34 | byte[] b = new byte[10]; 35 | b[0] = MultiTainter.taintedByte((byte)1,"Foo"); 36 | b[1] = MultiTainter.taintedByte((byte)1,"Bar"); 37 | boolean taggedEquals = b.equals(null); 38 | 39 | Taint taint = MultiTainter.getTaint(taggedEquals); 40 | assertNullOrEmpty(taint); 41 | } 42 | 43 | @Test 44 | public void testReferenceReassignmentClearsTaint() { 45 | 46 | byte[] b = new byte[10]; 47 | b[0] = MultiTainter.taintedByte((byte)1,"Foo"); 48 | b[1] = MultiTainter.taintedByte((byte)1,"Bar"); 49 | b = new byte[10]; 50 | boolean taggedEquals = b.equals(null); 51 | 52 | Taint taint = MultiTainter.getTaint(taggedEquals); 53 | assertNullOrEmpty(taint); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/AtomicReferenceArrayObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.junit.Test; 5 | 6 | import java.util.concurrent.atomic.AtomicReferenceArray; 7 | 8 | public class AtomicReferenceArrayObjTagITCase extends BaseMultiTaintClass { 9 | static class Holder { 10 | int x; 11 | } 12 | 13 | @Test 14 | public void testGetAndSetReference() { 15 | AtomicReferenceArray array = new AtomicReferenceArray(10); 16 | array.set(0, MultiTainter.taintedReference(new Holder(), "tag")); 17 | assertTaintHasLabel(MultiTainter.getTaint(array.get(0)), "tag"); 18 | array.set(0, new Holder()); 19 | assertNullOrEmpty(MultiTainter.getTaint(array.get(0))); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.runtime.TaintSinkError; 5 | import org.junit.After; 6 | 7 | import static edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass.assertNonNullTaint; 8 | 9 | public class AutoTaintConstructorsImplicitITCase extends AutoTaintConstructorsObjTagITCase { 10 | /** 11 | * All tests are inherited from the obj tag test. 12 | */ 13 | 14 | @After 15 | public void resetState() { 16 | MultiTainter.getControlFlow().reset(); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/AutoTaintImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.junit.After; 5 | 6 | public class AutoTaintImplicitITCase extends AutoTaintObjTagITCase { 7 | 8 | /** 9 | * All tests are inherited from the obj tag test. 10 | */ 11 | @After 12 | public void resetState() { 13 | MultiTainter.getControlFlow().reset(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/BaseMultiTaintClass.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 5 | 6 | import java.util.Arrays; 7 | 8 | import static org.junit.Assert.assertNotNull; 9 | import static org.junit.Assert.fail; 10 | 11 | public class BaseMultiTaintClass extends BasePhosphorTest { 12 | 13 | public static void assertNullOrEmpty(Taint taint) { 14 | if(taint != null && !taint.isEmpty()) { 15 | fail("Expected null taint. Got: " + taint); 16 | } 17 | } 18 | 19 | public static void assertNoTaint(String obj) { 20 | Taint taint = MultiTainter.getTaint(obj.toCharArray()[0]); 21 | if(taint != null && !taint.isEmpty()) { 22 | fail("Expected null taint. Got: " + taint); 23 | } 24 | } 25 | 26 | public static void assertNonNullTaint(Object obj) { 27 | Taint t = MultiTainter.getTaint(obj); 28 | assertNotNull(obj); 29 | if(t == null || t.isEmpty()) { 30 | fail("Expected non-null taint - got: " + t); 31 | } 32 | } 33 | 34 | public static void assertNonNullTaint(Taint obj) { 35 | assertNotNull(obj); 36 | if(obj.isEmpty()) { 37 | fail("Expected non-null taint - got: " + obj); 38 | } 39 | } 40 | 41 | public static void assertTaintHasLabel(Taint obj, Object lbl) { 42 | assertNotNull(obj); 43 | if(!obj.containsLabel(lbl)) { 44 | fail("Expected taint contained " + lbl + ", has " + obj); 45 | } 46 | } 47 | 48 | public static void assertTaintHasOnlyLabel(Taint obj, Object lbl) { 49 | assertNotNull(obj); 50 | if(!obj.containsOnlyLabels(new Object[]{lbl})) { 51 | fail("Expected taint contained ONLY " + lbl + ", found " + obj); 52 | } 53 | 54 | } 55 | 56 | public static void assertTaintHasOnlyLabels(Taint obj, Object... lbl) { 57 | assertNotNull(obj); 58 | if(!obj.containsOnlyLabels(lbl)) { 59 | fail("Expected taint contained ONLY " + Arrays.toString(lbl) + ", found " + obj); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/BasePhosphorTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.Phosphor; 4 | import org.junit.After; 5 | import org.junit.Assert; 6 | import org.junit.Before; 7 | 8 | public class BasePhosphorTest { 9 | @Before 10 | public void clearErrorFlag() { 11 | Phosphor.INSTRUMENTATION_EXCEPTION_OCCURRED = false; 12 | } 13 | 14 | @After 15 | public void checkForError() { 16 | if(Phosphor.INSTRUMENTATION_EXCEPTION_OCCURRED) { 17 | Assert.fail("Instrumentation error occurred"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/CharacterCodePointObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.util.IgnoredTestUtil; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class CharacterCodePointObjTagITCase extends BasePhosphorTest { 11 | @Test 12 | public void testCodePointAt(){ 13 | char[] c = new char[1]; 14 | c[0] = MultiTainter.taintedChar((char)4,"foo"); 15 | int i = Character.codePointAt(c,0); 16 | Assert.assertNotNull(MultiTainter.getTaint(i)); 17 | 18 | final char[] crar = Character.toChars(Character.codePointAt(c, 0)); 19 | Assert.assertNotNull(MultiTainter.getTaint(crar[0])); 20 | } 21 | 22 | @Test 23 | public void testCodePointBefore() { 24 | char[] s = {'a', 'b', 'c', 'd', 'e'}; 25 | for (int i = 0; i < 5; i++) { 26 | s[i] = MultiTainter.taintedChar(s[i], i); 27 | } 28 | 29 | for (int i = 1; i <= 5; i++) { 30 | int ret = Character.codePointBefore(s, i); 31 | assertEquals(MultiTainter.getTaint(ret).getLabels()[0], i-1); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/DeepImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | public class DeepImplicitITCase extends BasePhosphorTest { 8 | int x; 9 | public void setX(int x){ 10 | this.x=x; 11 | } 12 | public class Holder{ 13 | int z; 14 | 15 | public void setZ(int z) { 16 | this.z = z; 17 | } 18 | public void otherSetZ(int z){ 19 | this.z = z; 20 | } 21 | } 22 | static Holder oh; 23 | Holder h; 24 | 25 | 26 | @Test 27 | public void testSimpleLV(){ 28 | int l = 0; 29 | int y = MultiTainter.taintedInt(10,"testSimpleLV"); 30 | if(y >100) 31 | l = 10; 32 | System.out.println(MultiTainter.getTaint(l)); 33 | Assert.assertNotNull(MultiTainter.getTaint(l)); 34 | } 35 | @Test 36 | public void testMethodsOfFields(){ 37 | // int x = 10; 38 | h = new Holder(); 39 | oh = new Holder(); 40 | int y = MultiTainter.taintedInt(10,"testMethodsOfFields"); 41 | if(y > 100) 42 | h.setZ(40); 43 | if(y > 1000) 44 | oh.otherSetZ(455); 45 | System.out.println(MultiTainter.getTaint(h)); 46 | System.out.println(MultiTainter.getTaint(oh)); 47 | Assert.assertNotNull(MultiTainter.getTaint(h)); 48 | Assert.assertNotNull(MultiTainter.getTaint(oh)); 49 | } 50 | @Test 51 | public void testFieldsOfThis(){ 52 | x = 0; 53 | int y = MultiTainter.taintedInt(10,"testFieldsOfThis"); 54 | if(y > 100) 55 | this.x =10; 56 | System.out.println(MultiTainter.getTaint(this.x)); 57 | Assert.assertNotNull(MultiTainter.getTaint(this.x)); 58 | } 59 | 60 | public static void main(String[] args) { 61 | new DeepImplicitITCase().testFieldsOfThis(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/EnumObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertSame; 5 | 6 | import org.junit.Test; 7 | 8 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 9 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 10 | 11 | public class EnumObjTagITCase extends BasePhosphorTest { 12 | @Test 13 | public void testEnumFlow() throws Exception { 14 | String s = "abcd"; 15 | // MultiTainter.taintedObject(s, Taint.withLabel("foo")); 16 | s = MultiTainter.taintedReference(s, "foo"); 17 | assertEquals(Taint.withLabel("foo"), MultiTainter.getTaint(s)); 18 | Dummy x = Dummy.a; 19 | Dummy y = Dummy.valueOf(s); 20 | assertEquals(Taint.withLabel("foo"), MultiTainter.getTaint(y)); 21 | assertSame(y, Dummy.abcd); 22 | } 23 | @Test 24 | public void testArrayCmpEq() throws Exception { 25 | int[] a = new int[5]; 26 | Object f = a; 27 | assertSame(f, a); 28 | } 29 | enum Dummy { 30 | a("A"),b("B"),c("C"),d("D"),abcd("ABCD"); 31 | String val; 32 | Dummy(String s) 33 | { 34 | this.val = s; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/ExceptionImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import junit.framework.AssertionFailedError; 5 | import org.junit.Test; 6 | 7 | public class ExceptionImplicitITCase extends BaseMultiTaintClass{ 8 | 9 | @Test 10 | public void testUnthrownExceptionTaintsNextLineOfControl(){ 11 | 12 | int x = MultiTainter.taintedInt(10,"testUnthrownExceptionTaintsNextLineOfControl"); 13 | if(x == 1) 14 | throw new AssertionFailedError(); 15 | int y = 10; // x's taint should propagate into y 16 | assertTaintHasOnlyLabel(MultiTainter.getTaint(y),"testUnthrownExceptionTaintsNextLineOfControl"); 17 | } 18 | 19 | @Test 20 | public void testUnthrownExceptionStopsTaintingAtTry(){ 21 | try { 22 | int x = MultiTainter.taintedInt(10, "testUnthrownExceptionStopsTaintingAtTry"); 23 | if (x == 1) 24 | throw new AssertionFailedError(); 25 | }catch(Throwable t){ 26 | //nop 27 | } 28 | int y = 10; // x's taint should NOT propagate into y 29 | assertNullOrEmpty(MultiTainter.getTaint(y)); 30 | } 31 | 32 | @Test 33 | public void testCatchBlockNotTaken(){ 34 | int y = 10; // x's taint should NOT propagate into y 35 | try { 36 | int x = MultiTainter.taintedInt(10, "testCatchBlockNotTaken"); 37 | if (x == 1) 38 | throw new AssertionFailedError(); 39 | }catch(Throwable t){ 40 | //nop 41 | y = 5; 42 | } 43 | assertTaintHasOnlyLabel(MultiTainter.getTaint(y),"testCatchBlockNotTaken"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/ExceptionalFlowImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.junit.After; 5 | import org.junit.Test; 6 | 7 | public class ExceptionalFlowImplicitITCase extends BaseMultiTaintClass { 8 | @After 9 | public void resetState() { 10 | MultiTainter.getControlFlow().reset(); 11 | } 12 | 13 | public void checkAndThrow(int in) { 14 | if(in < 0) { 15 | throw new IllegalStateException(); 16 | } 17 | } 18 | 19 | @Test 20 | public void testThrownException() { 21 | resetState(); 22 | int x = MultiTainter.taintedInt(5, "testThrownExceptions.X"); 23 | int y = 10; 24 | int z = 10; 25 | try { 26 | checkAndThrow(x); 27 | } catch(IllegalStateException ex) { 28 | y = 4; 29 | } 30 | z = 45; 31 | assertTaintHasOnlyLabel(MultiTainter.getTaint(y), "testThrownExceptions.X"); 32 | assertNullOrEmpty(MultiTainter.getTaint(z)); 33 | } 34 | 35 | @Test 36 | public void testThrownExceptionNested() { 37 | resetState(); 38 | int x = MultiTainter.taintedInt(5, "testThrownExceptionsNested.X"); 39 | int x2 = MultiTainter.taintedInt(5, "testThrownExceptionsNested.X2"); 40 | int y = 10; 41 | int z = 10; 42 | int q = 40; 43 | try { 44 | try { 45 | checkAndThrow(x); 46 | if(x2 > 5) { 47 | throw new NullPointerException(); 48 | } 49 | } catch(NullPointerException npe) { 50 | y = 45; 51 | } 52 | } catch(IllegalStateException ex) { 53 | z = 4; 54 | } 55 | q = 56; 56 | assertTaintHasOnlyLabels(MultiTainter.getTaint(y), "testThrownExceptionsNested.X", "testThrownExceptionsNested.X2"); 57 | assertTaintHasOnlyLabel(MultiTainter.getTaint(z), "testThrownExceptionsNested.X"); 58 | assertNullOrEmpty(MultiTainter.getTaint(q)); 59 | } 60 | 61 | @Test 62 | public void testUnthrownExceptions() { 63 | resetState(); 64 | int x = MultiTainter.taintedInt(10, "testUnthrownExceptions.X"); 65 | int y = 10; 66 | int z = 5; 67 | try { 68 | checkAndThrow(x); 69 | } catch(Throwable t) { 70 | y = 1000; 71 | } 72 | z = 5; 73 | assertTaintHasOnlyLabel(MultiTainter.getTaint(y), "testUnthrownExceptions.X"); 74 | assertNullOrEmpty(MultiTainter.getTaint(z)); 75 | 76 | } 77 | 78 | @Test 79 | public void testUnthrownExceptionsReturn() { 80 | resetState(); 81 | int x = MultiTainter.taintedInt(10, "testUnthrownExceptionsReturn.X"); 82 | int y = 10; 83 | int z = 5; 84 | try { 85 | checkAndThrow(x); 86 | } catch(Throwable t) { 87 | y = 1000; 88 | return; 89 | } 90 | z = 5; 91 | assertTaintHasOnlyLabel(MultiTainter.getTaint(y),"testUnthrownExceptionsReturn.X"); 92 | assertNullOrEmpty(MultiTainter.getTaint(z)); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/FakeEnumTest.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 5 | 6 | public class FakeEnumTest extends BasePhosphorTest{ 7 | 8 | public static void main(String[] args) { 9 | System.out.println(Foo.A); 10 | String a = "A"; 11 | MultiTainter.taintedObject(a, Taint.withLabel("Z")); 12 | System.out.println(Foo.valueOf(a)); 13 | System.out.println(MultiTainter.getTaint(Foo.valueOf(a))); 14 | System.out.println(MultiTainter.getTaint(a)); 15 | System.out.println(MultiTainter.getTaint(Foo.A)); 16 | 17 | } 18 | 19 | enum Foo { 20 | A,B,C; 21 | String baz; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/InheritedAutoTaintObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | import org.junit.Test; 3 | 4 | 5 | public class InheritedAutoTaintObjTagITCase extends BaseMultiTaintClass { 6 | 7 | public interface TaintSourceInterface { 8 | int getSource(); 9 | } 10 | 11 | public interface ChildInterface extends TaintSourceInterface { 12 | 13 | } 14 | 15 | public static class Grandchild implements ChildInterface { 16 | public int getSource() { 17 | return 2; 18 | } 19 | } 20 | 21 | public static class TaintSourceClass { 22 | public int getSource() { 23 | return 7; 24 | } 25 | } 26 | 27 | public static class ChildClass extends TaintSourceClass { 28 | 29 | } 30 | 31 | public static class Grandchild2 extends ChildClass { 32 | @Override 33 | public int getSource() { 34 | return 3; 35 | } 36 | } 37 | 38 | /* Tests that the source method of a grandchild class of an interface whose source method is marked as a taint source 39 | * is also treated as a taint source. */ 40 | @Test 41 | public void testInterfaceSourceMethodInherited() throws Exception { 42 | Grandchild obj = new Grandchild(); 43 | int taintedInt = obj.getSource(); 44 | assertNonNullTaint(taintedInt); 45 | } 46 | 47 | /* Tests that the source method of a grandchild class of a class whose source method is marked as a taint source 48 | * is also treated as a taint source. */ 49 | @Test 50 | public void testClassSourceMethodInherited() throws Exception { 51 | Grandchild2 obj = new Grandchild2(); 52 | int taintedInt = obj.getSource(); 53 | assertNonNullTaint(taintedInt); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/LambdaImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Test; 4 | 5 | import java.security.PrivilegedActionException; 6 | import java.security.PrivilegedExceptionAction; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.function.BiConsumer; 10 | import java.util.function.DoubleSupplier; 11 | import java.util.function.ObjDoubleConsumer; 12 | import java.util.function.Supplier; 13 | import java.util.stream.Collectors; 14 | import java.util.stream.IntStream; 15 | 16 | import static java.security.AccessController.doPrivileged; 17 | 18 | public class LambdaImplicitITCase extends BasePhosphorTest { 19 | 20 | @Test 21 | public void testDoubleConsumer() throws Exception{ 22 | ObjDoubleConsumer consumer = (ll, l) -> { 23 | ll[0] += l; 24 | }; 25 | consumer.accept(new double[1], 1.0); 26 | 27 | BiConsumer consumer2 = (ll, rr) -> { 28 | ll[0] += rr[0]; 29 | }; 30 | consumer2.accept(new double[1], new double[1]); 31 | } 32 | 33 | float getFloat() { 34 | return 0f; 35 | } 36 | 37 | @Test 38 | public void testFloat2DoubleSupplier() throws Exception { 39 | DoubleSupplier supplier = ((DoubleSupplier) this::getFloat); 40 | double d = supplier.getAsDouble(); 41 | } 42 | 43 | @Test 44 | public void testCollectors() throws Exception{ 45 | List givenList = Arrays.asList("a", "bb", "ccc", "dd"); 46 | givenList.stream().collect(Collectors.toList()); 47 | } 48 | 49 | @Test 50 | public void testIntStreamsDontCrash() throws Exception { 51 | int sum = IntStream.of(1, 2, 3, 4, 5).sum(); //creates a bunch of lambdas 52 | } 53 | 54 | @Test 55 | public void testEmptyLambda() throws Exception { 56 | Runnable r = () -> { 57 | }; 58 | } 59 | 60 | @Test 61 | public void testLambdaIntArg() throws Exception { 62 | intArg(new int[10]); 63 | } 64 | 65 | void initStreams(int[] arg) { 66 | } 67 | 68 | void intArg(int[] arg) { 69 | try { 70 | doPrivileged((PrivilegedExceptionAction) () -> { 71 | initStreams(arg); 72 | return null; 73 | }); 74 | } catch (PrivilegedActionException ex) { 75 | } 76 | } 77 | @Test 78 | public void testSupplier() throws Exception { 79 | Supplier supplier = () -> new double[3]; 80 | double[] d = supplier.get(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/LocalVariableInstCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Test; 4 | 5 | public class LocalVariableInstCase { 6 | @Test 7 | public void testLocalVariableVerifySuccessWhenTaintDisabled() { 8 | // We only need to load this class to trigger JVM verification. 9 | for (ClassWithLargeMethod value : ClassWithLargeMethod.values()) { 10 | // NOOP 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/OrImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.junit.After; 5 | import org.junit.Test; 6 | 7 | public class OrImplicitITCase extends BaseMultiTaintClass { 8 | 9 | @After 10 | public void resetState() { 11 | MultiTainter.getControlFlow().reset(); 12 | } 13 | @Test 14 | public void testOneWayOr() throws Exception { 15 | resetState(); 16 | int x = MultiTainter.taintedInt(-1, "x"); 17 | int y = MultiTainter.taintedInt(6, "y"); 18 | int result = 0; 19 | int other = 0; 20 | if (x > 0 || y > 0) { 21 | result += 1; 22 | } 23 | other+=5; 24 | assertTaintHasOnlyLabels(MultiTainter.getTaint(result), "x", "y"); 25 | assertNullOrEmpty(MultiTainter.getTaint(other)); 26 | } 27 | 28 | @Test 29 | public void testOneWayOr2() throws Exception { 30 | resetState(); 31 | int x = MultiTainter.taintedInt(1, "x"); 32 | int y = MultiTainter.taintedInt(6, "y"); 33 | int result = 0; 34 | int other = 0; 35 | if (x > 0 || y > 0) { 36 | result += 1; 37 | } 38 | other+=5; 39 | assertTaintHasOnlyLabels(MultiTainter.getTaint(result), "x"); 40 | assertNullOrEmpty(MultiTainter.getTaint(other)); 41 | } 42 | 43 | @Test 44 | public void testTwoWayOr() throws Exception { 45 | resetState(); 46 | int x = MultiTainter.taintedInt(-1, "x"); 47 | int y = MultiTainter.taintedInt(6, "y"); 48 | int z = MultiTainter.taintedInt(8, "z"); 49 | 50 | int result = 0; 51 | int other = 0; 52 | if (x > 0 || y > 0) { 53 | result += 1; 54 | if(z > 3) 55 | result += 2; 56 | } 57 | other+=5; 58 | assertTaintHasOnlyLabels(MultiTainter.getTaint(result), "x", "y","z"); 59 | assertNullOrEmpty(MultiTainter.getTaint(other)); 60 | } 61 | @Test 62 | public void testTwoWayOr2() throws Exception { 63 | resetState(); 64 | int x = MultiTainter.taintedInt(2, "x"); 65 | int y = MultiTainter.taintedInt(6, "y"); 66 | int z = MultiTainter.taintedInt(8, "z"); 67 | 68 | int result = 0; 69 | int other = 0; 70 | if (x > 0 || y > 0) { 71 | result += 1; 72 | if(z > 3) 73 | result += 2; 74 | } 75 | other+=5; 76 | assertTaintHasOnlyLabels(MultiTainter.getTaint(result), "x","z"); 77 | assertNullOrEmpty(MultiTainter.getTaint(other)); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/OverTaintingImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Test; 4 | 5 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 6 | public class OverTaintingImplicitITCase extends BasePhosphorTest { 7 | static int v1; 8 | static int v2; 9 | 10 | @Test 11 | public void testControlFlowCraziness() throws Exception { 12 | System.out.println("OK"); 13 | v1 = 5; 14 | v2 = v1+6; 15 | //End Test 16 | System.out.println(v1); 17 | int v3 = v2 + 11; 18 | // assertEquals(22, v3); 19 | System.out.println(MultiTainter.getTaint(v3)); 20 | System.out.println(MultiTainter.getTaint(v2)); 21 | 22 | System.out.println(v2); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/ParameterAnnotationObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.lang.annotation.Annotation; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.reflect.Method; 10 | 11 | public class ParameterAnnotationObjTagITCase { 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @interface Annotated { 14 | String value(); 15 | } 16 | 17 | static class AnnotationHolder{ 18 | public void primitiveMethod(String str, @Annotated(value="Param1") int param1, int noAnnotation2, @Annotated(value="param3") int[] param3){ 19 | 20 | } 21 | } 22 | 23 | @Test 24 | public void testParameterAnnotationsAreReindexed() throws Exception{ 25 | Method meth = AnnotationHolder.class.getDeclaredMethod("primitiveMethod", String.class, Integer.TYPE, Integer.TYPE, int[].class); 26 | Annotation[][] annotations = meth.getParameterAnnotations(); 27 | 28 | Assert.assertEquals(4, annotations.length); 29 | Assert.assertEquals(0, annotations[0].length); 30 | Assert.assertEquals(1, annotations[1].length); 31 | Annotated param1 = (Annotated) annotations[1][0]; 32 | Assert.assertEquals("Param1",param1.value()); 33 | Assert.assertEquals(0, annotations[2].length); 34 | Assert.assertEquals(1, annotations[3].length); 35 | Annotated param3 = (Annotated) annotations[3][0]; 36 | Assert.assertEquals("param3",param3.value()); 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/PartiallyInstrumentedClass.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | public class PartiallyInstrumentedClass { 4 | 5 | public PartiallyInstrumentedClass() 6 | { 7 | 8 | } 9 | public PartiallyInstrumentedClass(int in) 10 | { 11 | 12 | } 13 | public PartiallyInstrumentedClass(int[][][] mdin) 14 | { 15 | 16 | } 17 | public static void foo(){ 18 | 19 | } 20 | public static void inst(int a) 21 | { 22 | 23 | } 24 | public static boolean uninst(){ 25 | return false; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/PopAllCalledImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import org.junit.After; 5 | import org.junit.Test; 6 | 7 | import java.util.function.BiFunction; 8 | 9 | import static org.junit.Assert.assertNotNull; 10 | 11 | public class PopAllCalledImplicitITCase extends BaseMultiTaintClass { 12 | 13 | private void throwsExceptionInFinally() { 14 | int[] a = null; 15 | int x = MultiTainter.taintedInt(8, "throwsExceptionInFinally"); 16 | try { 17 | if(x > 0) { 18 | a[0] = 8; 19 | } 20 | } finally { 21 | a[0] = 7; 22 | } 23 | } 24 | 25 | @Test 26 | public void testExceptionThrownInFinally() { 27 | try { 28 | throwsExceptionInFinally(); 29 | } catch(Exception e) { 30 | // 31 | } 32 | int y = 7; 33 | assertNullOrEmpty(MultiTainter.getTaint(y)); 34 | } 35 | 36 | @Test 37 | public void testExceptionThrownBeforeSuperInit() { 38 | boolean b = MultiTainter.taintedBoolean(true, "b"); 39 | Exception e = null; 40 | try { 41 | Child c = new Child(null, b); 42 | } catch(NullPointerException ex) { 43 | e = ex; 44 | } 45 | assertNotNull(e); 46 | int i = 7; 47 | assertNullOrEmpty(MultiTainter.getTaint(i)); 48 | } 49 | 50 | @Test 51 | public void testBranchBeforeSuperInit() { 52 | boolean b = MultiTainter.taintedBoolean(true, "b"); 53 | Child c = new Child(new int[1], b); 54 | int i = 7; 55 | assertNullOrEmpty(MultiTainter.getTaint(i)); 56 | assertTaintHasOnlyLabel(MultiTainter.getTaint(c.i), "b"); 57 | } 58 | 59 | @Test 60 | public void testConstructorReferenceExceptionThrownBeforeSuperInit() { 61 | boolean b = MultiTainter.taintedBoolean(true, "b"); 62 | Exception e = null; 63 | BiFunction f = Child::new; 64 | try { 65 | Child c = f.apply(null, b); 66 | } catch (NullPointerException ex) { 67 | e = ex; 68 | } 69 | assertNotNull(e); 70 | int i = 7; 71 | assertNullOrEmpty(MultiTainter.getTaint(i)); 72 | } 73 | 74 | @After 75 | public void resetState() { 76 | MultiTainter.getControlFlow().reset(); 77 | } 78 | 79 | private static class Parent { 80 | int i; 81 | 82 | Parent(int i) { 83 | this.i = i; 84 | } 85 | } 86 | 87 | private static class Child extends Parent { 88 | Child(int[] a, boolean b) { 89 | super(b ? a[0] : a[1]); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/RuntimeAnnotationExample.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 4 | import static java.lang.annotation.ElementType.CONSTRUCTOR; 5 | import static java.lang.annotation.ElementType.FIELD; 6 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 7 | import static java.lang.annotation.ElementType.METHOD; 8 | import static java.lang.annotation.ElementType.PACKAGE; 9 | import static java.lang.annotation.ElementType.PARAMETER; 10 | import static java.lang.annotation.ElementType.TYPE; 11 | import static java.lang.annotation.ElementType.TYPE_PARAMETER; 12 | import static java.lang.annotation.ElementType.TYPE_USE; 13 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 14 | 15 | import java.lang.annotation.Retention; 16 | import java.lang.annotation.Target; 17 | 18 | @Retention(RUNTIME) 19 | @Target({ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, 20 | TYPE_USE }) 21 | public @interface RuntimeAnnotationExample { 22 | String[] value(); 23 | } 24 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/RuntimeAnnotationImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Test; 4 | 5 | public class RuntimeAnnotationImplicitITCase extends BasePhosphorTest { 6 | 7 | 8 | @Test 9 | public void testSimpleIf() { 10 | // this will crash if the test fails. 11 | @RuntimeAnnotationExample("EXAMPLE") int a = 100; 12 | 13 | 14 | a = a + 100; 15 | 16 | int b = 10; 17 | 18 | a = b + 1; 19 | 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/StringConcatObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor; 2 | 3 | import org.junit.Test; 4 | 5 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 6 | import edu.columbia.cs.psl.phosphor.runtime.Taint; 7 | import edu.columbia.cs.psl.phosphor.struct.TaintedWithObjTag; 8 | 9 | import static org.junit.Assert.*; 10 | 11 | public class StringConcatObjTagITCase extends BasePhosphorTest { 12 | @Test 13 | public void testLDCStringConcat() throws Exception { 14 | String str1 = "abcdefg"; 15 | ((TaintedWithObjTag)((Object)str1)).setPHOSPHOR_TAG(Taint.withLabel("sensitive")); 16 | String str2 = "a"+str1; 17 | assertTrue(MultiTainter.getTaint(str2.charAt(0)).isEmpty()); 18 | assertFalse(MultiTainter.getTaint(str2.charAt(1)).isEmpty()); 19 | } 20 | 21 | @Test 22 | public void testNewStringConcat() throws Exception { 23 | String str1 = "abcdefg"; 24 | ((TaintedWithObjTag)((Object)str1)).setPHOSPHOR_TAG(Taint.withLabel("sensitive")); 25 | String str2 = "a"+str1; 26 | assertTrue(MultiTainter.getTaint(str2.charAt(0)).isEmpty()); 27 | assertFalse(MultiTainter.getTaint(str2.charAt(1)).isEmpty()); 28 | } 29 | 30 | @Test 31 | public void testConcatAndMultiTainter() throws Exception { 32 | String str1 = "abcdefg"; 33 | MultiTainter.taintedObject(str1, Taint.withLabel("Sensitive")); 34 | String str2 = str1 + "a"; 35 | assertFalse(MultiTainter.getTaint(str2.charAt(0)).isEmpty()); 36 | assertTrue(MultiTainter.getTaint(str2.charAt(7)).isEmpty()); 37 | } 38 | 39 | @Test 40 | public void testConcateStringInt() { 41 | String s = "abc"; 42 | int val = 98; 43 | 44 | MultiTainter.taintedObject(s, Taint.withLabel("string")); 45 | val = MultiTainter.taintedInt(val, "int"); 46 | 47 | String concate = s + val; 48 | 49 | for (int i = 0; i < concate.length(); i++) { 50 | char c = concate.charAt(i); 51 | Taint ct = MultiTainter.getTaint(c); 52 | if (i < 3) { 53 | assertEquals(ct.getLabels()[0], "string"); 54 | } else { 55 | assertEquals(ct.getLabels()[0], "int"); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/ArrayCopyImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass; 5 | import org.junit.Test; 6 | 7 | public class ArrayCopyImplicitITCase extends BaseMultiTaintClass { 8 | 9 | @Test 10 | public void testControlTagPropagatesToCopiedElements() { 11 | int[] arr1 = new int[10]; 12 | int[] arr2 = new int[]{1, 2, 3, 4, 5}; 13 | boolean b = MultiTainter.taintedBoolean(true, 0); 14 | if(b) { 15 | System.arraycopy(arr2, 0, arr1, 2, arr2.length - 2); 16 | } 17 | for(int i : arr1) { 18 | if(i == 0) { 19 | assertNullOrEmpty(MultiTainter.getTaint(i)); 20 | } else { 21 | assertTaintHasOnlyLabel(MultiTainter.getTaint(i), 0); 22 | } 23 | } 24 | } 25 | 26 | @Test 27 | public void testSourceTaintPropagatesToCopiedElements() { 28 | int[] arr1 = new int[10]; 29 | int[] arr2 = new int[]{1, 2, 3, 4, 5}; 30 | arr2 = MultiTainter.taintedReference(arr2, 0); 31 | System.arraycopy(arr2, 0, arr1, 2, arr2.length - 2); 32 | for(int i : arr1) { 33 | if(i == 0) { 34 | assertNullOrEmpty(MultiTainter.getTaint(i)); 35 | } else { 36 | assertTaintHasOnlyLabel(MultiTainter.getTaint(i), 0); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/ArrayReflectionImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | public class ArrayReflectionImplicitITCase extends ArrayReflectionObjTagITCase { 4 | } 5 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/ArrayReflectionObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass; 5 | import org.junit.Test; 6 | 7 | import java.lang.reflect.Array; 8 | import java.util.LinkedList; 9 | 10 | import static junit.framework.TestCase.assertTrue; 11 | import static org.junit.Assert.assertArrayEquals; 12 | import static org.junit.Assert.assertEquals; 13 | 14 | public class ArrayReflectionObjTagITCase extends BaseMultiTaintClass { 15 | 16 | @Test 17 | public void testArrayGet() { 18 | boolean[] b = new boolean[] {false}; 19 | assertTrue(b.getClass().isArray()); 20 | for (int i = 0; i < Array.getLength(b); i++) { 21 | Array.get(b, i); 22 | } 23 | } 24 | 25 | @Test 26 | public void testRefArraySet() { 27 | int[] arr = new int[]{18}; 28 | arr = MultiTainter.taintedIntArray(arr, "arr"); 29 | Object obj = arr; 30 | int ret = Array.getInt(obj, 0); 31 | assertEquals(MultiTainter.getTaint(arr[0]), MultiTainter.getTaint(ret)); 32 | } 33 | 34 | @Test 35 | public void testNewInstancePrimitiveComponentMultiDimensionalArray() { 36 | int[] expectedDimensions = new int[]{33, 2, 9}; 37 | Object arr = Array.newInstance(int.class, expectedDimensions); 38 | LinkedList actual = new LinkedList<>(); 39 | for(Class clazz = arr.getClass(); clazz.isArray(); clazz = clazz.getComponentType()) { 40 | actual.add(Array.getLength(arr)); 41 | arr = Array.get(arr, 0); 42 | } 43 | int[] actualDimensions = new int[actual.size()]; 44 | for(int i = 0; i < actualDimensions.length; i++) { 45 | actualDimensions[i] = actual.pop(); 46 | } 47 | assertArrayEquals(expectedDimensions, actualDimensions); 48 | } 49 | 50 | @Test 51 | public void testNewInstancePrimitiveArrayComponentMultiDimensionalArray() { 52 | Object arr = Array.newInstance(int[].class, 33, 2, 9); 53 | assertTrue(arr instanceof int[][][][]); 54 | } 55 | 56 | @Test 57 | public void testTaintedPrimitiveArraySet() { 58 | int[] ia = new int[2]; 59 | int val = MultiTainter.taintedInt(23, "label"); 60 | Array.set(ia, 0, val); 61 | assertNonNullTaint(ia[0]); 62 | 63 | byte[] ba = new byte[2]; 64 | Array.set(ba, 0, MultiTainter.taintedByte((byte) 2,"label")); 65 | assertNonNullTaint(ba[0]); 66 | 67 | char[] ca = new char[2]; 68 | Array.set(ca, 0, MultiTainter.taintedChar((char) 2,"label")); 69 | assertNonNullTaint(ca[0]); 70 | 71 | long[] ja = new long[2]; 72 | Array.set(ja, 0, MultiTainter.taintedLong(2L,"label")); 73 | assertNonNullTaint(ja[0]); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/CharacterPropagationImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class CharacterPropagationImplicitITCase extends BaseMultiTaintClass { 10 | 11 | @Test 12 | public void testForDigitPropagates() { 13 | int digit = MultiTainter.taintedInt(5, "digit"); 14 | int radix = MultiTainter.taintedInt(10, "radix"); 15 | char result = Character.forDigit(digit, radix); 16 | assertEquals('5', result); 17 | assertTaintHasOnlyLabels(MultiTainter.getTaint(result), "digit", "radix"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/CharacterPropagationObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class CharacterPropagationObjTagITCase extends BaseMultiTaintClass { 10 | 11 | @Test 12 | public void testForDigitPropagates() { 13 | int digit = MultiTainter.taintedInt(5, "digit"); 14 | int radix = MultiTainter.taintedInt(10, "radix"); 15 | char result = Character.forDigit(digit, radix); 16 | assertEquals('5', result); 17 | assertTaintHasOnlyLabel(MultiTainter.getTaint(result), "digit"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/FieldReflectionImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | public class FieldReflectionImplicitITCase extends FieldReflectionObjTagITCase { 4 | } 5 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/GetCharsObjTagITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | import edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass; 5 | import org.junit.experimental.theories.DataPoints; 6 | import org.junit.experimental.theories.Theories; 7 | import org.junit.experimental.theories.Theory; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(Theories.class) 11 | public class GetCharsObjTagITCase extends BaseMultiTaintClass { 12 | 13 | @DataPoints 14 | public static Integer[] intValues() { 15 | return new Integer[]{-10000, -1000, -100, -10, 0, 10, 100, 1000, 10000}; 16 | } 17 | 18 | @DataPoints 19 | public static Long[] longValues() { 20 | return new Long[]{-10000L, -1000L, -100L, -10L, 0L, 10L, 100L, 1000L, 10000L}; 21 | } 22 | 23 | @DataPoints 24 | public static Boolean[] tainted() { 25 | return new Boolean[]{Boolean.TRUE, Boolean.FALSE}; 26 | } 27 | 28 | @Theory 29 | public void testGetCharsInt(Integer value, Boolean tainted) { 30 | int val = tainted ? MultiTainter.taintedInt(value, "tainted int") : value; 31 | String result = new StringBuilder().append(val).toString(); 32 | for(char c : result.toCharArray()) { 33 | if(tainted) { 34 | assertNonNullTaint(MultiTainter.getTaint(c)); 35 | } else { 36 | assertNullOrEmpty(MultiTainter.getTaint(c)); 37 | } 38 | } 39 | } 40 | 41 | @Theory 42 | public void testGetCharsLong(Long value, Boolean tainted) { 43 | long val = tainted ? MultiTainter.taintedLong(value, "tainted long") : value; 44 | String result = new StringBuilder().append(val).toString(); 45 | for(char c : result.toCharArray()) { 46 | if(tainted) { 47 | assertNonNullTaint(MultiTainter.getTaint(c)); 48 | } else { 49 | assertNullOrEmpty(MultiTainter.getTaint(c)); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/MethodHolder.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 4 | 5 | import static edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass.assertNonNullTaint; 6 | import static edu.columbia.cs.psl.test.phosphor.BaseMultiTaintClass.assertNullOrEmpty; 7 | 8 | @SuppressWarnings("unused") 9 | public class MethodHolder { 10 | 11 | public static final int RET_VALUE = 2; 12 | 13 | // Whether methods' arguments are expected to be tainted 14 | private final boolean checkArgsTainted; 15 | 16 | MethodHolder(boolean checkArgsTainted) { 17 | this.checkArgsTainted = checkArgsTainted; 18 | } 19 | 20 | public int example(boolean taintedBool) { 21 | if(checkArgsTainted) { 22 | assertNonNullTaint(MultiTainter.getTaint(taintedBool)); 23 | } else { 24 | assertNullOrEmpty(MultiTainter.getTaint(taintedBool)); 25 | } 26 | return RET_VALUE; 27 | } 28 | 29 | public int example(boolean[] b) { 30 | if(checkArgsTainted) { 31 | assertNonNullTaint(MultiTainter.getTaint(b[0])); 32 | } else { 33 | assertNullOrEmpty(MultiTainter.getTaint(b[0])); 34 | } 35 | return RET_VALUE; 36 | } 37 | 38 | public int getLast(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, 39 | int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, 40 | int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, 41 | int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39) { 42 | if (checkArgsTainted) { 43 | assertNonNullTaint(MultiTainter.getTaint(a39)); 44 | } else { 45 | assertNullOrEmpty(MultiTainter.getTaint(a39)); 46 | } 47 | return a39; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/MethodReflectionImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | public class MethodReflectionImplicitITCase extends MethodReflectionObjTagITCase { 4 | } 5 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/ParsePrimitiveImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | public class ParsePrimitiveImplicitITCase extends ParsePrimitiveObjTagITCase { 4 | 5 | public ParsePrimitiveImplicitITCase(Boolean taintString, Boolean taintChars) { 6 | super(taintString, taintChars); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/ReflectionImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | import static org.junit.Assert.fail; 5 | 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.Modifier; 8 | import java.util.Arrays; 9 | import java.util.HashSet; 10 | import java.util.Set; 11 | import java.util.stream.IntStream; 12 | 13 | import edu.columbia.cs.psl.phosphor.Phosphor; 14 | import org.junit.Test; 15 | 16 | public class ReflectionImplicitITCase extends ReflectionObjTagITCase{ 17 | 18 | @Test 19 | public void testIntStreamsDontCrash() throws Exception { 20 | int sum = IntStream.of(1, 2, 3, 4, 5).sum(); //creates a bunch of lambdas 21 | } 22 | 23 | int[][] multiDArray; 24 | 25 | @Test 26 | public void testMultiDArrayAssignableFrom() throws Exception { 27 | Field f = ReflectionImplicitITCase.class.getDeclaredField("multiDArray"); 28 | Object z = new int[5][6]; 29 | assertTrue(f.getType().isAssignableFrom(z.getClass())); 30 | } 31 | 32 | @Test 33 | public void testReflectionDoesntCrash() { 34 | try { 35 | for (Class c : Phosphor.getInstrumentation().getAllLoadedClasses()) { 36 | Set allFields = new HashSet(); 37 | try { 38 | Field[] declaredFields = c.getDeclaredFields(); 39 | Field[] fields = c.getFields(); 40 | allFields.addAll(Arrays.asList(declaredFields)); 41 | allFields.addAll(Arrays.asList(fields)); 42 | } catch (NoClassDefFoundError e) { 43 | continue; 44 | } 45 | 46 | for (Field f : allFields) { 47 | if ((Modifier.isStatic(f.getModifiers())) && !((Modifier.isFinal(f.getModifiers())) && (f.getType().isPrimitive()))) { 48 | Object ret = f.get(null); 49 | if (!f.getType().isArray() && !f.getType().isPrimitive() && ret != null) { 50 | visit(f, ret); 51 | } 52 | } 53 | } 54 | } 55 | } catch (Throwable t) { 56 | t.printStackTrace(); 57 | fail(); 58 | } 59 | } 60 | 61 | private void visit(Field _f, Object o) throws IllegalArgumentException, IllegalAccessException { 62 | Object z = _f.get(o); 63 | if (z == null) 64 | return; 65 | Class c = z.getClass(); 66 | Set allFields = new HashSet(); 67 | try { 68 | Field[] declaredFields = c.getDeclaredFields(); 69 | Field[] fields = c.getFields(); 70 | allFields.addAll(Arrays.asList(declaredFields)); 71 | allFields.addAll(Arrays.asList(fields)); 72 | } catch (NoClassDefFoundError e) { 73 | return; 74 | } 75 | 76 | for (Field f : allFields) { 77 | if ((Modifier.isStatic(f.getModifiers())) && !((Modifier.isFinal(f.getModifiers())) && (f.getType().isPrimitive()))) { 78 | Object ret = f.get(null); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/SerializationImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | public class SerializationImplicitITCase extends SerializationObjTagITCase { 4 | } 5 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/runtime/UnsafeImplicitITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.runtime; 2 | 3 | public class UnsafeImplicitITCase extends UnsafeObjTagITCase { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /integration-tests/src/test/java/edu/columbia/cs/psl/test/phosphor/util/TaintThroughExample.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.phosphor.util; 2 | 3 | 4 | import edu.columbia.cs.psl.phosphor.runtime.MultiTainter; 5 | 6 | public class TaintThroughExample { 7 | 8 | public void taintBackToArgs(int[] input) { 9 | try { 10 | input[0] = 1; 11 | int x = input[0]; 12 | } finally { 13 | //taint input 14 | } 15 | } 16 | 17 | public int passIntTaintThrough(int i) { 18 | System.out.println(MultiTainter.getTaint(i)); 19 | return i; 20 | } 21 | 22 | public String passStringTaintThrough(String s) { 23 | return s; 24 | } 25 | 26 | public int taintThroughInt() { 27 | return 7; 28 | } 29 | 30 | public static String staticMethod(String s) { 31 | return s; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /integration-tests/src/test/resources/taint-sinks: -------------------------------------------------------------------------------- 1 | #java/io/OutputStream.write(I)V 2 | #java/io/OutputStream.write([B)V 3 | #java/io/OutputStream.write([BII)V 4 | #java/io/PrintStream.println(Ljava/lang/String;)V 5 | #java/io/PrintStream.println(Ljava/lang/Object;)V 6 | #phosphor/test/SourceSinkTest.sink(Ljava/lang/Object;)V 7 | #phosphor/test/SourceSinkTest.sink2([I)V 8 | #phosphor/test/SourceSinkTest.sink(I)V 9 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.exceptionCatchingSink(I)I 10 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.sink(I)V 11 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.staticSink(I)V 12 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.sink(Ljava/lang/String;)V 13 | 14 | edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsObjTagITCase$ExampleWithSinkConstructors.(C)V 15 | edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsObjTagITCase$ExampleWithSinkConstructors.([C)V 16 | edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsObjTagITCase$ExampleWithSinkConstructors.([[C)V -------------------------------------------------------------------------------- /integration-tests/src/test/resources/taint-sources: -------------------------------------------------------------------------------- 1 | #java/io/InputStream.read()I 2 | #java/io/InputStream.read([B)I 3 | #java/io/InputStream.read([BII)I 4 | #java/io/InputStream.readLine([BII)I 5 | #javax/servlet/http/HttpServletRequest.getQueryString()Ljava/lang/String; 6 | #javax/servlet/http/HttpServletRequest.getRemoteUser()Ljava/lang/String; 7 | #javax/servlet/http/HttpServletRequest.getRequestedSessionId()Ljava/lang/String; 8 | #javax/servlet/http/HttpServletRequest.getRequestURI()Ljava/lang/String; 9 | #javax/servlet/ServletRequest.getAttribute(Ljava/lang/String;)Ljava/lang/Object; 10 | #javax/servlet/ServletRequest.getAttributeNames()Ljava/util/Enumeration; 11 | #javax/servlet/ServletRequest.getContentLength()I 12 | #javax/servlet/ServletRequest.getContentLengthLong()J 13 | #javax/servlet/ServletRequest.getParameter(Ljava/lang/String;)Ljava/lang/String; 14 | #javax/servlet/ServletRequest.getParameterValues(Ljava/lang/String;)[Ljava/lang/String; 15 | #javax/servlet/ServletRequest.getParameterNames(Ljava/lang/String;)Ljava/util/Enumeration; 16 | #javax/servlet/http/Cookie.getPath()Ljava/lang/String; 17 | #javax/servlet/http/Cookie.getDomain()Ljava/lang/String; 18 | #javax/servlet/http/Cookie.getMaxAge()I 19 | #javax/servlet/http/Cookie.getName()Ljava/lang/String; 20 | #javax/servlet/http/Cookie.getValue()Ljava/lang/String; 21 | #javax/servlet/http/HttpSession.getAttribute(Ljava/lang/String;)Ljava/lang/Object; 22 | #javax/servlet/http/HttpSession.getValue(Ljava/lang/String;)Ljava/lang/Object; 23 | #javax/servlet/http/HttpSession.getAttributeNames()Ljava/util/Enumeration; 24 | #javax/servlet/http/HttpSession.getValueNames()[Ljava/lang/String; 25 | #org/apache/catalina/connector/CoyoteReader.read()I 26 | #org/apache/catalina/connector/CoyoteReader.read([C)I 27 | #org/apache/catalina/connector/CoyoteReader.read([CII)I 28 | #org/apache/catalina/connector/CoyoteReader.readLine()Ljava/lang/String; 29 | #phosphor/test/SourceSinkTest.sourceArgs(Ljava/lang/Object;)V 30 | #phosphor/test/SourceSinkTest.sourceArgs2([I)V 31 | #phosphor/test/SourceSinkTest.sourceRet1()I 32 | #phosphor/test/SourceSinkTest.sourceRet2()[I 33 | #phosphor/test/SourceSinkTest.sourceRet3()Ljava/lang/Object; 34 | #phosphor/test/SourceSinkTest.sourceRet4()[I 35 | 36 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.source()Ljava/lang/String; 37 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.iSource()I 38 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.source([I)V 39 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.source([I)V 40 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.sourceWithDoubleCharArrParam([[C)V 41 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.sourceWithStringArrParam([Ljava/lang/String;)V 42 | 43 | edu/columbia/cs/psl/test/phosphor/AutoTaintObjTagITCase.staticSource(I)I 44 | 45 | edu/columbia/cs/psl/test/phosphor/InheritedAutoTaintObjTagITCase$TaintSourceInterface.getSource()I 46 | edu/columbia/cs/psl/test/phosphor/InheritedAutoTaintObjTagITCase$TaintSourceClass.getSource()I 47 | 48 | edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsObjTagITCase$ExampleWithSourceConstructors.(CLjava/lang/String;)V 49 | edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsObjTagITCase$ExampleWithSourceConstructors.([C)V 50 | edu/columbia/cs/psl/test/phosphor/AutoTaintConstructorsObjTagITCase$ExampleWithSourceConstructors.([[C)V -------------------------------------------------------------------------------- /integration-tests/src/test/resources/taint-through: -------------------------------------------------------------------------------- 1 | edu/columbia/cs/psl/test/phosphor/util/TaintThroughExample.taintBackToArgs([I)V 2 | edu/columbia/cs/psl/test/phosphor/util/TaintThroughExample.passIntTaintThrough(I)I 3 | edu/columbia/cs/psl/test/phosphor/util/TaintThroughExample.taintThroughInt()I 4 | edu/columbia/cs/psl/test/phosphor/util/TaintThroughExample.passStringTaintThrough(Ljava/lang/String;)Ljava/lang/String; 5 | edu/columbia/cs/psl/test/phosphor/util/TaintThroughExample.staticMethod(Ljava/lang/String;)Ljava/lang/String; 6 | 7 | java/net/URI.getPath()Ljava/lang/String; 8 | java/nio/channels/SocketChannel.isConnected()Z -------------------------------------------------------------------------------- /integration-tests/src/test/resources/test-methods: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/DeletingFileVisitor.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.driver; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.FileVisitResult; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.nio.file.SimpleFileVisitor; 8 | import java.nio.file.attribute.BasicFileAttributes; 9 | 10 | /** 11 | * Deletes a file tree. 12 | */ 13 | public class DeletingFileVisitor extends SimpleFileVisitor { 14 | /** 15 | * Deletes the specified file. 16 | * @param file {@inheritDoc} 17 | * @param attrs {@inheritDoc} 18 | * @return FileVisitResult#CONTINUE 19 | * @throws IOException if an I/O error occurs 20 | */ 21 | @Override 22 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 23 | Files.delete(file); 24 | return FileVisitResult.CONTINUE; 25 | } 26 | 27 | /** 28 | * Deletes the specified directory. 29 | * @param dir {@inheritDoc} 30 | * @param e {@inheritDoc} 31 | * @return FileVisitResult#CONTINUE 32 | * @throws IOException if an I/O error occurred with traversing dir 33 | */ 34 | @Override 35 | public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { 36 | if (e == null) { 37 | Files.delete(dir); 38 | return FileVisitResult.CONTINUE; 39 | } else { 40 | throw e; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/InstrumentJLinkPlugin.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.driver; 2 | 3 | import jdk.tools.jlink.plugin.Plugin; 4 | import jdk.tools.jlink.plugin.ResourcePool; 5 | import jdk.tools.jlink.plugin.ResourcePoolBuilder; 6 | import jdk.tools.jlink.plugin.ResourcePoolEntry; 7 | 8 | import java.io.File; 9 | import java.io.FileReader; 10 | import java.io.IOException; 11 | import java.util.Map; 12 | import java.util.Properties; 13 | 14 | public class InstrumentJLinkPlugin implements Plugin { 15 | private Instrumentation instrumentation; 16 | private ResourcePoolPacker packer; 17 | 18 | @Override 19 | public String getName() { 20 | return "phosphor-instrument"; 21 | } 22 | 23 | @Override 24 | public Category getType() { 25 | return Category.FILTER; 26 | } 27 | 28 | @Override 29 | public String getDescription() { 30 | return "Applies instrumentation to the runtime image and packs classes into the java.base module"; 31 | } 32 | 33 | @Override 34 | public boolean hasArguments() { 35 | return true; 36 | } 37 | 38 | @Override 39 | public void configure(Map config) { 40 | try (FileReader reader = new FileReader(config.get("options"))) { 41 | Properties options = new Properties(); 42 | options.load(reader); 43 | instrumentation = Instrumentation.create(config.get("type"), new File(config.get("source")), options); 44 | } catch (IOException | ReflectiveOperationException e) { 45 | throw new RuntimeException("Failed to process configuration", e); 46 | } 47 | } 48 | 49 | @Override 50 | public ResourcePool transform(ResourcePool pool, ResourcePoolBuilder out) { 51 | packer = new ResourcePoolPacker(instrumentation, pool, out); 52 | pool.transformAndCopy(this::transform, out); 53 | return out.build(); 54 | } 55 | 56 | private ResourcePoolEntry transform(ResourcePoolEntry entry) { 57 | if (entry.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE) 58 | && entry.path().endsWith(".class")) { 59 | if (entry.path().endsWith("module-info.class")) { 60 | if (entry.path().startsWith("/java.base")) { 61 | // Transform java.base's module-info.class file and pack core classes into java.base 62 | return packer.pack(entry); 63 | } 64 | } else { 65 | byte[] instrumented = instrumentation.apply(entry.contentBytes()); 66 | return instrumented == null ? entry : entry.copyWithContent(instrumented); 67 | } 68 | } 69 | return entry; 70 | } 71 | } -------------------------------------------------------------------------------- /phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/Instrumentation.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.driver; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.Properties; 6 | import java.util.Set; 7 | import java.util.function.Function; 8 | 9 | /** 10 | * Implementors are expected to have a zero-argument, public constructor. 11 | */ 12 | public interface Instrumentation { 13 | /** 14 | * Configures this instance using the specified options. 15 | * 16 | * @param source the location to be instrumented 17 | * @param options the key-value pairs that should be used to configure this instance 18 | * @throws IOException if an I/O error occurs 19 | */ 20 | void configure(File source, Properties options) throws IOException, ReflectiveOperationException; 21 | 22 | /** 23 | * Returns an array of class path elements needed to use this class. 24 | * The returned array should be non-null. 25 | * All elements of the returned array should be non-null. 26 | * 27 | * @return class path elements needed to use this class 28 | */ 29 | Set getClassPathElements(); 30 | 31 | byte[] apply(byte[] classFileBuffer); 32 | 33 | boolean shouldPack(String classFileName); 34 | 35 | Set getElementsToPack(); 36 | 37 | Patcher createPatcher(Function entryLocator); 38 | 39 | static Instrumentation create(String className, File source, Properties options) 40 | throws ReflectiveOperationException, IOException { 41 | Class clazz = Class.forName(className, true, Instrumentation.class.getClassLoader()); 42 | Instrumentation instance = (Instrumentation) clazz.getConstructor().newInstance(); 43 | instance.configure(source, options); 44 | return instance; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/Patcher.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.driver; 2 | 3 | import java.io.IOException; 4 | 5 | public interface Patcher { 6 | byte[] patch(String classFileName, byte[] classFileBuffer) throws IOException; 7 | } 8 | -------------------------------------------------------------------------------- /phosphor-driver/src/main/java/edu/columbia/cs/psl/phosphor/driver/PhosphorInstrumenter.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.driver; 2 | 3 | import edu.columbia.cs.psl.phosphor.Configuration; 4 | import edu.columbia.cs.psl.phosphor.PhosphorOption; 5 | import edu.columbia.cs.psl.phosphor.org.apache.commons.cli.CommandLine; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | 10 | public final class PhosphorInstrumenter { 11 | private PhosphorInstrumenter() { 12 | throw new AssertionError("Tried to instantiate static utility class: " + getClass()); 13 | } 14 | 15 | public static void main(String[] args) throws IOException { 16 | PhosphorInstrumentation instrumentation = new PhosphorInstrumentation(); 17 | CommandLine line = PhosphorOption.configure(false, args); 18 | if(line == null) { 19 | // The "help" option was specified 20 | return; 21 | } 22 | args = line.getArgs(); 23 | File source = new File(args[0]); 24 | File destination = new File(args[1]); 25 | instrumentation.initialize(line); 26 | boolean verbose = !Configuration.QUIET_MODE; 27 | String modules = line.hasOption("jvmModules") ? line.getOptionValue("jvmModules") : "ALL-MODULE-PATH"; 28 | System.out.printf("Instrumenting %s to %s%n", source, destination); 29 | long elapsedTime = Instrumenter.instrument(source, destination, PhosphorOption.toProperties(line), 30 | instrumentation, verbose, modules); 31 | System.out.printf("Finished instrumentation after %dms%n", elapsedTime); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /phosphor-driver/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module edu.columbia.cs.psl.phosphor.driver { 2 | exports edu.columbia.cs.psl.phosphor.driver; 3 | 4 | requires jdk.jlink; 5 | requires java.instrument; 6 | } 7 | -------------------------------------------------------------------------------- /phosphor-instrument-maven-plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | phosphor-instrument-maven-plugin 5 | maven-plugin 6 | A Maven plugin for creating phosphor-instrumented JVMs 7 | 8 | edu.gmu.swe.phosphor 9 | phosphor-parent 10 | 0.1.0 11 | 12 | 13 | 14 | org.apache.maven 15 | maven-plugin-api 16 | 3.8.1 17 | 18 | 19 | org.apache.maven.plugin-tools 20 | maven-plugin-annotations 21 | 3.6.1 22 | provided 23 | 24 | 25 | edu.gmu.swe.phosphor 26 | Phosphor 27 | ${project.version} 28 | 29 | 30 | edu.gmu.swe.phosphor 31 | phosphor-driver 32 | ${project.version} 33 | 34 | 35 | 36 | 37 | 38 | org.apache.maven.plugins 39 | maven-plugin-plugin 40 | 3.6.0 41 | 42 | 43 | mojo-descriptor 44 | 45 | descriptor 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /phosphor-microbench/src/main/java/edu/columbia/cs/psl/phosphor/bench/set/CopyBenchmark.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.bench.set; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.BitSet; 4 | import edu.columbia.cs.psl.phosphor.struct.PowerSetTree; 5 | import org.openjdk.jmh.annotations.*; 6 | 7 | import java.util.HashSet; 8 | import java.util.concurrent.ThreadLocalRandom; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | @Fork(3) 12 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 13 | @BenchmarkMode(Mode.AverageTime) 14 | @State(Scope.Benchmark) 15 | public class CopyBenchmark { 16 | 17 | // The percentage of the number of unique elements that are present in each set 18 | @Param({".1", ".2", ".3"}) 19 | private static double percentPresent; 20 | // Singleton used to create empty SetNodes 21 | private final PowerSetTree setTree = PowerSetTree.getInstance(); 22 | // The number of different possible unique elements 23 | @Param({"10000"}) 24 | private int uniqueElementsSize; 25 | // Sets being tested 26 | private BitSet bitSet; 27 | private PowerSetTree.SetNode setNode; 28 | private HashSet hashSet; 29 | 30 | @Setup(Level.Trial) 31 | public void initSets() { 32 | bitSet = new BitSet(uniqueElementsSize); 33 | setNode = setTree.emptySet(); 34 | hashSet = new HashSet<>(); 35 | int setSize = (int) (uniqueElementsSize * percentPresent); 36 | for(int i : ThreadLocalRandom.current().ints(0, uniqueElementsSize).distinct().limit(setSize).toArray()) { 37 | bitSet.add(i); 38 | setNode = setNode.add(i); 39 | hashSet.add(i); 40 | } 41 | } 42 | 43 | @Benchmark 44 | public BitSet bitSetCopyTest() { 45 | return bitSet.copy(); 46 | } 47 | 48 | @Benchmark 49 | public PowerSetTree.SetNode setNodeCopyTest() { 50 | return setNode; 51 | } 52 | 53 | @Benchmark 54 | public HashSet hashSetCopyTest() { 55 | return new HashSet<>(hashSet); 56 | } 57 | } -------------------------------------------------------------------------------- /phosphor-microbench/src/main/java/edu/columbia/cs/psl/phosphor/bench/set/UnionBenchmark.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.phosphor.bench.set; 2 | 3 | import edu.columbia.cs.psl.phosphor.struct.BitSet; 4 | import edu.columbia.cs.psl.phosphor.struct.PowerSetTree; 5 | import org.openjdk.jmh.annotations.*; 6 | 7 | import java.util.HashSet; 8 | import java.util.concurrent.ThreadLocalRandom; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | @Fork(3) 12 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 13 | @BenchmarkMode(Mode.AverageTime) 14 | @State(Scope.Benchmark) 15 | public class UnionBenchmark { 16 | 17 | // The percentage of the number of unique elements that are present in each set 18 | @Param({".1", ".2", ".3"}) 19 | private static double percentPresent; 20 | // Singleton used to create empty SetNodes 21 | private final PowerSetTree setTree = PowerSetTree.getInstance(); 22 | // The number of different possible unique elements 23 | @Param({"10000"}) 24 | private int uniqueElementsSize; 25 | // Sets being tested 26 | private BitSet[] bitSets = new BitSet[2]; 27 | private PowerSetTree.SetNode[] setNodes = new PowerSetTree.SetNode[2]; 28 | @SuppressWarnings("unchecked") 29 | private HashSet[] hashSets = new HashSet[2]; 30 | 31 | @Setup(Level.Invocation) 32 | public void initSets() { 33 | int setSize = (int) (uniqueElementsSize * percentPresent); 34 | for(int i = 0; i < 2; i++) { 35 | bitSets[i] = new BitSet(uniqueElementsSize); 36 | setNodes[i] = setTree.emptySet(); 37 | hashSets[i] = new HashSet<>(); 38 | } 39 | int i = 0; 40 | for(int el : ThreadLocalRandom.current().ints(0, uniqueElementsSize).distinct().limit(setSize * 2).toArray()) { 41 | bitSets[i % 2].add(el); 42 | setNodes[i % 2] = setNodes[i % 2].add(el); 43 | hashSets[i % 2].add(el); 44 | i++; 45 | } 46 | } 47 | 48 | @TearDown(Level.Invocation) 49 | public void clearSetsForGC() { 50 | for(int i = 0; i < 2; i++) { 51 | bitSets[i] = null; 52 | setNodes[i] = null; 53 | hashSets[i] = null; 54 | } 55 | } 56 | 57 | @Benchmark 58 | public BitSet bitSetUnionTest() { 59 | bitSets[0].union(bitSets[1]); 60 | return bitSets[0]; 61 | } 62 | 63 | @Benchmark 64 | public PowerSetTree.SetNode setNodeUnionTest() { 65 | return setNodes[0].union(setNodes[1]); 66 | } 67 | 68 | @Benchmark 69 | public HashSet hashSetUnionTest() { 70 | hashSets[0].addAll(hashSets[1]); 71 | return hashSets[0]; 72 | } 73 | } --------------------------------------------------------------------------------