├── .gitignore ├── LICENSE ├── README.md ├── T.java ├── bugs ├── checkstyle106 │ ├── generated │ │ └── SuppressionsStringPrinterm106TemplateGEN1.java │ ├── minimized │ │ └── C.java │ └── template │ │ └── SuppressionsStringPrinterm106Template.java ├── codec292 │ ├── generated │ │ └── Sha2Cryptm292TemplateGEN5.java │ ├── minimized │ │ └── C.java │ └── template │ │ └── Sha2Cryptm292Template.java ├── compress208 │ ├── generated │ │ └── HuffmanDecoderm208TemplateGEN7.java │ ├── minimized │ │ └── C.java │ └── template │ │ └── HuffmanDecoderm208Template.java ├── m12gen61 │ ├── generated │ │ └── M12GEN61.java │ ├── minimized │ │ └── C.java │ └── template │ │ └── M12.java ├── m4gen152 │ ├── generated │ │ └── M4GEN152.java │ ├── minimized │ │ └── C.java │ └── template │ │ └── M4.java └── math182 │ ├── generated │ └── ComplexUtilsm184TemplateGEN2.java │ ├── minimized │ └── C.java │ └── template │ └── ComplexUtilsm184Template.java ├── demo.sh └── tool ├── .gitignore ├── api ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── settings.gradle └── src │ ├── main │ └── java │ │ └── jattack │ │ ├── Boom.java │ │ ├── Config.java │ │ ├── Constants.java │ │ ├── annotation │ │ ├── Argument.java │ │ ├── Arguments.java │ │ └── Entry.java │ │ ├── ast │ │ ├── Node.java │ │ ├── exp │ │ │ ├── AltExp.java │ │ │ ├── AssignExp.java │ │ │ ├── BAriExp.java │ │ │ ├── BoolVal.java │ │ │ ├── ByteVal.java │ │ │ ├── CastExp.java │ │ │ ├── CharVal.java │ │ │ ├── DoubleVal.java │ │ │ ├── Exp.java │ │ │ ├── FloatVal.java │ │ │ ├── IdExp.java │ │ │ ├── ImBoolVal.java │ │ │ ├── ImByteVal.java │ │ │ ├── ImCharVal.java │ │ │ ├── ImDoubleVal.java │ │ │ ├── ImFloatVal.java │ │ │ ├── ImIntVal.java │ │ │ ├── ImLongVal.java │ │ │ ├── ImShortVal.java │ │ │ ├── ImVal.java │ │ │ ├── IntArrVal.java │ │ │ ├── IntVal.java │ │ │ ├── LHSExp.java │ │ │ ├── LitExp.java │ │ │ ├── LogExp.java │ │ │ ├── LongVal.java │ │ │ ├── NumberVal.java │ │ │ ├── PreIncExp.java │ │ │ ├── RefArrAccessExp.java │ │ │ ├── RefId.java │ │ │ ├── RelExp.java │ │ │ ├── ShiftExp.java │ │ │ ├── ShortVal.java │ │ │ └── iterator │ │ │ │ ├── ChainItr.java │ │ │ │ ├── CombItr.java │ │ │ │ ├── ExpItr.java │ │ │ │ ├── ImItr.java │ │ │ │ ├── Itr.java │ │ │ │ ├── LitItr.java │ │ │ │ └── RangeItr.java │ │ ├── nodetypes │ │ │ ├── NodeWithOperator.java │ │ │ ├── NodeWithSideEffect.java │ │ │ ├── NodeWithType.java │ │ │ └── TerminalNode.java │ │ ├── operator │ │ │ ├── AriOp.java │ │ │ ├── AriOrShiftOp.java │ │ │ ├── IncDecOp.java │ │ │ ├── LogOp.java │ │ │ ├── Op.java │ │ │ ├── OpNode.java │ │ │ ├── RelOp.java │ │ │ └── ShiftOp.java │ │ ├── stmt │ │ │ ├── AltStmt.java │ │ │ ├── BlockStmt.java │ │ │ ├── ExprStmt.java │ │ │ ├── IfStmt.java │ │ │ ├── Stmt.java │ │ │ ├── TryStmt.java │ │ │ └── WhileStmt.java │ │ └── visitor │ │ │ ├── EvalVisitor.java │ │ │ ├── PrintVisitor.java │ │ │ ├── Visitable.java │ │ │ ├── Visitor.java │ │ │ └── Z3ExprBuilder.java │ │ ├── bytecode │ │ ├── FieldAnalyzer.java │ │ ├── LocalVariableTableClassVisitor.java │ │ ├── LocalVariableTableMethodVisitor.java │ │ ├── SaveLocalVarValuesClassVisitor.java │ │ ├── SaveLocalVarValuesMethodVisitor.java │ │ ├── SaveUpdateUtil.java │ │ ├── StaticFieldAnalyzer.java │ │ ├── StaticGenClassVisitor.java │ │ ├── StaticGenMethodVisitor.java │ │ ├── StaticInitRenamer.java │ │ ├── Symbol.java │ │ ├── Var.java │ │ └── VariableAnalyzer.java │ │ ├── compiler │ │ ├── Agent.java │ │ ├── ClassBytes.java │ │ ├── ClassFileManager.java │ │ ├── CompilationException.java │ │ ├── InMemoryClassLoader.java │ │ ├── InMemoryCompiler.java │ │ ├── JavaClassObject.java │ │ ├── JavaSourceFromString.java │ │ └── StaticInitCopyTransformer.java │ │ ├── data │ │ ├── Data.java │ │ ├── Memory.java │ │ └── RuntimeSymbol.java │ │ ├── driver │ │ ├── Cli.java │ │ ├── Driver.java │ │ └── SearchStrategy.java │ │ ├── exception │ │ └── InvokedFromNotDriverException.java │ │ ├── log │ │ └── Log.java │ │ ├── transformer │ │ ├── HoleExtractor.java │ │ ├── HoleIdAssigner.java │ │ ├── OnDemandTransformer.java │ │ ├── OutputTransformer.java │ │ ├── Transformer.java │ │ └── visitor │ │ │ ├── DeadCodeEliminator.java │ │ │ ├── HideGenericTypeArgumentPrinterVisitor.java │ │ │ ├── HoleFiller.java │ │ │ ├── NeverReachableHoleMarker.java │ │ │ ├── RemoveVisitor.java │ │ │ └── RenameVisitor.java │ │ └── util │ │ ├── IOUtil.java │ │ ├── JPUtil.java │ │ ├── Rand.java │ │ ├── TypeUtil.java │ │ ├── UniqueList.java │ │ └── Z3Util.java │ └── test │ └── java │ └── jattack │ ├── ast │ └── Z3Test.java │ ├── examples │ ├── SkTestArgumentAnnotation.java │ ├── SkTestArgumentWithGenericTypeUsingArgumentAnnotation.java │ ├── SkTestArgumentWithGenericTypeUsingArgumentsAnnotation.java │ ├── SkTestArgumentsAnnotation.java │ ├── SkTestArithmeticWithDouble.java │ ├── SkTestArrayIndexOutOfBoundExceptionWhenGetting.java │ ├── SkTestArrayIndexOutOfBoundExceptionWhenSetting.java │ ├── SkTestArrayNullPointerException.java │ ├── SkTestAssignmentApis.java │ ├── SkTestBlockStmtApis.java │ ├── SkTestBoolIdApis.java │ ├── SkTestCastApi.java │ ├── SkTestClassCastException.java │ ├── SkTestDeadForLoopElimination.java │ ├── SkTestDividedByZeroException.java │ ├── SkTestDoubleIdApis.java │ ├── SkTestDoubleValApis.java │ ├── SkTestDynamicUseCase.java │ ├── SkTestEscapingSpecialChars.java │ ├── SkTestExceptionCaughtInTemplate.java │ ├── SkTestExceptionInArgumentMethods.java │ ├── SkTestExceptionInArgumentsMethod.java │ ├── SkTestExceptionInEvaluatingMultiDimArrays.java │ ├── SkTestHoleInArgument.java │ ├── SkTestHoleInConstructor.java │ ├── SkTestHoleInStaticInitializer.java │ ├── SkTestIdAutoInfer.java │ ├── SkTestIfStmtApis.java │ ├── SkTestImValApis.java │ ├── SkTestIntArrRelatedApis.java │ ├── SkTestIntValApis.java │ ├── SkTestLocalVariableShadowsField.java │ ├── SkTestMultiDimensionArrays.java │ ├── SkTestNonCompilableGeneratedProgram.java │ ├── SkTestNonStaticEntryMethodWithSeparateArgumentMethods.java │ ├── SkTestNonStaticEntryMethodWithSingleArgumentsMethod.java │ ├── SkTestOptStopEarlyCorrectnessForCollection.java │ ├── SkTestOptStopEarlyCorrectnessForImmutable.java │ ├── SkTestOptStopEarlyCorrectnessForJDKClass.java │ ├── SkTestOptStopEarlyCorrectnessForObject.java │ ├── SkTestPreIncApis.java │ ├── SkTestPrimitiveArrRelatedApis.java │ ├── SkTestPrimitiveIdApis.java │ ├── SkTestPrimitiveValApis.java │ ├── SkTestReceiverOfEntryMethodIsNull.java │ ├── SkTestRefArrRelatedApis.java │ ├── SkTestRefIdApis.java │ ├── SkTestRefIdCastToSuperTypeWhenFilled.java │ ├── SkTestRefIdWorksWhenVarIsNull.java │ ├── SkTestShiftApis.java │ ├── SkTestShortCircuitEvaluation.java │ ├── SkTestSolverAidWithArrays.java │ ├── SkTestStaticFieldReset.java │ ├── SkTestStaticFieldResetForNestedClass.java │ ├── SkTestTryStmtApis.java │ ├── SkTestVoidReturnEntryMethod.java │ └── SkTestWhileStmtApis.java │ ├── log │ └── LogTest.java │ ├── transformer │ └── HoleExtractorTest.java │ └── util │ └── UniqueListTest.java ├── csutil ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── settings.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── csutil │ │ ├── Helper.java │ │ ├── checksum │ │ └── WrappedChecksum.java │ │ ├── log │ │ └── Log.java │ │ └── util │ │ ├── ByteBufferUtil.java │ │ └── TypeUtil.java │ └── test │ └── java │ └── org │ └── csutil │ ├── checksum │ └── WrappedChecksumTest.java │ └── util │ ├── ByteBufferUtilTest.java │ └── ExtRandom.java ├── install.sh ├── jattack.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Emacs 2 | *~ 3 | \#*\# 4 | 5 | # IntelliJ 6 | .idea/ 7 | out/ 8 | *.iml 9 | 10 | # VS Code 11 | .vscode/ 12 | 13 | # Java 14 | *.class 15 | *.jar 16 | 17 | # Scripts 18 | *.log 19 | .jattack/ 20 | .downloads/ 21 | -------------------------------------------------------------------------------- /T.java: -------------------------------------------------------------------------------- 1 | import jattack.annotation.Entry; 2 | import static jattack.Boom.*; 3 | 4 | public class T { 5 | 6 | static int s1; 7 | static int s2; 8 | 9 | @Entry 10 | public static int m() { 11 | int[] arr = { s1++, s2, 1, 2, intVal().eval() }; 12 | for (int i = 0; i < arr.length; ++i) { 13 | if (intIdOrIntArrAccessExp().eval() <= s2 14 | || relation(intId("s2"), intIdOrIntArrAccessExp(), LE).eval()) { 15 | arr[i] &= arithmetic(intId(), intArrAccessExp(), ADD, MUL).eval(); 16 | } 17 | } 18 | return s1 + s2; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /bugs/checkstyle106/generated/SuppressionsStringPrinterm106TemplateGEN1.java: -------------------------------------------------------------------------------- 1 | package com.puppycrawl.tools.checkstyle; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.List; 7 | import java.util.Locale; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | import java.util.stream.Collectors; 11 | import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 12 | import com.puppycrawl.tools.checkstyle.api.DetailAST; 13 | import com.puppycrawl.tools.checkstyle.api.FileText; 14 | import com.puppycrawl.tools.checkstyle.xpath.XpathQueryGenerator; 15 | import static jattack.Boom.*; 16 | import jattack.annotation.*; 17 | import org.csutil.checksum.WrappedChecksum; 18 | 19 | public final class SuppressionsStringPrinterm106TemplateGEN1 { 20 | 21 | private static final Pattern VALID_SUPPRESSION_LINE_COLUMN_NUMBER_REGEX = Pattern.compile("^([0-9]+):([0-9]+)$"); 22 | 23 | private static final String LINE_SEPARATOR = System.getProperty("line.separator"); 24 | 25 | private SuppressionsStringPrinterm106TemplateGEN1() { 26 | } 27 | 28 | public static String printSuppressions(File file, String suppressionLineColumnNumber, int tabWidth) throws IOException, CheckstyleException { 29 | final Matcher matcher = VALID_SUPPRESSION_LINE_COLUMN_NUMBER_REGEX.matcher(suppressionLineColumnNumber); 30 | if (!matcher.matches()) { 31 | final String exceptionMsg = String.format(Locale.ROOT, "%s does not match valid format 'line:column'.", suppressionLineColumnNumber); 32 | throw new IllegalStateException(exceptionMsg); 33 | } 34 | final FileText fileText = new FileText(file.getAbsoluteFile(), System.getProperty("file.encoding", StandardCharsets.UTF_8.name())); 35 | final DetailAST detailAST = JavaParser.parseFileText(fileText, JavaParser.Options.WITH_COMMENTS); 36 | final int lineNumber = Integer.parseInt(matcher.group(1)); 37 | final int columnNumber = Integer.parseInt(matcher.group(2)); 38 | return generate(fileText, detailAST, lineNumber, columnNumber, tabWidth); 39 | } 40 | 41 | private static String generate(FileText fileText, DetailAST detailAST, int lineNumber, int columnNumber, int tabWidth) { 42 | final XpathQueryGenerator queryGenerator = new XpathQueryGenerator(detailAST, lineNumber, columnNumber, fileText, tabWidth); 43 | final List suppressions = queryGenerator.generate(); 44 | return suppressions.stream().collect(Collectors.joining(LINE_SEPARATOR, "", LINE_SEPARATOR)); 45 | } 46 | 47 | public static File nonPrim1() { 48 | return null; 49 | } 50 | 51 | public static String nonPrim2() { 52 | return null; 53 | } 54 | 55 | public static int intArg3() { 56 | return -922089966; 57 | } 58 | 59 | public static long main0(String[] args) { 60 | int N = 100000; 61 | if (args.length > 0) { 62 | N = Math.min(Integer.parseInt(args[0]), N); 63 | } 64 | WrappedChecksum cs = new WrappedChecksum(); 65 | for (int i = 0; i < N; ++i) { 66 | try { 67 | File arg1 = nonPrim1(); 68 | String arg2 = nonPrim2(); 69 | int arg3 = intArg3(); 70 | cs.update(printSuppressions(arg1, arg2, arg3)); 71 | } catch (Throwable e) { 72 | cs.update(e.getClass().getName()); 73 | } 74 | } 75 | cs.updateStaticFieldsOfClass(SuppressionsStringPrinterm106TemplateGEN1.class); 76 | return cs.getValue(); 77 | } 78 | 79 | public static void main(String[] args) { 80 | System.out.println(main0(args)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /bugs/checkstyle106/minimized/C.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To reproduce the bug, use JDK 16(<=16.0.2). 3 | * 4 | * $ javac C.java 5 | * $ java C 6 | * JVM will crash. 7 | * 8 | * Bug report: https://bugs.openjdk.java.net/browse/JDK-8271276 9 | */ 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class C { 14 | 15 | public static void m(String s) { 16 | Pattern pattern = Pattern.compile(""); 17 | Matcher matcher = pattern.matcher(s); 18 | } 19 | public static void main(String[] args) { 20 | for (int i = 0; i < 10_000; ++i) { 21 | try { 22 | m(null); 23 | } catch (Throwable e) { 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bugs/checkstyle106/template/SuppressionsStringPrinterm106Template.java: -------------------------------------------------------------------------------- 1 | package com.puppycrawl.tools.checkstyle; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.List; 7 | import java.util.Locale; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | import java.util.stream.Collectors; 11 | import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 12 | import com.puppycrawl.tools.checkstyle.api.DetailAST; 13 | import com.puppycrawl.tools.checkstyle.api.FileText; 14 | import com.puppycrawl.tools.checkstyle.xpath.XpathQueryGenerator; 15 | import static jattack.Boom.*; 16 | import jattack.annotation.*; 17 | 18 | public final class SuppressionsStringPrinterm106Template { 19 | 20 | private static final Pattern VALID_SUPPRESSION_LINE_COLUMN_NUMBER_REGEX = Pattern.compile("^([0-9]+):([0-9]+)$"); 21 | 22 | private static final String LINE_SEPARATOR = System.getProperty("line.separator"); 23 | 24 | private SuppressionsStringPrinterm106Template() { 25 | } 26 | 27 | @jattack.annotation.Entry() 28 | public static String printSuppressions(File file, String suppressionLineColumnNumber, int tabWidth) throws IOException, CheckstyleException { 29 | final Matcher matcher = VALID_SUPPRESSION_LINE_COLUMN_NUMBER_REGEX.matcher(suppressionLineColumnNumber); 30 | if (!matcher.matches()) { 31 | final String exceptionMsg = String.format(Locale.ROOT, "%s does not match valid format 'line:column'.", suppressionLineColumnNumber); 32 | throw new IllegalStateException(exceptionMsg); 33 | } 34 | final FileText fileText = new FileText(file.getAbsoluteFile(), System.getProperty("file.encoding", StandardCharsets.UTF_8.name())); 35 | final DetailAST detailAST = JavaParser.parseFileText(fileText, JavaParser.Options.WITH_COMMENTS); 36 | final int lineNumber = Integer.parseInt(matcher.group(1)); 37 | final int columnNumber = Integer.parseInt(matcher.group(2)); 38 | return generate(fileText, detailAST, lineNumber, columnNumber, tabWidth); 39 | } 40 | 41 | private static String generate(FileText fileText, DetailAST detailAST, int lineNumber, int columnNumber, int tabWidth) { 42 | final XpathQueryGenerator queryGenerator = new XpathQueryGenerator(detailAST, lineNumber, columnNumber, fileText, tabWidth); 43 | final List suppressions = queryGenerator.generate(); 44 | return suppressions.stream().collect(Collectors.joining(LINE_SEPARATOR, "", LINE_SEPARATOR)); 45 | } 46 | 47 | @Argument(1) 48 | public static File nonPrim1() { 49 | return null; 50 | } 51 | 52 | @Argument(2) 53 | public static String nonPrim2() { 54 | return null; 55 | } 56 | 57 | @Argument(3) 58 | public static int intArg3() { 59 | return intVal().eval(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /bugs/codec292/minimized/C.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To reproduce the bug, use JDK 8(<=8u341) or 11(<=11.0.13) or 3 | * 17(<=17.0.1). 4 | * 5 | * $ javac C.java 6 | * 7 | * # Compilation up to level 4 (default) 8 | * $ java C 9 | * # Output (incorrect and non-deterministic) 10 | * 5597 11 | * 12 | * # Compilation up to level 1 13 | * $ java -XX:TieredStopAtLevel=1 C 14 | * # Output (correct) 15 | * 10000 16 | * 17 | * Bug report: https://bugs.openjdk.java.net/browse/JDK-8271459 18 | */ 19 | public class C { 20 | 21 | static String m() { 22 | StringBuilder sb = new StringBuilder(-1); 23 | return sb.toString(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | int sum = 0; 28 | for (int i = 0; i < 10_000; ++i) { 29 | try { 30 | m(); 31 | } catch (Throwable e) { 32 | sum += 1; 33 | } 34 | } 35 | System.out.println(sum); // should be 10_000 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /bugs/compress208/minimized/C.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To reproduce the bug, use 11(<=11.0.12) or 16(<=16.0.2). 3 | * 4 | * $ javac C.java 5 | * $ java C 6 | * JVM will crash. 7 | * 8 | * Bug report: https://bugs.openjdk.java.net/browse/JDK-8271926 9 | */ 10 | import java.util.Arrays; 11 | 12 | public class C { 13 | 14 | private static void m() { 15 | int[] arr = { 0 }; 16 | int max = -1; 17 | for (int i : arr) { 18 | max = max; 19 | } 20 | Arrays.copyOf(arr, max); 21 | } 22 | 23 | public static void main(String[] args) { 24 | for (int i = 0; i < 10_000; ++i) { 25 | try { 26 | m(); 27 | } catch (Throwable e) { 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bugs/m12gen61/generated/M12GEN61.java: -------------------------------------------------------------------------------- 1 | import jattack.annotation.Entry; 2 | import static jattack.Boom.*; 3 | import org.csutil.checksum.WrappedChecksum; 4 | 5 | public class M12GEN61 { 6 | 7 | static int s1; 8 | 9 | static int s2; 10 | 11 | static int s3; 12 | 13 | static { 14 | } 15 | 16 | public static int m() { 17 | int var1 = -453613994 - s2; 18 | s2 = ~var1; 19 | s3 = (s3 - s1); 20 | int i1 = 0; 21 | while (i1++ < 20 && ((s1 > var1) || (s2 > s3))) { 22 | var1 *= s3 + (--s2); 23 | s1 ^= (var1 - s1); 24 | } 25 | return s1 + s2 + s3; 26 | } 27 | 28 | public static long main0(String[] args) { 29 | int N = 100000; 30 | if (args.length > 0) { 31 | N = Math.min(Integer.parseInt(args[0]), N); 32 | } 33 | WrappedChecksum cs = new WrappedChecksum(); 34 | for (int i = 0; i < N; ++i) { 35 | try { 36 | cs.update(m()); 37 | } catch (Throwable e) { 38 | if (e instanceof sketchy.exception.InvokedFromNotDriverException) { 39 | throw e; 40 | } 41 | cs.update(e.getClass().getName()); 42 | } 43 | } 44 | cs.updateStaticFieldsOfClass(M12GEN61.class); 45 | return cs.getValue(); 46 | } 47 | 48 | public static void main(String[] args) { 49 | System.out.println(main0(args)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /bugs/m12gen61/minimized/C.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To reproduce the bug, use JDK 8(<=8u261) or 11(<=11.0.8). 3 | * 4 | * $ javac C.java 5 | * 6 | * # Compilation up to level 1 7 | * $ java -XX:TieredStopAtLevel=1 C 8 | * # Output (correct) 9 | * 671240562 10 | * 11 | * # Compilation up to level 4 (default) 12 | * $ java C 13 | * # Output (incorrect and non-deterministic) 14 | * 703783828 15 | * 16 | * Bug report: https://bugs.openjdk.java.net/browse/JDK-8239244 17 | * CVE record: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14792 18 | */ 19 | public class C { 20 | 21 | static int s1; 22 | 23 | static int s2; 24 | 25 | private static void m() { 26 | int X = 4_194_304; 27 | int var1 = 0; 28 | int i = 0; 29 | s1 = s1 + X; 30 | while (i++ < 10 && (s1 <= s2 || s1 > X)) { 31 | s2 = --s1 + s2; 32 | var1 += s1 + s2; 33 | } 34 | } 35 | 36 | public static void main(String[] args) { 37 | for (int i = 0; i < 100_000; ++i) { 38 | m(); 39 | } 40 | System.out.println(s1 + s2); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /bugs/m12gen61/template/M12.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | /** 8 | * NOTE: C67. 9 | */ 10 | public class M12 { 11 | 12 | static int s1; 13 | static int s2; 14 | static int s3; 15 | 16 | @Entry 17 | public static int m() { 18 | int var1 = intVal().eval() - s2; 19 | s2 = ~var1; 20 | s3 = arithmetic(intId(), intId(), SUB, ADD, MUL).eval(); 21 | int i1 = 0; 22 | while (i1++ < intVal(1, 21).eval() 23 | && logic(relation(intId(true, "i1"), intId(true, "i1"), LE, GE, LT, GT), 24 | relation(intId(true, "i1"), intId(true, "i1"), LE, GE, LT, GT), 25 | OR, AND).eval()) { 26 | var1 *= intId(true, "i1").eval() + (--s2); 27 | s1 ^= arithmetic(intId(true, "i1"), intId(true, "i1"), SUB, ADD).eval(); 28 | } 29 | return s1 + s2 + s3; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bugs/m4gen152/generated/M4GEN152.java: -------------------------------------------------------------------------------- 1 | import jattack.annotation.Entry; 2 | import static jattack.Boom.*; 3 | import org.csutil.checksum.WrappedChecksum; 4 | 5 | public class M4GEN152 { 6 | 7 | static int s1; 8 | 9 | static int s2; 10 | 11 | static { 12 | } 13 | 14 | public static int m() { 15 | int[] arr1 = { s1, s2, 1193717173, 1279218896, -417627869 }; 16 | for (int i = 0; i < arr1.length; ++i) { 17 | if (((arr1[3] <= s2) || (s2 <= arr1[2]))) { 18 | arr1[i] &= (s1 - s2); 19 | } 20 | s1 ^= (s2 * s2); 21 | } 22 | s2 |= (s2 + arr1[3]); 23 | int ret = s1 + s2; 24 | for (int e : arr1) { 25 | ret += e; 26 | } 27 | return ret; 28 | } 29 | 30 | public static long main0(String[] args) { 31 | int N = 100000; 32 | if (args.length > 0) { 33 | N = Math.min(Integer.parseInt(args[0]), N); 34 | } 35 | WrappedChecksum cs = new WrappedChecksum(); 36 | for (int i = 0; i < N; ++i) { 37 | try { 38 | cs.update(m()); 39 | } catch (Throwable e) { 40 | if (e instanceof sketchy.exception.InvokedFromNotDriverException) { 41 | throw e; 42 | } 43 | cs.update(e.getClass().getName()); 44 | } 45 | } 46 | cs.updateStaticFieldsOfClass(M4GEN152.class); 47 | return cs.getValue(); 48 | } 49 | 50 | public static void main(String[] args) { 51 | System.out.println(main0(args)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /bugs/m4gen152/minimized/C.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To reproduce the bug, use JDK 11(<=11.0.9). 3 | * 4 | * $ javac C.java 5 | * $ java C 6 | * JVM will crash. 7 | * 8 | * Bug report: https://bugs.openjdk.java.net/browse/JDK-8258981 9 | */ 10 | public class C { 11 | 12 | static int s1; 13 | 14 | static int s2; 15 | 16 | public static void m() { 17 | int[] arr1 = { s1, s2, 1, 2, 0 }; 18 | for (int i = 0; i < arr1.length; ++i) { 19 | if (arr1[3] <= s2 || s2 <= arr1[2]) { 20 | arr1[i] &= s1; 21 | } 22 | } 23 | } 24 | 25 | public static void main(String[] args) { 26 | for (int i = 0; i < 100_000; ++i) { 27 | m(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /bugs/m4gen152/template/M4.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | /** 8 | * NOTE: Arrays. 9 | */ 10 | public class M4 { 11 | 12 | static int s1; 13 | static int s2; 14 | 15 | @Entry 16 | public static int m() { 17 | int[] arr1 = { s1, s2, intVal().eval(), intVal().eval(), intVal().eval() }; 18 | for (int i = 0; i < arr1.length; ++i) { 19 | if (logic(relation(intIdOrIntArrAccessExp(true, "i"), intIdOrIntArrAccessExp(true, "i"), LE), 20 | relation(intIdOrIntArrAccessExp(true, "i"), intIdOrIntArrAccessExp(true, "i"), LE), 21 | OR, AND).eval()) { 22 | arr1[i] &= arithmetic(intIdOrIntArrAccessExp(true, "i"), intIdOrIntArrAccessExp(true, "i"), SUB, ADD, MUL).eval(); 23 | } 24 | s1 ^= arithmetic(intIdOrIntArrAccessExp(true, "i"), intIdOrIntArrAccessExp(true, "i"), SUB, ADD, MUL).eval(); 25 | } 26 | s2 |= arithmetic(intIdOrIntArrAccessExp(), intIdOrIntArrAccessExp(), SUB, ADD, MUL).eval(); 27 | 28 | int ret = s1 + s2; 29 | for (int e : arr1) { 30 | ret += e; 31 | } 32 | return ret; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /bugs/math182/minimized/C.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To reproduce the bug, use JDK 8(<=8u311) or 11(<=11.0.13) or 3 | * 17(<=17.0.1). 4 | * 5 | * $ javac C.java 6 | * $ java -Xmx7g C 7 | * JVM will crash. 8 | * 9 | * Bug report: https://bugs.openjdk.java.net/browse/JDK-8271130 10 | * CVE record: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21305 11 | */ 12 | public class C { 13 | 14 | public static void m() { 15 | int X = 536_870_908; 16 | int[] a = new int[X + 1]; // Object[] also works 17 | a[X] = 1; 18 | } 19 | 20 | public static void main(String[] args) { 21 | for (int i = 0; i < 1_000; ++i) { 22 | m(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | readonly _DIR="$( cd -P "$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )" )" && pwd )" 4 | 5 | # Download a buggy jdk to reproduce a bug. 6 | readonly DL_DIR="${_DIR}/.downloads" 7 | mkdir -p "${DL_DIR}" 8 | readonly JDK_DIR="${DL_DIR}/jdk-11.0.8+10" 9 | if [[ ! -f ${JDK_DIR}/bin/java || ! -f ${JDK_DIR}/bin/javac ]]; then 10 | echo "Download JDK..." 11 | rm -f "${DL_DIR}/openjdk11.tar.gz" 12 | wget -q 'https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.8_10.tar.gz' -O ${DL_DIR}/openjdk11.tar.gz 13 | if [[ $? -ne 0 ]]; then 14 | echo "ERROR: Downloading JDK failed!" >&2 15 | exit 1 16 | fi 17 | rm -fr "${JDK_DIR}" && mkdir -p "${JDK_DIR}" 18 | tar xf "${DL_DIR}/openjdk11.tar.gz" -C "${JDK_DIR}" --strip-components=1 \ 19 | && rm -f "${DL_DIR}/openjdk11.tar.gz" 20 | fi 21 | export PATH="${JDK_DIR}/bin:${PATH}" 22 | export JAVA_HOME="${JDK_DIR}" 23 | 24 | # Install jattack (JDK >=11 and Python 3.8) 25 | ./tool/install.sh 26 | 27 | # Run jattack (We fix random seed by --seed 42 to ensure the bug is 28 | # reproduced consistently) 29 | ./tool/jattack --clz T --n_gen 3 --seed 42 30 | -------------------------------------------------------------------------------- /tool/.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | .gradle/ 3 | build/ 4 | !gradle-wrapper.jar 5 | 6 | # Install 7 | /jattack 8 | -------------------------------------------------------------------------------- /tool/api/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Java Library project to get you started. 5 | * For more details take a look at the Java Libraries chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/6.0.1/userguide/java_library_plugin.html 7 | */ 8 | 9 | plugins { 10 | id 'java-library' 11 | id 'com.github.johnrengelman.shadow' version '7.0.0' 12 | } 13 | 14 | group 'jattack' 15 | version '0.84.15' 16 | 17 | repositories { 18 | mavenCentral() 19 | } 20 | 21 | dependencies { 22 | implementation 'csutil:csutil' 23 | implementation 'com.github.javaparser:javaparser-core:3.25.0' 24 | implementation 'io.github.tudo-aqua:z3-turnkey:4.8.10' 25 | implementation 'org.ow2.asm:asm:9.4' 26 | implementation 'org.ow2.asm:asm-tree:9.4' 27 | testImplementation 'junit:junit:4.12' 28 | } 29 | 30 | java { 31 | sourceCompatibility = JavaVersion.VERSION_11 32 | targetCompatibility = JavaVersion.VERSION_11 33 | } 34 | 35 | // compileJava { 36 | // options.compilerArgs << '-Xlint:unchecked' 37 | // } 38 | 39 | jar { 40 | manifest { 41 | attributes('Manifest-Version': '1.0', 42 | 'Main-Class': 'jattack.driver.Driver', 43 | 'Implementation-Version': project.version, 44 | 'Premain-Class': 'jattack.compiler.Agent', 45 | 'Can-Redefine-Classes': 'true', 46 | 'Can-Retransform-Classes': 'true', 47 | 'Agent-Class': 'jattack.compiler.Agent' 48 | ) 49 | } 50 | } 51 | 52 | shadowJar { 53 | // archiveBaseName.set('jattack') // default rootProject.name 54 | // archiveClassifier.set('nodeps') // default 'all' 55 | // archiveVersion.set('1.0') // default version 56 | relocate 'org.objectweb.asm', 'jattack.asm' 57 | } 58 | 59 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 60 | task csutilJar(type: ShadowJar) { 61 | archiveClassifier.set("with-csutil") 62 | from sourceSets.main.output 63 | configurations = [project.configurations.compileClasspath] 64 | dependencies { 65 | // Include only csutil 66 | include(dependency('csutil:csutil')) 67 | include(dependency('org.ow2.asm:asm')) 68 | include(dependency('org.ow2.asm:asm-tree')) 69 | exclude('module-info.class') 70 | relocate('org.objectweb.asm', 'jattack.asm') 71 | } 72 | 73 | manifest { 74 | // Inherit manifest from jar task 75 | inheritFrom project.tasks.jar.manifest 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tool/api/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EngineeringSoftware/jattack/212ce3ebbc4ebc80691aecfcb94c3c2995f2bc9e/tool/api/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /tool/api/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /tool/api/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/6.0.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'jattack' 11 | includeBuild '../csutil' 12 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/annotation/Argument.java: -------------------------------------------------------------------------------- 1 | package jattack.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotates a static method that returns a value that is used as one 11 | * argument of the entry method. The value of the annotation 12 | * represents which argument, e.g., {@code @Argument(1)} means the 13 | * first argument. 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target(ElementType.METHOD) 17 | @Documented 18 | public @interface Argument { 19 | int value(); 20 | } 21 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/annotation/Arguments.java: -------------------------------------------------------------------------------- 1 | package jattack.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotates a static method that returns an array of values that are 11 | * used as all the arguments when invoking the entry method. 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.METHOD) 15 | @Documented 16 | public @interface Arguments { 17 | } 18 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/annotation/Entry.java: -------------------------------------------------------------------------------- 1 | package jattack.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotates the entry method. 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.METHOD) 14 | @Documented 15 | public @interface Entry { 16 | } 17 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/AltExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.Itr; 4 | import jattack.ast.exp.iterator.LitItr; 5 | import jattack.ast.visitor.Visitor; 6 | import jattack.driver.Driver; 7 | import jattack.util.UniqueList; 8 | 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | /** 13 | * Alternative expression. 14 | */ 15 | public class AltExp extends Exp { 16 | 17 | private UniqueList> exps; 18 | 19 | private Exp exp; 20 | 21 | private boolean emptyPruned; 22 | 23 | public AltExp(List> exps) { 24 | if (exps.isEmpty()) { 25 | throw new IllegalArgumentException("No expression passed!"); 26 | } 27 | this.exps = new UniqueList<>(exps); 28 | this.exp = null; 29 | this.emptyPruned = false; 30 | } 31 | 32 | @Override 33 | public void stepRand() { 34 | removeEmptyExps(); 35 | // TODO: consider if we need uniform distribution of choices 36 | // inside each expression rather than of expressions. 37 | exp = exps.pick(Driver.rand); 38 | exp.stepRand(); 39 | } 40 | 41 | @Override 42 | public boolean hasRandChoice() { 43 | for (Exp e : exps) { 44 | if (e.hasRandChoice()) { 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | 51 | @Override 52 | protected void setItr() { 53 | removeEmptyExps(); 54 | itr = new LitItr<>(exps) { 55 | 56 | private Itr currItr; 57 | 58 | @Override 59 | public void next() { 60 | super.next(); 61 | if (currItr == null || !currItr.hasNext()) { 62 | exp = iterator.next(); 63 | currItr = exp.itr(); 64 | } 65 | currItr.next(); 66 | } 67 | 68 | @Override 69 | public void reset() { 70 | super.reset(); 71 | currItr = null; 72 | for (Exp exp : exps) { 73 | exp.itr().reset(); 74 | } 75 | } 76 | 77 | @Override 78 | public boolean hasNext() { 79 | if (isReset()) { 80 | return iterator.hasNext(); 81 | } 82 | return iterator.hasNext() || currItr.hasNext(); 83 | } 84 | }; 85 | } 86 | 87 | @Override 88 | public Class getType() { 89 | return exps.get(0).getType(); 90 | } 91 | 92 | @Override 93 | public void accept(Visitor v) { 94 | if (v.visit(this)) { 95 | exp.accept(v); 96 | v.endVisit(this); 97 | } 98 | } 99 | 100 | private void removeEmptyExps() { 101 | if (emptyPruned) { 102 | return; 103 | } 104 | List> nonEmptyExps = new LinkedList<>(); 105 | for (Exp e : exps) { 106 | if (e.hasChoice()) { 107 | nonEmptyExps.add(e); 108 | } 109 | } 110 | if (nonEmptyExps.isEmpty()) { 111 | throw new RuntimeException("No expression can be used!"); 112 | } 113 | exps = new UniqueList<>(nonEmptyExps); 114 | emptyPruned = true; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/AssignExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.ChainItr; 4 | import jattack.ast.nodetypes.NodeWithSideEffect; 5 | import jattack.ast.visitor.Visitor; 6 | 7 | public class AssignExp extends Exp implements NodeWithSideEffect { 8 | 9 | private final LHSExp target; 10 | 11 | private final Exp value; 12 | 13 | @Override 14 | public void updateVal(T val) { 15 | target.updateVal(val); 16 | } 17 | 18 | public AssignExp(LHSExp target, Exp value) { 19 | this.target = target; 20 | this.value = value; 21 | } 22 | 23 | @Override 24 | protected void setItr() { 25 | itr = new ChainItr(target.itr(), value.itr()); 26 | } 27 | 28 | @Override 29 | public void stepRand() { 30 | target.stepRand(); 31 | value.stepRand(); 32 | } 33 | 34 | @Override 35 | public boolean hasRandChoice() { 36 | return target.hasRandChoice() && value.hasRandChoice(); 37 | } 38 | 39 | @Override 40 | public Class getType() { 41 | return target.getType(); 42 | } 43 | 44 | @Override 45 | public void accept(Visitor v) { 46 | if (v.visit(this)) { 47 | value.accept(v); 48 | target.accept(v); 49 | v.endVisit(this); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/BAriExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.nodetypes.NodeWithOperator; 4 | import jattack.ast.exp.iterator.ChainItr; 5 | import jattack.ast.operator.AriOp; 6 | import jattack.ast.operator.OpNode; 7 | import jattack.ast.visitor.Visitor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Binary arithmetic expression. 13 | */ 14 | public class BAriExp extends Exp implements NodeWithOperator { 15 | 16 | // We assume left and right are not the same object. 17 | private final Exp left; 18 | 19 | private final Exp right; 20 | 21 | private final OpNode op; 22 | 23 | public BAriExp(Exp left, Exp right, List operators) { 24 | this.left = left; 25 | this.right = right; 26 | this.op = new OpNode<>(operators); 27 | } 28 | 29 | @Override 30 | public AriOp getOp() { 31 | return op.getOp(); 32 | } 33 | 34 | @Override 35 | protected void setItr() { 36 | itr = new ChainItr(op.itr(), left.itr(), right.itr()); 37 | } 38 | 39 | @Override 40 | public void stepRand() { 41 | left.stepRand(); 42 | right.stepRand(); 43 | op.stepRand(); 44 | } 45 | 46 | @Override 47 | public boolean hasRandChoice() { 48 | return left.hasRandChoice() && right.hasRandChoice() && op.hasRandChoice(); 49 | } 50 | 51 | @Override 52 | public Class getType() { 53 | return left.getType(); 54 | } 55 | 56 | @Override 57 | public void accept(Visitor v) { 58 | if (v.visit(this)) { 59 | left.accept(v); 60 | right.accept(v); 61 | v.endVisit(this); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/BoolVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.LitItr; 4 | import jattack.ast.visitor.Visitor; 5 | import jattack.driver.Driver; 6 | import jattack.util.UniqueList; 7 | 8 | /** 9 | * Boolean literal expression. 10 | */ 11 | public class BoolVal extends LitExp { 12 | 13 | private final UniqueList vals; 14 | 15 | /** 16 | * Constructor for both random and systematic exploration. 17 | */ 18 | public BoolVal() { 19 | this.vals = new UniqueList<>(); 20 | vals.add(false); 21 | vals.add(true); 22 | } 23 | 24 | @Override 25 | protected void setItr() { 26 | itr = new LitItr<>(vals) { 27 | @Override 28 | public void next() { 29 | super.next(); 30 | val = iterator.next(); 31 | } 32 | }; 33 | } 34 | 35 | @Override 36 | public void stepRand() { 37 | val = Driver.rand.nextBoolean(); 38 | } 39 | 40 | @Override 41 | public Class getType() { 42 | return Boolean.class; 43 | } 44 | 45 | @Override 46 | public void accept(Visitor v) { 47 | if (v.visit(this)) { 48 | v.endVisit(this); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ByteVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.RangeItr; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | import java.util.List; 7 | 8 | public class ByteVal extends NumberVal { 9 | 10 | /** 11 | * Constructor only for random exploration. 12 | */ 13 | public ByteVal() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Constructor only for systematic exploration. 19 | */ 20 | public ByteVal(List vals) { 21 | super(vals); 22 | } 23 | 24 | /** 25 | * Constructor accepting lower and upper bounds. 26 | */ 27 | public ByteVal(byte low, byte high) { 28 | super(low, high); 29 | } 30 | 31 | @Override 32 | protected void setBoundedItr() { 33 | itr = new RangeItr((byte) low, (byte) high) { 34 | @Override 35 | public void next() { 36 | super.next(); 37 | val = (byte) getCurrent(); 38 | } 39 | }; 40 | } 41 | 42 | @Override 43 | public Class getType() { 44 | return Byte.class; 45 | } 46 | 47 | @Override 48 | public void accept(Visitor v) { 49 | if (v.visit(this)) { 50 | v.endVisit(this); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/CastExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | public class CastExp extends Exp { 6 | 7 | private final Exp exp; 8 | private final Class type; 9 | 10 | public CastExp(Class type, Exp exp) { 11 | if (type.isPrimitive()) { 12 | throw new RuntimeException("target type cannot be primitive type: " + type); 13 | } 14 | this.type = type; 15 | this.exp = exp; 16 | } 17 | 18 | /** 19 | * Set the iterator. 20 | */ 21 | @Override 22 | protected void setItr() { 23 | itr = exp.itr(); 24 | } 25 | 26 | /** 27 | * Step to next random choice; 28 | */ 29 | @Override 30 | public void stepRand() { 31 | exp.stepRand(); 32 | } 33 | 34 | /** 35 | * Returns if the exp has choice under random search strategy. 36 | */ 37 | @Override 38 | public boolean hasRandChoice() { 39 | return exp.hasRandChoice(); 40 | } 41 | 42 | @Override 43 | public Class getType() { 44 | return type; 45 | } 46 | 47 | @Override 48 | public void accept(Visitor v) { 49 | if (v.visit(this)) { 50 | exp.accept(v); 51 | v.endVisit(this); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/CharVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.LitItr; 4 | import jattack.ast.visitor.Visitor; 5 | import jattack.driver.Driver; 6 | import jattack.util.TypeUtil; 7 | import jattack.util.UniqueList; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Char literal expression. 13 | */ 14 | public class CharVal extends LitExp { 15 | 16 | private final UniqueList vals; 17 | 18 | /** 19 | * Constructor only for random exploration. 20 | */ 21 | public CharVal() { 22 | this.vals = null; 23 | } 24 | 25 | /** 26 | * Constructor only for systematic exploration. 27 | */ 28 | public CharVal(List vals) { 29 | if (vals.isEmpty()) { 30 | throw new RuntimeException("No values that can be used!"); 31 | } 32 | this.vals = new UniqueList<>(vals); 33 | // We leave initialization of val done in eval(). val will not 34 | // be initialized until next() or step() is called. 35 | } 36 | 37 | @Override 38 | public String asStr() { 39 | // Needs to escape single quote and backslash 40 | return "'" + TypeUtil.charAsString(getVal()) + "'"; 41 | } 42 | 43 | @Override 44 | protected void setItr() { 45 | itr = new LitItr<>(vals) { 46 | @Override 47 | public void next() { 48 | super.next(); 49 | val = iterator.next(); 50 | } 51 | }; 52 | } 53 | 54 | @Override 55 | public void stepRand() { 56 | val = Driver.rand.nextChar(); 57 | } 58 | 59 | @Override 60 | public Class getType() { 61 | return Character.class; 62 | } 63 | 64 | @Override 65 | public void accept(Visitor v) { 66 | if (v.visit(this)) { 67 | v.endVisit(this); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/DoubleVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Double literal expression. 9 | */ 10 | public class DoubleVal extends NumberVal { 11 | 12 | /** 13 | * Constructor only for random exploration 14 | */ 15 | public DoubleVal() { 16 | super(); 17 | } 18 | 19 | /** 20 | * Constructor only for systematic exploration. 21 | */ 22 | public DoubleVal(List vals) { 23 | super(vals); 24 | } 25 | 26 | /** 27 | * Constructor accepting lower and upper bounds. 28 | */ 29 | public DoubleVal(double low, double high) { 30 | super(low, high); 31 | } 32 | 33 | @Override 34 | public Class getType() { 35 | return Double.class; 36 | } 37 | 38 | @Override 39 | protected void setBoundedItr() { 40 | // Bounded range systematic exploration does not make sense 41 | // for a double. 42 | throw new RuntimeException( 43 | "Bounded range systematic exploration does not make" + 44 | "sense for a range of double."); 45 | } 46 | 47 | @Override 48 | public void accept(Visitor v) { 49 | if (v.visit(this)) { 50 | v.endVisit(this); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/Exp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.Node; 4 | import jattack.ast.nodetypes.NodeWithType; 5 | import jattack.ast.visitor.EvalVisitor; 6 | 7 | /** 8 | * Abstract class for all expressions. 9 | * @param the type of value evaluated from this expression 10 | */ 11 | public abstract class Exp extends Node 12 | implements NodeWithType { 13 | 14 | /** 15 | * Really evaluate. 16 | */ 17 | @SuppressWarnings("unchecked") 18 | protected T evaluate() { 19 | EvalVisitor v = new EvalVisitor(); 20 | accept(v); 21 | return (T) v.getResult(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/FloatVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | import java.util.List; 6 | 7 | public class FloatVal extends NumberVal { 8 | 9 | /** 10 | * Constructor only for random exploration. 11 | */ 12 | public FloatVal() { 13 | super(); 14 | } 15 | 16 | /** 17 | * Constructor only for systematic exploration. 18 | */ 19 | public FloatVal(List vals) { 20 | super(vals); 21 | } 22 | 23 | /** 24 | * Constructor accepting lower and upper bounds. 25 | */ 26 | public FloatVal(float low, float high) { 27 | super(low, high); 28 | } 29 | 30 | @Override 31 | public String asStr() { 32 | return val + "F"; 33 | } 34 | 35 | @Override 36 | protected void setBoundedItr() { 37 | // Bounded range systematic exploration does not make sense 38 | // for a double. 39 | throw new RuntimeException( 40 | "Bounded range systematic exploration does not make" + 41 | "sense for a range of float."); 42 | } 43 | 44 | @Override 45 | public Class getType() { 46 | return Float.class; 47 | } 48 | 49 | @Override 50 | public void accept(Visitor v) { 51 | if (v.visit(this)) { 52 | v.endVisit(this); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/IdExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.LitItr; 4 | import jattack.ast.nodetypes.TerminalNode; 5 | import jattack.data.Data; 6 | import jattack.driver.Driver; 7 | import jattack.util.UniqueList; 8 | 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | /** 14 | * A base class for all identifier expressions. 15 | */ 16 | public abstract class IdExp extends LHSExp 17 | implements TerminalNode { 18 | 19 | private UniqueList ids; 20 | 21 | private final Set excludedIds; 22 | 23 | private String id; 24 | 25 | public IdExp(List ids) { 26 | this(false, ids); 27 | } 28 | 29 | public IdExp(boolean exclude, List ids) { 30 | if (exclude) { 31 | this.ids = null; 32 | this.excludedIds = new HashSet<>(ids); 33 | } else { 34 | this.ids = ids.isEmpty() ? null : new UniqueList<>(ids); 35 | this.excludedIds = new HashSet<>(); 36 | } 37 | } 38 | 39 | @Override 40 | public void updateVal(T val) { 41 | Data.updateMemory(id, val); 42 | } 43 | 44 | @SuppressWarnings("unchecked") 45 | @Override 46 | public T getVal() { 47 | return (T) Data.getFromMemoryValueOfSymbol(id); 48 | } 49 | 50 | @Override 51 | public String asStr() { 52 | // Cast to the expected type if we are not already of that 53 | // type, the casting is safe since the actual type is 54 | // guaranteed to be a subtype of the expected type. 55 | if (getType() != Data.getDeclaringTypeOfSymbol(id)) { 56 | return "((" + getType().getCanonicalName() + ")" + id + ")"; 57 | } 58 | return id; 59 | } 60 | 61 | @Override 62 | protected void setItr() { 63 | itr = new LitItr<>(ids()) { 64 | @Override 65 | public void next() { 66 | super.next(); 67 | setId(iterator.next()); 68 | } 69 | }; 70 | } 71 | 72 | @Override 73 | public void stepRand() { 74 | setId(ids().pick(Driver.rand)); 75 | } 76 | 77 | @Override 78 | public boolean hasRandChoice() { 79 | return !ids().isEmpty(); 80 | } 81 | 82 | private UniqueList ids() { 83 | if (ids == null) { 84 | // infer identifiers 85 | Set availableIds = Data.getSymbolsOfType(getType()); 86 | for (String id : excludedIds) { 87 | availableIds.remove(id); 88 | } 89 | ids = new UniqueList<>(availableIds); 90 | } 91 | return ids; 92 | } 93 | 94 | private void setId(String id) { 95 | this.id = id; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImBoolVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable boolean literal expression. 7 | */ 8 | public class ImBoolVal extends ImVal { 9 | 10 | public ImBoolVal(boolean val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public Class getType() { 16 | return Boolean.class; 17 | } 18 | 19 | @Override 20 | public void accept(Visitor v) { 21 | if (v.visit(this)) { 22 | v.endVisit(this); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImByteVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable byte literal expression. 7 | */ 8 | public final class ImByteVal extends ImVal { 9 | 10 | public ImByteVal(byte val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public Class getType() { 16 | return Byte.class; 17 | } 18 | 19 | @Override 20 | public void accept(Visitor v) { 21 | if (v.visit(this)) { 22 | v.endVisit(this); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImCharVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | import jattack.util.TypeUtil; 5 | 6 | public final class ImCharVal extends ImVal { 7 | 8 | public ImCharVal(char val) { 9 | super(val); 10 | } 11 | 12 | @Override 13 | public String asStr() { 14 | // Needs to escape single quote and backslash 15 | return "'" + TypeUtil.charAsString(getVal()) + "'"; 16 | } 17 | 18 | @Override 19 | public Class getType() { 20 | return Character.class; 21 | } 22 | 23 | @Override 24 | public void accept(Visitor v) { 25 | if (v.visit(this)) { 26 | v.endVisit(this); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImDoubleVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable double literal expression. 7 | */ 8 | public final class ImDoubleVal extends ImVal { 9 | 10 | public ImDoubleVal(double val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public Class getType() { 16 | return Double.class; 17 | } 18 | 19 | @Override 20 | public void accept(Visitor v) { 21 | if (v.visit(this)) { 22 | v.endVisit(this); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImFloatVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable float literal expression. 7 | */ 8 | public final class ImFloatVal extends ImVal { 9 | 10 | public ImFloatVal(float val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public String asStr() { 16 | return getVal() + "F"; 17 | } 18 | 19 | @Override 20 | public Class getType() { 21 | return Float.class; 22 | } 23 | 24 | @Override 25 | public void accept(Visitor v) { 26 | if (v.visit(this)) { 27 | v.endVisit(this); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImIntVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable int literal expression. 7 | */ 8 | public final class ImIntVal extends ImVal { 9 | 10 | public ImIntVal(int val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public Class getType() { 16 | return Integer.class; 17 | } 18 | 19 | @Override 20 | public void accept(Visitor v) { 21 | if (v.visit(this)) { 22 | v.endVisit(this); 23 | } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImLongVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable long literal expression. 7 | */ 8 | public final class ImLongVal extends ImVal { 9 | 10 | public ImLongVal(long val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public String asStr() { 16 | return getVal() + "L"; 17 | } 18 | 19 | @Override 20 | public Class getType() { 21 | return Long.class; 22 | } 23 | 24 | @Override 25 | public void accept(Visitor v) { 26 | if (v.visit(this)) { 27 | v.endVisit(this); 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImShortVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | /** 6 | * Immutable short literal expression. 7 | */ 8 | public final class ImShortVal extends ImVal { 9 | 10 | public ImShortVal(short val) { 11 | super(val); 12 | } 13 | 14 | @Override 15 | public Class getType() { 16 | return Short.class; 17 | } 18 | 19 | @Override 20 | public void accept(Visitor v) { 21 | if (v.visit(this)) { 22 | v.endVisit(this); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ImVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.ImItr; 4 | import jattack.ast.nodetypes.TerminalNode; 5 | 6 | /** 7 | * Common abstract class of immutable literal expressions. 8 | */ 9 | public abstract class ImVal extends Exp 10 | implements TerminalNode { 11 | 12 | private final T val; 13 | 14 | public ImVal(T val) { 15 | this.val = val; 16 | } 17 | 18 | @Override 19 | public T getVal() { 20 | return val; 21 | } 22 | 23 | @Override 24 | public String asStr() { 25 | return String.valueOf(val); 26 | } 27 | 28 | @Override 29 | protected void setItr() { 30 | itr = new ImItr(); 31 | } 32 | 33 | @Override 34 | public void stepRand() {} 35 | 36 | @Override 37 | public boolean hasRandChoice() { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/IntVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.RangeItr; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Int literal expression. 10 | */ 11 | public class IntVal extends NumberVal { 12 | 13 | /** 14 | * Constructor only for random exploration. 15 | */ 16 | public IntVal() { 17 | super(); 18 | } 19 | 20 | /** 21 | * Constructor only for systematic exploration. 22 | */ 23 | public IntVal(List vals) { 24 | super(vals); 25 | } 26 | 27 | /** 28 | * Constructor accepting lower and upper bounds. 29 | */ 30 | public IntVal(int low, int high) { 31 | super(low, high); 32 | } 33 | 34 | @Override 35 | public Class getType() { 36 | return Integer.class; 37 | } 38 | 39 | @Override 40 | protected void setBoundedItr() { 41 | itr = new RangeItr((int) low, (int) high) { 42 | @Override 43 | public void next() { 44 | super.next(); 45 | val = (int) getCurrent(); 46 | } 47 | }; 48 | } 49 | 50 | @Override 51 | public void accept(Visitor v) { 52 | if (v.visit(this)) { 53 | v.endVisit(this); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/LHSExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.nodetypes.NodeWithSideEffect; 4 | 5 | public abstract class LHSExp extends Exp implements NodeWithSideEffect { 6 | } 7 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/LitExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.nodetypes.TerminalNode; 4 | 5 | /** 6 | * A base class for all literal expressions, including boolean, 7 | * number and String. 8 | */ 9 | public abstract class LitExp extends Exp 10 | implements TerminalNode { 11 | 12 | protected T val; 13 | 14 | @Override 15 | public T getVal() { 16 | return val; 17 | } 18 | 19 | @Override 20 | public String asStr() { 21 | return String.valueOf(val); 22 | } 23 | 24 | @Override 25 | public boolean hasRandChoice() { 26 | return true; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/LogExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.nodetypes.NodeWithOperator; 4 | import jattack.ast.exp.iterator.ChainItr; 5 | import jattack.ast.operator.LogOp; 6 | import jattack.ast.operator.OpNode; 7 | import jattack.ast.visitor.Visitor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Logical expression. 13 | */ 14 | public class LogExp extends Exp implements NodeWithOperator { 15 | 16 | private final Exp left; 17 | 18 | private final Exp right; 19 | 20 | private final OpNode op; 21 | 22 | public LogExp(Exp left, Exp right, List operators) { 23 | this.left = left; 24 | this.right = right; 25 | this.op = new OpNode<>(operators); 26 | } 27 | 28 | @Override 29 | public LogOp getOp() { 30 | return op.getOp(); 31 | } 32 | 33 | @Override 34 | protected void setItr() { 35 | itr = new ChainItr(op.itr(), left.itr(), right.itr()); 36 | } 37 | 38 | @Override 39 | public void stepRand() { 40 | left.stepRand(); 41 | right.stepRand(); 42 | op.stepRand(); 43 | } 44 | 45 | @Override 46 | public boolean hasRandChoice() { 47 | return left.hasRandChoice() && right.hasRandChoice() && op.hasRandChoice(); 48 | } 49 | 50 | @Override 51 | public Class getType() { 52 | return Boolean.class; 53 | } 54 | 55 | @Override 56 | public void accept(Visitor v) { 57 | if (v.visit(this)) { 58 | left.accept(v); 59 | op.accept(v); // for short circuit evaluation 60 | right.accept(v); 61 | v.endVisit(this); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/LongVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.RangeItr; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Long literal expression. 10 | */ 11 | public class LongVal extends NumberVal { 12 | 13 | /** 14 | * Constructor only for random exploration 15 | */ 16 | public LongVal() { 17 | super(); 18 | } 19 | 20 | /** 21 | * Constructor only for systematic exploration. 22 | */ 23 | public LongVal(List vals) { 24 | super(vals); 25 | } 26 | 27 | /** 28 | * Constructor accepting lower and upper bounds. 29 | */ 30 | public LongVal(long low, long high) { 31 | super(low, high); 32 | } 33 | 34 | @Override 35 | public String asStr() { 36 | return val + "L"; 37 | } 38 | 39 | @Override 40 | public Class getType() { 41 | return Long.class; 42 | } 43 | 44 | @Override 45 | protected void setBoundedItr() { 46 | itr = new RangeItr((long) low, (long) high) { 47 | @Override 48 | public void next() { 49 | super.next(); 50 | val = getCurrent(); 51 | } 52 | }; 53 | } 54 | 55 | @Override 56 | public void accept(Visitor v) { 57 | if (v.visit(this)) { 58 | v.endVisit(this); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/NumberVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.LitItr; 4 | import jattack.driver.Driver; 5 | import jattack.util.TypeUtil; 6 | import jattack.util.UniqueList; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Number literal expression, i.e, short, byte, int, long, float, double 12 | */ 13 | public abstract class NumberVal extends LitExp { 14 | 15 | private final UniqueList vals; 16 | 17 | /* Bounds as input. */ 18 | private final boolean isBounded; 19 | protected Number low; // inclusive 20 | protected Number high; // exclusive 21 | 22 | /** 23 | * Constructor only for random exploration. 24 | */ 25 | public NumberVal() { 26 | this.vals = null; 27 | this.isBounded = false; 28 | } 29 | 30 | /** 31 | * Constructor only for systematic exploration. 32 | */ 33 | public NumberVal(List vals) { 34 | if (vals.isEmpty()) { 35 | throw new RuntimeException("No values that can be used!"); 36 | } 37 | this.vals = new UniqueList<>(vals); 38 | this.isBounded = false; 39 | // We leave initialization of val done in eval(). val will not 40 | // be initialized until next() or step() is called. 41 | } 42 | 43 | /** 44 | * Constructor accepting lower and upper bounds. 45 | */ 46 | public NumberVal(Number low, Number high) { 47 | if (TypeUtil.compare(low, high) >= 0) { 48 | throw new IllegalArgumentException("low must be less than high!"); 49 | } 50 | this.vals = null; 51 | this.isBounded = true; 52 | this.low = low; 53 | this.high = high; 54 | } 55 | 56 | protected abstract void setBoundedItr(); 57 | 58 | @Override 59 | protected void setItr() { 60 | if (isBounded) { 61 | setBoundedItr(); 62 | return; 63 | } 64 | itr = new LitItr<>(vals) { 65 | @Override 66 | public void next() { 67 | super.next(); 68 | val = iterator.next(); 69 | } 70 | }; 71 | } 72 | 73 | @SuppressWarnings("unchecked") 74 | @Override 75 | public void stepRand() { 76 | val = (T) (isBounded ? 77 | Driver.rand.nextNumber(getType(), low, high) : 78 | Driver.rand.nextNumber(getType())); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/PreIncExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.nodetypes.NodeWithSideEffect; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | public class PreIncExp extends Exp 7 | implements NodeWithSideEffect { 8 | 9 | private final LHSExp id; 10 | 11 | public PreIncExp(LHSExp id) { 12 | this.id = id; 13 | } 14 | 15 | @Override 16 | public void updateVal(N val) { 17 | id.updateVal(val); 18 | } 19 | 20 | @Override 21 | protected void setItr() { 22 | itr = id.itr(); 23 | } 24 | 25 | @Override 26 | public void stepRand() { 27 | id.stepRand(); 28 | } 29 | 30 | @Override 31 | public boolean hasRandChoice() { 32 | return id.hasRandChoice(); 33 | } 34 | 35 | @Override 36 | public Class getType() { 37 | return id.getType(); 38 | } 39 | 40 | @Override 41 | public void accept(Visitor v) { 42 | if (v.visit(this)) { 43 | id.accept(v); 44 | v.endVisit(this); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/RefId.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.visitor.Visitor; 4 | 5 | import java.util.List; 6 | 7 | public class RefId extends IdExp { 8 | 9 | private final Class type; 10 | 11 | public RefId(Class type, List ids) { 12 | this(type, false, ids); 13 | } 14 | 15 | public RefId(Class type, boolean exclude, List ids) { 16 | super(exclude, ids); 17 | this.type = type; 18 | } 19 | 20 | @Override 21 | public Class getType() { 22 | return type; 23 | } 24 | 25 | @Override 26 | public void accept(Visitor v) { 27 | if (v.visit(this)) { 28 | v.endVisit(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/RelExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.nodetypes.NodeWithOperator; 4 | import jattack.ast.exp.iterator.ChainItr; 5 | import jattack.ast.operator.OpNode; 6 | import jattack.ast.operator.RelOp; 7 | import jattack.ast.visitor.Visitor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Relational expression. 13 | */ 14 | public class RelExp extends Exp implements NodeWithOperator { 15 | 16 | private final Exp left; 17 | 18 | private final Exp right; 19 | 20 | private final OpNode op; 21 | 22 | public RelExp(Exp left, Exp right, List operators) { 23 | this.left = left; 24 | this.right = right; 25 | this.op = new OpNode<>(operators); 26 | } 27 | 28 | @Override 29 | public RelOp getOp() { 30 | return op.getOp(); 31 | } 32 | 33 | @Override 34 | protected void setItr() { 35 | itr = new ChainItr(op.itr(), left.itr(), right.itr()); 36 | } 37 | 38 | @Override 39 | public void stepRand() { 40 | left.stepRand(); 41 | right.stepRand(); 42 | op.stepRand(); 43 | } 44 | 45 | @Override 46 | public boolean hasRandChoice() { 47 | return left.hasRandChoice() && right.hasRandChoice() && op.hasRandChoice(); 48 | } 49 | 50 | @Override 51 | public Class getType() { 52 | return Boolean.class; 53 | } 54 | 55 | @Override 56 | public void accept(Visitor v) { 57 | if (v.visit(this)) { 58 | left.accept(v); 59 | right.accept(v); 60 | v.endVisit(this); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ShiftExp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.ChainItr; 4 | import jattack.ast.nodetypes.NodeWithOperator; 5 | import jattack.ast.operator.OpNode; 6 | import jattack.ast.operator.ShiftOp; 7 | import jattack.ast.visitor.Visitor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Binary shift expression. {@link N} can only be {@link Integer} or 13 | * {@link Long}; so is {@link M}. 14 | */ 15 | public class ShiftExp extends Exp 16 | implements NodeWithOperator { 17 | 18 | private final Exp left; 19 | 20 | private final Exp right; 21 | 22 | private final OpNode op; 23 | 24 | public ShiftExp(Exp left, Exp right, List operators) { 25 | this.left = left; 26 | this.right = right; 27 | this.op = new OpNode<>(operators); 28 | } 29 | 30 | @Override 31 | public ShiftOp getOp() { 32 | return op.getOp(); 33 | } 34 | 35 | @Override 36 | protected void setItr() { 37 | itr = new ChainItr(op.itr(), left.itr(), right.itr()); 38 | } 39 | 40 | @Override 41 | public void stepRand() { 42 | left.stepRand(); 43 | right.stepRand(); 44 | op.stepRand(); 45 | } 46 | 47 | @Override 48 | public boolean hasRandChoice() { 49 | return left.hasRandChoice() && right.hasRandChoice() && op.hasRandChoice(); 50 | } 51 | 52 | @Override 53 | public Class getType() { 54 | return left.getType(); 55 | } 56 | 57 | @Override 58 | public void accept(Visitor v) { 59 | if (v.visit(this)) { 60 | left.accept(v); 61 | right.accept(v); 62 | v.endVisit(this); 63 | } 64 | } 65 | 66 | public Exp getLeft() { 67 | return left; 68 | } 69 | 70 | public Exp getRight() { 71 | return right; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/ShortVal.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp; 2 | 3 | import jattack.ast.exp.iterator.RangeItr; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Short literal expression. 10 | */ 11 | public class ShortVal extends NumberVal { 12 | 13 | /** 14 | * Constructor only for random exploration. 15 | */ 16 | public ShortVal() { 17 | super(); 18 | } 19 | 20 | /** 21 | * Constructor only for systematic exploration. 22 | */ 23 | public ShortVal(List vals) { 24 | super(vals); 25 | } 26 | 27 | /** 28 | * Constructor accepting lower and upper bounds. 29 | */ 30 | public ShortVal(short low, short high) { 31 | super(low, high); 32 | } 33 | 34 | @Override 35 | public Class getType() { 36 | return Short.class; 37 | } 38 | 39 | @Override 40 | protected void setBoundedItr() { 41 | itr = new RangeItr((short) low, (short) high) { 42 | @Override 43 | public void next() { 44 | super.next(); 45 | val = (short) getCurrent(); 46 | } 47 | }; 48 | } 49 | 50 | @Override 51 | public void accept(Visitor v) { 52 | if (v.visit(this)) { 53 | v.endVisit(this); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/ChainItr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | /** 7 | * Chain iterator to concatenate more than one iterator. 8 | */ 9 | public class ChainItr extends ExpItr { 10 | 11 | private final Itr itr; 12 | 13 | /** 14 | * Constructor taking varargs. 15 | */ 16 | public ChainItr(Itr itr0, Itr itr1, Itr... itrs) { 17 | CombItr combItr = new CombItr(itr0, itr1); 18 | for (Itr itr : itrs) { 19 | combItr = new CombItr(combItr, itr); 20 | } 21 | this.itr = combItr; 22 | } 23 | 24 | /** 25 | * Constructor taking a list. 26 | */ 27 | public ChainItr(List itrs) { 28 | if (itrs.isEmpty()) { 29 | throw new IllegalArgumentException("itrs cannot be empty!"); 30 | } 31 | if (itrs.size() == 1) { 32 | this.itr = itrs.get(0); 33 | return; 34 | } 35 | // itrs.size() >= 2 36 | Iterator it = itrs.iterator(); 37 | CombItr combItr = new CombItr(it.next(), it.next()); 38 | while (it.hasNext()) { 39 | combItr = new CombItr(combItr, it.next()); 40 | } 41 | this.itr = combItr; 42 | } 43 | 44 | @Override 45 | public void next() { 46 | super.next(); 47 | itr.next(); 48 | } 49 | 50 | @Override 51 | public void reset() { 52 | super.reset(); 53 | itr.reset(); 54 | } 55 | 56 | @Override 57 | public boolean hasNext() { 58 | return itr.hasNext(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/CombItr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | /** 4 | * Combination iterator to combine two iterators. 5 | */ 6 | public class CombItr extends ExpItr { 7 | 8 | private final Itr lItr; 9 | private final Itr rItr; 10 | 11 | public CombItr(Itr lItr, Itr rItr) { 12 | this.lItr = lItr; 13 | this.rItr = rItr; 14 | } 15 | 16 | @Override 17 | public void next() { 18 | super.next(); 19 | // iteration order: right then left 20 | if (lItr.hasNext() && !rItr.hasNext()) { 21 | rItr.reset(); 22 | lItr.next(); 23 | } 24 | rItr.next(); 25 | if (lItr.isReset()) { 26 | lItr.next(); 27 | } 28 | } 29 | 30 | @Override 31 | public void reset() { 32 | super.reset(); 33 | lItr.reset(); 34 | rItr.reset(); 35 | } 36 | 37 | @Override 38 | public boolean hasNext() { 39 | return lItr.hasNext() || rItr.hasNext(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/ExpItr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | import jattack.ast.exp.Exp; 4 | 5 | /** 6 | * Abstract class for all iterators used by {@link Exp}. 7 | */ 8 | public abstract class ExpItr implements Itr { 9 | 10 | private boolean isReset; 11 | 12 | protected ExpItr() { 13 | isReset = true; 14 | } 15 | 16 | public void next() { 17 | if (!hasNext()) { 18 | throw new RuntimeException("No next!"); 19 | } 20 | isReset = false; 21 | } 22 | 23 | public void reset() { 24 | isReset = true; 25 | } 26 | 27 | public abstract boolean hasNext(); 28 | 29 | public boolean isReset() { 30 | return isReset; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/ImItr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | /** 4 | * Iterator for an immutable AST node that contains only one value 5 | * never changed. 6 | */ 7 | public class ImItr extends ExpItr { 8 | 9 | @Override 10 | public boolean hasNext() { 11 | return isReset(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/Itr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | /** 4 | * Interface implemented by all iterators. 5 | */ 6 | public interface Itr { 7 | 8 | void next(); 9 | 10 | void reset(); 11 | 12 | boolean hasNext(); 13 | 14 | boolean isReset(); 15 | } 16 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/LitItr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | /** 7 | * Iterator for a literal node such as IntVal, IntId, OpNode. 8 | * @param 9 | */ 10 | public abstract class LitItr extends ExpItr { 11 | 12 | private final List values; 13 | 14 | protected Iterator iterator; 15 | 16 | protected LitItr(List values) { 17 | this.values = values; 18 | this.iterator = this.values.iterator(); 19 | } 20 | 21 | @Override 22 | public void reset() { 23 | super.reset(); 24 | iterator = values.iterator(); 25 | } 26 | 27 | @Override 28 | public boolean hasNext() { 29 | return iterator.hasNext(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/exp/iterator/RangeItr.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.exp.iterator; 2 | 3 | /** 4 | * Range iterator with a given range of integers. 5 | */ 6 | public class RangeItr extends ExpItr { 7 | 8 | private final long low; 9 | private final long high; 10 | 11 | private long current; 12 | 13 | public RangeItr(long low, long high) { 14 | if (low >= high) { 15 | throw new IllegalArgumentException("low must be less than high!"); 16 | } 17 | if (low == Long.MIN_VALUE) { 18 | // TODO: support it 19 | throw new IllegalArgumentException("low must be strictly greater than Long.MIN_VALUE!"); 20 | } 21 | this.low = low; 22 | this.high = high; 23 | reset(); 24 | } 25 | 26 | @Override 27 | public void next() { 28 | super.next(); 29 | current++; 30 | } 31 | 32 | @Override 33 | public boolean hasNext() { 34 | return current < high - 1; 35 | } 36 | 37 | @Override 38 | public void reset() { 39 | super.reset(); 40 | current = low - 1L; // long 41 | } 42 | 43 | public long getCurrent() { 44 | if (isReset()) { 45 | throw new RuntimeException("current is unavailable when reset."); 46 | } 47 | return current; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/nodetypes/NodeWithOperator.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.nodetypes; 2 | 3 | import jattack.ast.operator.Op; 4 | 5 | public interface NodeWithOperator { 6 | O getOp(); 7 | } 8 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/nodetypes/NodeWithSideEffect.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.nodetypes; 2 | 3 | public interface NodeWithSideEffect { 4 | void updateVal(T val); 5 | } 6 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/nodetypes/NodeWithType.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.nodetypes; 2 | 3 | public interface NodeWithType { 4 | Class getType(); 5 | } 6 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/nodetypes/TerminalNode.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.nodetypes; 2 | 3 | /** 4 | * A terminal node. 5 | */ 6 | public interface TerminalNode { 7 | String asStr(); 8 | T getVal(); 9 | } 10 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/operator/AriOrShiftOp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.operator; 2 | 3 | public interface AriOrShiftOp extends Op{ 4 | } 5 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/operator/IncDecOp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.operator; 2 | 3 | public enum IncDecOp implements Op{ 4 | PRE_INC("++"); 5 | 6 | private final String strRep; 7 | 8 | IncDecOp(String strRep) { 9 | this.strRep = strRep; 10 | } 11 | 12 | @Override 13 | public String asStr() { 14 | return strRep; 15 | } 16 | 17 | public Number apply(Number operand) { 18 | if (operand instanceof Integer) { 19 | return apply(operand.intValue()); 20 | } else if (operand instanceof Long) { 21 | return apply(operand.longValue()); 22 | } else if (operand instanceof Double) { 23 | return apply(operand.doubleValue()); 24 | } else { 25 | throw new RuntimeException("Unsupported type: " + operand.getClass()); 26 | } 27 | } 28 | 29 | private int apply(int operand) { 30 | ++operand; 31 | return operand; 32 | } 33 | 34 | private long apply(long operand) { 35 | ++operand; 36 | return operand; 37 | } 38 | 39 | private double apply(double operand) { 40 | ++operand; 41 | return operand; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/operator/LogOp.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.operator; 2 | 3 | import com.microsoft.z3.BoolExpr; 4 | import com.microsoft.z3.Context; 5 | 6 | /** 7 | * Logical Operator. 8 | */ 9 | public enum LogOp implements Op { 10 | AND("&&"), 11 | OR("||"); 12 | 13 | private final String strRep; 14 | 15 | LogOp(String strRep) { 16 | this.strRep = strRep; 17 | } 18 | 19 | @Override 20 | public String asStr() { 21 | return strRep; 22 | } 23 | 24 | public boolean apply(boolean left, boolean right) { 25 | switch (this) { 26 | case AND: 27 | return left && right; 28 | case OR: 29 | return left || right; 30 | default: 31 | throw new RuntimeException("Unrecognized operator " + this.asStr()); 32 | } 33 | } 34 | 35 | @SuppressWarnings("unchecked") 36 | public BoolExpr buildZ3Expr(BoolExpr left, BoolExpr right, Context ctx) { 37 | switch (this) { 38 | case AND: 39 | return ctx.mkAnd(left, right); 40 | case OR: 41 | return ctx.mkOr(left, right); 42 | default: 43 | throw new RuntimeException("Unrecognized operator " + this.asStr()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/operator/Op.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.operator; 2 | 3 | /** 4 | * Interface for all operators. 5 | */ 6 | public interface Op { 7 | 8 | String asStr(); 9 | } 10 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/operator/OpNode.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.operator; 2 | 3 | import jattack.ast.Node; 4 | import jattack.ast.exp.iterator.LitItr; 5 | import jattack.ast.visitor.Visitor; 6 | import jattack.driver.Driver; 7 | import jattack.util.UniqueList; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Operator node. 13 | */ 14 | public class OpNode extends Node { 15 | 16 | private final UniqueList ops; 17 | 18 | private T op; 19 | 20 | public OpNode(List ops) { 21 | if (ops.isEmpty()) { 22 | throw new RuntimeException("No operators that can be used!"); 23 | } 24 | this.ops = new UniqueList<>(ops); 25 | } 26 | 27 | public T getOp() { 28 | return op; 29 | } 30 | 31 | @Override 32 | protected void setItr() { 33 | itr = new LitItr(ops) { 34 | @Override 35 | public void next() { 36 | super.next(); 37 | op = iterator.next(); 38 | } 39 | }; 40 | } 41 | 42 | @Override 43 | public void stepRand() { 44 | op = ops.pick(Driver.rand); 45 | } 46 | 47 | @Override 48 | public boolean hasRandChoice() { 49 | return !ops.isEmpty(); 50 | } 51 | 52 | @Override 53 | public void accept(Visitor v) { 54 | if (v.visit(this)) { 55 | v.endVisit(this); 56 | } 57 | } 58 | 59 | @Override 60 | public Void evaluate() { 61 | // Never called. 62 | return null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/AltStmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.exp.iterator.Itr; 4 | import jattack.ast.exp.iterator.LitItr; 5 | import jattack.ast.visitor.Visitor; 6 | import jattack.driver.Driver; 7 | import jattack.util.UniqueList; 8 | 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | /** 13 | * Alternative statement. 14 | */ 15 | // TODO: merge with AltExp somehow, which not quite intuitive since 16 | // because we want to keep inheritance: one is Exp while the other 17 | // is Stmt. 18 | public class AltStmt extends Stmt { 19 | 20 | private UniqueList stmts; 21 | 22 | private Stmt stmt; 23 | 24 | private boolean emptyPruned; 25 | 26 | public AltStmt(List stmts) { 27 | this.stmts = new UniqueList<>(stmts); 28 | this.stmt = null; 29 | this.emptyPruned = false; 30 | } 31 | 32 | @Override 33 | public void stepRand() { 34 | removeEmptyStmts(); 35 | // TODO: consider if we need uniform distribution of choices 36 | // inside each statement rather than of statement. 37 | stmt = stmts.pick(Driver.rand); 38 | stmt.stepRand(); 39 | } 40 | 41 | @Override 42 | public boolean hasRandChoice() { 43 | for (Stmt s : stmts) { 44 | if (s.hasRandChoice()) { 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | 51 | @Override 52 | protected void setItr() { 53 | removeEmptyStmts(); 54 | itr = new LitItr<>(stmts) { 55 | 56 | private Itr currItr; 57 | 58 | @Override 59 | public void next() { 60 | super.next(); 61 | if (currItr == null || !currItr.hasNext()) { 62 | stmt = iterator.next(); 63 | currItr = stmt.itr(); 64 | } 65 | currItr.next(); 66 | } 67 | 68 | @Override 69 | public void reset() { 70 | super.reset(); 71 | currItr = null; 72 | for (Stmt s : stmts) { 73 | s.itr().reset(); 74 | } 75 | } 76 | 77 | @Override 78 | public boolean hasNext() { 79 | if (isReset()) { 80 | return iterator.hasNext(); 81 | } 82 | return iterator.hasNext() || currItr.hasNext(); 83 | } 84 | }; 85 | } 86 | 87 | @Override 88 | public void accept(Visitor v) { 89 | stmt.accept(v); 90 | } 91 | 92 | private void removeEmptyStmts() { 93 | if (emptyPruned) { 94 | return; 95 | } 96 | List nonEmptyStmts = new LinkedList<>(); 97 | for (Stmt s : stmts) { 98 | if (s.hasChoice()) { 99 | nonEmptyStmts.add(s); 100 | } 101 | } 102 | if (nonEmptyStmts.isEmpty()) { 103 | throw new RuntimeException("No statement can be used!"); 104 | } 105 | stmts = new UniqueList<>(nonEmptyStmts); 106 | emptyPruned = true; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/BlockStmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.Node; 4 | import jattack.ast.exp.iterator.ChainItr; 5 | import jattack.ast.visitor.Visitor; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | public class BlockStmt extends Stmt { 11 | 12 | private final List stmts; 13 | 14 | public BlockStmt(List stmts) { 15 | this.stmts = stmts; 16 | } 17 | 18 | public List getStmts() { 19 | return stmts; 20 | } 21 | 22 | @Override 23 | protected void setItr() { 24 | itr = new ChainItr( 25 | stmts.stream().map(Node::itr).collect(Collectors.toList()) 26 | ); 27 | } 28 | 29 | @Override 30 | public void stepRand() { 31 | for (Stmt s : stmts) { 32 | s.stepRand(); 33 | } 34 | } 35 | 36 | @Override 37 | public boolean hasRandChoice() { 38 | for (Stmt s : stmts) { 39 | if (!s.hasRandChoice()) { 40 | return false; 41 | } 42 | } 43 | return true; 44 | } 45 | 46 | @Override 47 | public void accept(Visitor v) { 48 | v.visitStmt(this); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/ExprStmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.exp.Exp; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | /** 7 | * Expression as a statement. 8 | */ 9 | public class ExprStmt extends Stmt { 10 | 11 | private final Exp exp; 12 | 13 | public ExprStmt(Exp exp) { 14 | this.exp = exp; 15 | } 16 | 17 | @Override 18 | protected void setItr() { 19 | itr = exp.itr(); 20 | } 21 | 22 | @Override 23 | public void stepRand() { 24 | exp.stepRand(); 25 | } 26 | 27 | @Override 28 | public boolean hasRandChoice() { 29 | return exp.hasRandChoice(); 30 | } 31 | 32 | @Override 33 | public void accept(Visitor v) { 34 | v.visitStmt(this); 35 | } 36 | 37 | public Exp getExpression() { 38 | return exp; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/IfStmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.exp.Exp; 4 | import jattack.ast.exp.iterator.ChainItr; 5 | import jattack.ast.visitor.Visitor; 6 | 7 | /** 8 | * If Statement, with a condition expression, a then statement and an 9 | * optional else statement. 10 | */ 11 | public class IfStmt extends Stmt { 12 | 13 | private final Exp condition; 14 | 15 | private final Stmt thenStmt; 16 | 17 | private final Stmt elseStmt; 18 | 19 | public IfStmt(Exp condition, Stmt thenStmt) { 20 | this(condition, thenStmt, null); 21 | } 22 | 23 | public IfStmt(Exp condition, Stmt thenStmt, Stmt elseStmt) { 24 | this.condition = condition; 25 | this.thenStmt = thenStmt; 26 | this.elseStmt = elseStmt; 27 | } 28 | 29 | @Override 30 | protected void setItr() { 31 | itr = hasElseBranch() ? 32 | new ChainItr(condition.itr(), thenStmt.itr(), elseStmt.itr()) : 33 | new ChainItr(condition.itr(), thenStmt.itr()); 34 | } 35 | 36 | @Override 37 | public void stepRand() { 38 | condition.stepRand(); 39 | thenStmt.stepRand(); 40 | if (hasElseBranch()) { 41 | elseStmt.stepRand(); 42 | } 43 | } 44 | 45 | @Override 46 | public boolean hasRandChoice() { 47 | return condition.hasRandChoice() 48 | && thenStmt.hasRandChoice() 49 | && (!hasElseBranch() || elseStmt.hasRandChoice()); 50 | } 51 | 52 | @Override 53 | public void accept(Visitor v) { 54 | v.visitStmt(this); 55 | } 56 | 57 | public Exp getCondition() { 58 | return condition; 59 | } 60 | 61 | public Stmt getThenStmt() { 62 | return thenStmt; 63 | } 64 | 65 | /** 66 | * Returns else statement if non-nul, otherwise null. 67 | */ 68 | public Stmt getElseStmt() { 69 | return elseStmt; 70 | } 71 | 72 | public boolean hasElseBranch() { 73 | return elseStmt != null; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/Stmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.Node; 4 | import jattack.ast.visitor.EvalVisitor; 5 | 6 | /** 7 | * Abstract class for all statements. 8 | */ 9 | public abstract class Stmt extends Node { 10 | 11 | @Override 12 | public Void evaluate() { 13 | EvalVisitor v = new EvalVisitor(); 14 | accept(v); 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/TryStmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.exp.iterator.ChainItr; 4 | import jattack.ast.visitor.Visitor; 5 | 6 | public class TryStmt extends Stmt { 7 | 8 | // TODO: we hardcode catch ( e) for now 9 | private final Class exceptionType; 10 | 11 | private final BlockStmt tryBlock; 12 | private final BlockStmt catchBlock; 13 | private final BlockStmt finallyBlock; 14 | 15 | public TryStmt(BlockStmt tryBlock, Class exceptionType, BlockStmt catchBlock) { 16 | this(tryBlock, exceptionType, catchBlock, null); 17 | } 18 | 19 | public TryStmt(BlockStmt tryBlock, Class exceptionType, 20 | BlockStmt catchBlock, BlockStmt finallyBlock) { 21 | this.tryBlock = tryBlock; 22 | this.catchBlock = catchBlock; 23 | this.finallyBlock = finallyBlock; 24 | this.exceptionType = exceptionType; 25 | } 26 | 27 | public Class getExceptionType() { 28 | return exceptionType; 29 | } 30 | 31 | public BlockStmt getTryBlock() { 32 | return tryBlock; 33 | } 34 | 35 | public BlockStmt getCatchBlock() { 36 | return catchBlock; 37 | } 38 | 39 | public BlockStmt getFinallyBlock() { 40 | return finallyBlock; 41 | } 42 | 43 | public boolean hasFinally() { 44 | return finallyBlock != null; 45 | } 46 | 47 | @Override 48 | protected void setItr() { 49 | itr = new ChainItr(tryBlock.itr(), catchBlock.itr(), finallyBlock.itr()); 50 | } 51 | 52 | @Override 53 | public void stepRand() { 54 | tryBlock.stepRand(); 55 | catchBlock.stepRand(); 56 | finallyBlock.stepRand(); 57 | } 58 | 59 | @Override 60 | public boolean hasRandChoice() { 61 | return tryBlock.hasRandChoice() 62 | && catchBlock.hasRandChoice() 63 | && finallyBlock.hasRandChoice(); 64 | } 65 | 66 | @Override 67 | public void accept(Visitor v) { 68 | v.visitStmt(this); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/stmt/WhileStmt.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.stmt; 2 | 3 | import jattack.ast.exp.Exp; 4 | import jattack.ast.exp.iterator.ChainItr; 5 | import jattack.ast.visitor.Visitor; 6 | 7 | /** 8 | * While statement, with a condition expression and a body statement. 9 | */ 10 | public class WhileStmt extends Stmt { 11 | 12 | private final Exp condition; 13 | 14 | private final Stmt body; 15 | 16 | public WhileStmt(Exp condition, Stmt body) { 17 | this.condition = condition; 18 | this.body = body; 19 | } 20 | 21 | @Override 22 | protected void setItr() { 23 | itr = new ChainItr(condition.itr(), body.itr()); 24 | } 25 | 26 | @Override 27 | public void stepRand() { 28 | condition.stepRand(); 29 | body.stepRand(); 30 | } 31 | 32 | @Override 33 | public boolean hasRandChoice() { 34 | return condition.hasRandChoice() && body.hasRandChoice(); 35 | } 36 | 37 | @Override 38 | public void accept(Visitor v) { 39 | v.visitStmt(this); 40 | } 41 | 42 | public Exp getCondition() { 43 | return condition; 44 | } 45 | 46 | public Stmt getBody() { 47 | return body; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/ast/visitor/Visitable.java: -------------------------------------------------------------------------------- 1 | package jattack.ast.visitor; 2 | 3 | /** 4 | * Interface for all visitable classes. 5 | */ 6 | public interface Visitable { 7 | void accept(Visitor v); 8 | } 9 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/LocalVariableTableClassVisitor.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import jattack.Constants; 6 | import jattack.util.TypeUtil; 7 | 8 | /** 9 | * ClassVisitor to read local variable table from bytecode and to know 10 | * which local variables we have in every method body. 11 | */ 12 | public class LocalVariableTableClassVisitor extends ClassVisitor { 13 | 14 | private final String classBinName; 15 | 16 | public LocalVariableTableClassVisitor(ClassVisitor cv, String classBinName) { 17 | super(Constants.ASM_VERSION, cv); 18 | this.classBinName = classBinName; 19 | } 20 | 21 | @Override 22 | public MethodVisitor visitMethod( 23 | int access, 24 | String name, 25 | String desc, 26 | String signature, 27 | String[] exceptions) { 28 | MethodVisitor mv = super.visitMethod(access, name, 29 | desc, signature, exceptions); 30 | return new LocalVariableTableMethodVisitor( 31 | mv, 32 | TypeUtil.toFullMethodName(classBinName, name, desc)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/SaveLocalVarValuesClassVisitor.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | import jattack.Constants; 7 | import jattack.util.TypeUtil; 8 | 9 | /** 10 | * ClassVisitor to insert instructions to save values of local 11 | * variables right before each {@code eval()}. 12 | */ 13 | public class SaveLocalVarValuesClassVisitor extends ClassVisitor { 14 | 15 | private final String classBinName; 16 | 17 | public SaveLocalVarValuesClassVisitor(ClassVisitor cv, String classBinName) { 18 | super(Constants.ASM_VERSION, cv); 19 | this.classBinName = classBinName; 20 | } 21 | 22 | @Override 23 | public MethodVisitor visitMethod( 24 | int access, 25 | String name, 26 | String desc, 27 | String signature, 28 | String[] exceptions) { 29 | MethodVisitor mv = super.visitMethod(access, name, 30 | desc, signature, exceptions); 31 | return new SaveLocalVarValuesMethodVisitor( 32 | mv, 33 | TypeUtil.bin2Intern(classBinName), 34 | TypeUtil.toFullMethodName(classBinName, name, desc), 35 | (access & Opcodes.ACC_STATIC) != 0, 36 | name.equals("")); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/SaveUpdateUtil.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import jattack.data.Data; 4 | 5 | public class SaveUpdateUtil { 6 | 7 | public static void save() { 8 | Data.resetMemory(); 9 | } 10 | 11 | public static void update() { 12 | Data.resetMemory(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/StaticGenClassVisitor.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import jattack.Constants; 6 | import jattack.util.TypeUtil; 7 | 8 | /** 9 | * Class visitor for static generation. 10 | */ 11 | public class StaticGenClassVisitor extends ClassVisitor { 12 | 13 | private final String classBinName; 14 | 15 | public StaticGenClassVisitor(ClassVisitor cv, String classBinName) { 16 | super(Constants.ASM_VERSION, cv); 17 | this.classBinName = classBinName; 18 | } 19 | 20 | @Override 21 | public MethodVisitor visitMethod( 22 | int access, 23 | String name, 24 | String desc, 25 | String signature, 26 | String[] exceptions) { 27 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 28 | return new StaticGenMethodVisitor( 29 | mv, 30 | TypeUtil.toFullMethodName(classBinName, name, desc), 31 | access, 32 | name, 33 | desc, 34 | signature, 35 | exceptions); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/StaticInitRenamer.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.FieldVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | import jattack.Constants; 9 | import jattack.data.Data; 10 | import jattack.util.TypeUtil; 11 | 12 | /** 13 | * A {@link ClassVisitor} that renames <clinit> and create a new 14 | * method, which calls the original <clinit> method. 15 | *

16 | * Adapted from https://gitlab.ow2.org/asm/asm/-/blob/master/asm-commons/src/main/java/org/objectweb/asm/commons/StaticInitMerger.java 17 | */ 18 | public class StaticInitRenamer extends ClassVisitor { 19 | 20 | private final String newStaticInitName; 21 | private String owner; 22 | private MethodVisitor newClinitVisitor; 23 | 24 | public StaticInitRenamer(final String newStaticInitName, final ClassVisitor classVisitor) { 25 | super(Constants.ASM_VERSION, classVisitor); 26 | this.newStaticInitName = newStaticInitName; 27 | } 28 | 29 | @Override 30 | public void visit( 31 | final int version, 32 | final int access, 33 | final String name, 34 | final String signature, 35 | final String superName, 36 | final String[] interfaces) { 37 | super.visit(version, access, name, signature, superName, interfaces); 38 | this.owner = name; 39 | } 40 | 41 | @Override 42 | public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { 43 | // Unset any final modifier for fields so we can reset those 44 | // fields when reinitilazing the class 45 | return super.visitField(access & ~Opcodes.ACC_FINAL, name, descriptor, signature, value); 46 | } 47 | 48 | @Override 49 | public MethodVisitor visitMethod( 50 | final int access, 51 | final String name, 52 | final String descriptor, 53 | final String signature, 54 | final String[] exceptions) { 55 | MethodVisitor methodVisitor; 56 | if ("".equals(name)) { 57 | int newAccess = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC; 58 | String newName = newStaticInitName; 59 | methodVisitor = super.visitMethod(newAccess, newName, descriptor, signature, exceptions); 60 | 61 | // Creates a new that 62 | newClinitVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); 63 | // 1) invokes the renamed original 64 | newClinitVisitor.visitMethodInsn( 65 | Opcodes.INVOKESTATIC, 66 | owner, 67 | newName, 68 | descriptor, 69 | false); 70 | // 2) records the order of class initialization 71 | if (!Data.hasRecordedClassInitOrder()) { 72 | newClinitVisitor.visitLdcInsn(TypeUtil.intern2Bin(owner)); 73 | newClinitVisitor.visitMethodInsn( 74 | Opcodes.INVOKESTATIC, 75 | Constants.DATA_CLZ_INTERN_NAME, 76 | Constants.ADD_CLASS_INIT_METH_NAME, 77 | Constants.ADD_CLASS_INIT_METH_DESC, 78 | false); 79 | } 80 | newClinitVisitor.visitInsn(Opcodes.RETURN); 81 | newClinitVisitor.visitMaxs(0, 0); 82 | } else { 83 | methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); 84 | } 85 | return methodVisitor; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/Symbol.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * A field or local variable, wrapping name and type together. 7 | */ 8 | public class Symbol { 9 | 10 | private final String name; 11 | private final String desc; 12 | 13 | public Symbol(String name, String desc) { 14 | this.name = name; 15 | this.desc = desc; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public String getDesc() { 23 | return desc; 24 | } 25 | 26 | @Override 27 | public boolean equals(Object o) { 28 | if (this == o) return true; 29 | if (o == null || getClass() != o.getClass()) return false; 30 | Symbol symbol = (Symbol) o; 31 | return Objects.equals(name, symbol.name) && Objects.equals(desc, symbol.desc); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return Objects.hash(name, desc); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "Symbol{" + 42 | "name='" + name + '\'' + 43 | ", desc='" + desc + '\'' + 44 | '}'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/Var.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Class to represent a local variable, which has name, descriptor, 7 | * local variable index, start bytecode offset and end bytecode 8 | * offset. 9 | */ 10 | public class Var { 11 | 12 | private final String name; 13 | private final String desc; 14 | private final int index; 15 | private final int start; // inclusive 16 | private final int end; // exclusive 17 | 18 | public Var(String name, String desc, int index, int start, int end) { 19 | this.name = name; 20 | this.desc = desc; 21 | this.index = index; 22 | this.start = start; 23 | this.end = end; 24 | } 25 | 26 | public Var(Var other) { 27 | this(other.name, other.desc, other.index, other.start, other.end); 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public String getDesc() { 35 | return desc; 36 | } 37 | 38 | public int getIndex() { 39 | return index; 40 | } 41 | 42 | public int getStart() { 43 | return start; 44 | } 45 | 46 | public int getEnd() { 47 | return end; 48 | } 49 | 50 | public boolean isReachableAt(int offset) { 51 | return offset >= start && offset < end; 52 | } 53 | 54 | public boolean isArg() { 55 | return start == -1; 56 | } 57 | 58 | @Override 59 | public boolean equals(Object o) { 60 | if (this == o) return true; 61 | if (o == null || getClass() != o.getClass()) return false; 62 | Var var = (Var) o; 63 | return index == var.index 64 | && start == var.start 65 | && end == var.end 66 | && Objects.equals(name, var.name); 67 | } 68 | 69 | @Override 70 | public int hashCode() { 71 | return Objects.hash(name, index, start, end); 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | return "Var{" + 77 | "name='" + name + '\'' + 78 | ", desc='" + desc + '\'' + 79 | ", index=" + index + 80 | ", start=" + start + 81 | ", end=" + end + 82 | '}'; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/bytecode/VariableAnalyzer.java: -------------------------------------------------------------------------------- 1 | package jattack.bytecode; 2 | 3 | import org.objectweb.asm.ClassReader; 4 | import org.objectweb.asm.ClassWriter; 5 | 6 | /** 7 | * Util class to transform bytecode (to get local variables) and to 8 | * get fields. 9 | */ 10 | public class VariableAnalyzer { 11 | 12 | public static byte[] transformBytecode(String classBinName, byte[] classfile) { 13 | ClassReader cr; 14 | ClassWriter cw; 15 | try { 16 | // Pass 1: Get local variables of each method 17 | cr = new ClassReader(classfile); 18 | cw = new ClassWriter(cr, 0); // readonly ClassWriter 19 | cr.accept(new LocalVariableTableClassVisitor(cw, classBinName), 0); 20 | 21 | // Pass 2: insert instructions to save/update memory 22 | // before/after each eval() 23 | cr = new ClassReader(cw.toByteArray()); 24 | cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); 25 | cr.accept(new SaveLocalVarValuesClassVisitor(cw, classBinName), 0); 26 | } catch (Exception e) { 27 | throw new RuntimeException(e); 28 | } 29 | 30 | // DEBUGGING 31 | /* try { 32 | jattack.util.IOUtil.saveBytecodeToFile(cw.toByteArray(), classBinName); 33 | } catch (java.io.IOException e) { 34 | e.printStackTrace(); 35 | } */ 36 | 37 | return cw.toByteArray(); 38 | } 39 | 40 | public static void staticAnalyze(String classBinName, byte[] classfile) { 41 | ClassReader cr; 42 | ClassWriter cw; 43 | try { 44 | cr = new ClassReader(classfile); 45 | cw = new ClassWriter(cr, 0); // readonly ClassWriter 46 | cr.accept(new StaticGenClassVisitor(cw, classBinName), 0); 47 | } catch (Exception e) { 48 | throw new RuntimeException(e); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/Agent.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | import java.lang.instrument.Instrumentation; 4 | 5 | public class Agent { 6 | 7 | private static Instrumentation sInst; 8 | 9 | public static Instrumentation getInst() { 10 | return sInst; 11 | } 12 | 13 | public static void premain(String agentArgs, Instrumentation inst) { 14 | // System.out.println("Invoking premain method."); 15 | sInst = inst; 16 | StaticInitCopyTransformer t = new StaticInitCopyTransformer(); 17 | inst.addTransformer(t); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/ClassBytes.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | import jattack.util.TypeUtil; 4 | 5 | import java.util.HashMap; 6 | import java.util.HashSet; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | /** 11 | * Class holding bytes of classes compiled in memory. 12 | */ 13 | public class ClassBytes { 14 | 15 | private final Map bytesByClass = new HashMap<>(); 16 | private final Set packageNames = new HashSet<>(); 17 | 18 | /** 19 | * Returns the bytes of the given class or null if the class does 20 | * not exist in this map. 21 | * @param className the given fully qualified class name. 22 | * @return the bytes of the given class. 23 | */ 24 | public byte[] get(String className) { 25 | return bytesByClass.get(className); 26 | } 27 | 28 | public void put(String className, byte[] bytes) { 29 | bytesByClass.put(className, bytes); 30 | packageNames.add(TypeUtil.getPackageName(className)); 31 | } 32 | 33 | public Map getBytesByClass() { 34 | return bytesByClass; 35 | } 36 | 37 | public Set getPackageNames() { 38 | return packageNames; 39 | } 40 | 41 | public Set getClassNames() { 42 | return bytesByClass.keySet(); 43 | } 44 | 45 | public Set> entrySet() { 46 | return bytesByClass.entrySet(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/ClassFileManager.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | import javax.tools.FileObject; 4 | import javax.tools.ForwardingJavaFileManager; 5 | import javax.tools.JavaFileObject; 6 | import javax.tools.StandardJavaFileManager; 7 | import javax.tools.JavaFileObject.Kind; 8 | import java.io.IOException; 9 | import java.util.Map; 10 | 11 | /** 12 | * File Manager for our in-memory compiler. 13 | *

14 | * https://stackoverflow.com/questions/12173294/compile-code-fully-in-memory-with-javax-tools-javacompiler 15 | * https://javapracs.blogspot.com/2011/06/dynamic-in-memory-compilation-using.html 16 | *

17 | * We stopped using the approach in the link 18 | * https://atamur.blogspot.com/2009/10/using-built-in-javacompiler-with-custom.html 19 | * because it breaks the normal class loading so the class loader 20 | * cannot find jattack.data.Data class. 21 | */ 22 | public class ClassFileManager extends ForwardingJavaFileManager { 23 | 24 | private ClassBytes classBytes; 25 | 26 | /** 27 | * Will initialize the manager with the specified 28 | * standard java file manager 29 | */ 30 | public ClassFileManager(StandardJavaFileManager standardManager) { 31 | super(standardManager); 32 | classBytes = new ClassBytes(); 33 | } 34 | 35 | @Override 36 | public void close() throws IOException { 37 | super.close(); 38 | classBytes = null; 39 | } 40 | 41 | public Map getBytes() { 42 | return classBytes.getBytesByClass(); 43 | } 44 | 45 | public ClassBytes getClassBytes() { 46 | return classBytes; 47 | } 48 | 49 | /** 50 | * Gives the compiler an instance of the JavaClassObject 51 | * so that the compiler can write the byte code into it. 52 | */ 53 | @Override 54 | public JavaFileObject getJavaFileForOutput(Location location, 55 | String className, Kind kind, FileObject sibling) throws IOException { 56 | if (kind == Kind.CLASS) { 57 | return new JavaClassObject(className, classBytes); 58 | } else { 59 | return super.getJavaFileForOutput(location, className, kind, sibling); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/CompilationException.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | /** 4 | * Exception thrown when in-memory compilation fails. 5 | */ 6 | public class CompilationException extends Exception { 7 | 8 | public CompilationException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/InMemoryClassLoader.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | public class InMemoryClassLoader extends ClassLoader { 4 | 5 | private final ClassBytes classBytes; 6 | 7 | public InMemoryClassLoader(ClassBytes bytesByClass, ClassLoader parent) { 8 | super(parent); 9 | this.classBytes = bytesByClass; 10 | } 11 | 12 | @Override 13 | protected Class findClass(String name) throws ClassNotFoundException { 14 | byte[] bytes = classBytes.getBytesByClass().get(name); 15 | if (bytes != null) { 16 | return defineClass(name, bytes, 0, bytes.length); 17 | } 18 | return super.findClass(name); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/JavaClassObject.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.FilterOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.net.URI; 8 | 9 | import javax.tools.SimpleJavaFileObject; 10 | 11 | /** 12 | * Class to represent a compiled .class file in memory. 13 | *

14 | * https://javapracs.blogspot.com/2011/06/dynamic-in-memory-compilation-using.html 15 | */ 16 | public class JavaClassObject extends SimpleJavaFileObject { 17 | 18 | private final ClassBytes classBytes; 19 | private final String className; 20 | 21 | /** 22 | * Registers the compiled class object under URI 23 | * containing the class full name. 24 | */ 25 | public JavaClassObject(String name, ClassBytes classBytes) { 26 | super(URI.create("string:///" + name.replace('.', '/') 27 | + Kind.CLASS.extension), Kind.CLASS); 28 | this.className = name; 29 | this.classBytes = classBytes; 30 | } 31 | 32 | /** 33 | * Will provide the compiler with an output stream that leads 34 | * to our byte array. This way the compiler will write everything 35 | * into the byte array that we will instantiate later 36 | */ 37 | @Override 38 | public OutputStream openOutputStream() { 39 | return new FilterOutputStream(new ByteArrayOutputStream()) { 40 | public void close() throws IOException { 41 | out.close(); 42 | classBytes.put(className, ((ByteArrayOutputStream) out).toByteArray()); 43 | } 44 | }; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/compiler/JavaSourceFromString.java: -------------------------------------------------------------------------------- 1 | package jattack.compiler; 2 | 3 | import javax.tools.SimpleJavaFileObject; 4 | import java.net.URI; 5 | 6 | /** 7 | * Class to represent a source .java file in memory. 8 | */ 9 | public class JavaSourceFromString extends SimpleJavaFileObject { 10 | private final String code; 11 | 12 | public JavaSourceFromString(String classname, String code) { 13 | super(URI.create("string:///" + 14 | classname.replace('.','/') + 15 | Kind.SOURCE.extension), 16 | Kind.SOURCE); 17 | this.code = code; 18 | } 19 | 20 | @Override 21 | public CharSequence getCharContent(boolean ignoreEncodingErrors) { 22 | return code; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/data/Memory.java: -------------------------------------------------------------------------------- 1 | package jattack.data; 2 | 3 | import jattack.util.TypeUtil; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.NoSuchElementException; 8 | import java.util.Objects; 9 | 10 | /** 11 | * Class to track runtime values of symbols (local variables or 12 | * fields). 13 | */ 14 | public class Memory { 15 | 16 | public static final class Null { 17 | // Singleton 18 | // forbid from being constructed from outside 19 | private Null() {} 20 | 21 | @Override 22 | public boolean equals(Object other) { 23 | return other instanceof Null; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | return Objects.hashCode(null); 29 | } 30 | } 31 | 32 | public static final Null NULL = new Null(); 33 | 34 | private Map table; 35 | 36 | public Memory() { 37 | table = new HashMap<>(); 38 | } 39 | 40 | public Map getTable() { 41 | return table; 42 | } 43 | 44 | public boolean containsKey(String name) { 45 | return table.containsKey(name); 46 | } 47 | 48 | public void put(String name, String desc, Object val) { 49 | if (!TypeUtil.isTypeDescSupported(desc)) { 50 | return; 51 | } 52 | if (TypeUtil.isDescPrimitive(desc)) { 53 | // as we allow only boxed types inside 54 | desc = TypeUtil.primitiveDescToBoxedDesc(desc); 55 | } 56 | table.put(name, new RuntimeSymbol(name, desc, val)); // No! We do not want a deep copy 57 | } 58 | 59 | public void updateValue(String name, Object val) { 60 | if (!table.containsKey(name)) { 61 | throw new NoSuchElementException( 62 | "Symbol " + name + " does not exist in memory!"); 63 | } 64 | table.get(name).setValue(val); 65 | } 66 | 67 | /** 68 | * Returns the runtiem value of the given symbol name. 69 | * @param name the given symbol name 70 | * @return the correspoinding runtime value 71 | * @throws NoSuchElementException if the given symbol does not 72 | * exist in memory 73 | */ 74 | public Object getValue(String name) { 75 | if (!table.containsKey(name)) { 76 | throw new NoSuchElementException( 77 | "Symbol " + name + " does not exist in memory!"); 78 | } 79 | return table.get(name).getValue(); 80 | } 81 | 82 | public void reset() { 83 | table.clear(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/data/RuntimeSymbol.java: -------------------------------------------------------------------------------- 1 | package jattack.data; 2 | 3 | import java.util.Objects; 4 | 5 | public final class RuntimeSymbol { 6 | private final String name; 7 | private final String desc; 8 | private Object value; 9 | 10 | RuntimeSymbol(String name, String desc, Object value) { 11 | this.name = name; 12 | this.desc = desc; 13 | this.value = value; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public String getDesc() { 21 | return desc; 22 | } 23 | 24 | public Object getValue() { 25 | return value; 26 | } 27 | 28 | public void setValue(Object value) { 29 | this.value = value; 30 | } 31 | 32 | @Override 33 | public boolean equals(Object o) { 34 | if (this == o) return true; 35 | if (o == null || getClass() != o.getClass()) return false; 36 | RuntimeSymbol symbol = (RuntimeSymbol) o; 37 | return Objects.equals(name, symbol.name); 38 | } 39 | 40 | @Override 41 | public int hashCode() { 42 | return Objects.hash(name); 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "RuntimeSymbol{" + 48 | "name='" + name + '\'' + 49 | ", desc='" + desc + '\'' + 50 | ", value=" + value + 51 | '}'; 52 | } 53 | } -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/driver/SearchStrategy.java: -------------------------------------------------------------------------------- 1 | package jattack.driver; 2 | 3 | /** 4 | * Defines the search strategies. 5 | */ 6 | public enum SearchStrategy { 7 | 8 | /** 9 | * Systematic explore the whole search space across holes. 10 | */ 11 | SYSTEMATIC, 12 | 13 | /** 14 | * Randomly explore each hole independently. 15 | */ 16 | RANDOM, 17 | 18 | /** 19 | * Systematically explore each hole independently. 20 | */ 21 | SMART 22 | } 23 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/exception/InvokedFromNotDriverException.java: -------------------------------------------------------------------------------- 1 | package jattack.exception; 2 | 3 | public class InvokedFromNotDriverException extends RuntimeException { 4 | public InvokedFromNotDriverException() { 5 | super("Invoked from NOT the Driver!"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/log/Log.java: -------------------------------------------------------------------------------- 1 | package jattack.log; 2 | 3 | /** 4 | * Utility class for logging. 5 | */ 6 | public class Log { 7 | 8 | public enum Level { 9 | DEBUG("DEBUG", 2), 10 | INFO("INFO", 1), 11 | ERROR("ERROR", 0); 12 | 13 | private final String name; 14 | private final int order; 15 | 16 | Level(String name, int order) { 17 | this.name = name; 18 | this.order = order; 19 | } 20 | 21 | public int getOrder() { 22 | return order; 23 | } 24 | } 25 | 26 | private static final String MSG_PREFIX = "JAttack:"; 27 | 28 | private static Level level = Level.ERROR; 29 | 30 | public static void setLevel(String newLevel) { 31 | switch (newLevel) { 32 | case "debug": 33 | setLevel(Level.DEBUG); 34 | break; 35 | case "info": 36 | setLevel(Level.INFO); 37 | break; 38 | case "error": 39 | setLevel(Level.ERROR); 40 | break; 41 | default: 42 | throw new RuntimeException("Unrecognized logging level: " + newLevel + "!"); 43 | } 44 | } 45 | 46 | public static void setLevel(Level newLevel) { 47 | level = newLevel; 48 | } 49 | 50 | public static Level getLevel() { 51 | return level; 52 | } 53 | 54 | public static void debug(Object msg) { 55 | log(msg, Level.DEBUG); 56 | } 57 | 58 | public static void info(Object msg) { 59 | log(msg, Level.INFO); 60 | } 61 | 62 | public static void error(Object msg) { 63 | log(msg, Level.ERROR); 64 | } 65 | 66 | // We want to use this method in tests so I made it 67 | // package-private. 68 | static String getFullLogMessage(Object msg, Level logLevel) { 69 | return MSG_PREFIX + logLevel.name + ": " + msg + System.lineSeparator(); 70 | } 71 | 72 | private static void log(Object msg, Level logLevel) { 73 | if (level.order < logLevel.order) { 74 | return; 75 | } 76 | System.out.print(getFullLogMessage(msg, logLevel)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/HoleExtractor.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer; 2 | 3 | import com.github.javaparser.StaticJavaParser; 4 | import com.github.javaparser.ast.CompilationUnit; 5 | import com.github.javaparser.ast.ImportDeclaration; 6 | import com.github.javaparser.ast.expr.Expression; 7 | import com.github.javaparser.ast.expr.MethodCallExpr; 8 | import com.github.javaparser.ast.stmt.BlockStmt; 9 | import com.github.javaparser.ast.stmt.ExpressionStmt; 10 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 11 | import jattack.Constants; 12 | import jattack.util.JPUtil; 13 | 14 | public class HoleExtractor extends Transformer { 15 | 16 | public static final String CLASS_NAME = "ASTCreator"; 17 | 18 | public static final String METHOD_NAME = "createAST"; 19 | 20 | public HoleExtractor(CompilationUnit origCu) { 21 | super(origCu); 22 | initCu(); 23 | } 24 | 25 | @Override 26 | public void transform() { 27 | BlockStmt block = new BlockStmt(); 28 | origCu.accept(new VoidVisitorAdapter() { 29 | @Override 30 | public void visit(ExpressionStmt stmt, Void arg) { 31 | if (JPUtil.isHole(stmt)) { 32 | int id = JPUtil.getHoleId(stmt); 33 | Expression body = JPUtil.getHoleBody(stmt); 34 | addHoleBodyToBlock(body, id, block); 35 | } 36 | super.visit(stmt, arg); 37 | } 38 | 39 | @Override 40 | public void visit(MethodCallExpr expr, Void arg) { 41 | if (JPUtil.isHole(expr)) { 42 | int id = JPUtil.getHoleId(expr); 43 | Expression body = JPUtil.getHoleBody(expr); 44 | addHoleBodyToBlock(body, id, block); 45 | } 46 | super.visit(expr, arg); 47 | } 48 | }, null); 49 | cu.getClassByName(CLASS_NAME).get() 50 | .getMethodsByName(METHOD_NAME).get(0) 51 | .setBody(block); 52 | } 53 | 54 | private void addHoleBodyToBlock(Expression body, int id, BlockStmt block) { 55 | String stmt = String.format( 56 | "%s.%s().put(%d, %s);", 57 | Constants.DATA_CLZ, 58 | Constants.GET_AST_CACHE_METHOD, 59 | id, 60 | body); 61 | block.addStatement(stmt); 62 | } 63 | 64 | private void initCu() { 65 | cu = StaticJavaParser.parse(String.format( 66 | "public class %s { public static void %s(){} }", 67 | CLASS_NAME, METHOD_NAME)); 68 | // keep all original imports 69 | for (ImportDeclaration imp : origCu.getImports()) { 70 | cu.addImport(imp.clone()); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/OnDemandTransformer.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer; 2 | 3 | import com.github.javaparser.ast.CompilationUnit; 4 | import jattack.transformer.visitor.DeadCodeEliminator; 5 | import jattack.transformer.visitor.HoleFiller; 6 | 7 | /** 8 | * Transform templates in hot filling. 9 | */ 10 | public class OnDemandTransformer extends Transformer { 11 | 12 | /** 13 | * Flag if we perform dead code removal for all the always true or 14 | * false condition holes. 15 | */ 16 | private final boolean deadCodeRemoval; 17 | 18 | /** 19 | * Flag if we fill holes. 20 | */ 21 | private final boolean hotFilling; 22 | 23 | /** 24 | * Constructor. 25 | */ 26 | public OnDemandTransformer(CompilationUnit origCu, boolean hotFilling, boolean deadCodeRemoval) { 27 | super(origCu); 28 | this.hotFilling = hotFilling; 29 | this.deadCodeRemoval = deadCodeRemoval; 30 | } 31 | 32 | /** 33 | * Transforms part of this template. This is incremental 34 | * transformation, which means we starts with the previously 35 | * transformed {@link Transformer#cu}. 36 | */ 37 | @Override 38 | public void transform() { 39 | if (deadCodeRemoval) { 40 | // Remove dead code resulting from always true or false 41 | // condition holes. 42 | cu.accept(new DeadCodeEliminator(), null); 43 | } 44 | 45 | if (hotFilling) { 46 | cu.accept(new HoleFiller(), null); 47 | } 48 | } 49 | 50 | /** 51 | * Resets cu to a clone of origCu. This should be invoked before 52 | * a new run of the template. 53 | */ 54 | public void resetCu() { 55 | cu = origCu.clone(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/Transformer.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer; 2 | 3 | import com.github.javaparser.ast.CompilationUnit; 4 | 5 | /** 6 | * Abstract class for all transformers. 7 | */ 8 | public abstract class Transformer { 9 | 10 | protected final CompilationUnit origCu; 11 | protected CompilationUnit cu; 12 | 13 | public Transformer(CompilationUnit origCu) { 14 | this.origCu = origCu; 15 | this.cu = null; 16 | } 17 | 18 | public abstract void transform(); 19 | 20 | public String getSrcCode() { 21 | return cu.toString(); 22 | } 23 | 24 | public String transformAndGetSrcCode() { 25 | transform(); 26 | return getSrcCode(); 27 | } 28 | 29 | public CompilationUnit getCu() { 30 | return cu; 31 | } 32 | 33 | public CompilationUnit getOrigCu() { 34 | return origCu; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/visitor/HideGenericTypeArgumentPrinterVisitor.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer.visitor; 2 | 3 | import com.github.javaparser.ast.type.ClassOrInterfaceType; 4 | import com.github.javaparser.printer.DefaultPrettyPrinterVisitor; 5 | import com.github.javaparser.printer.configuration.PrinterConfiguration; 6 | 7 | public class HideGenericTypeArgumentPrinterVisitor extends DefaultPrettyPrinterVisitor { 8 | 9 | public HideGenericTypeArgumentPrinterVisitor(PrinterConfiguration conf) { 10 | super(conf); 11 | } 12 | 13 | @Override 14 | public void visit(ClassOrInterfaceType n, Void arg) { 15 | if (n.getScope().isPresent()) { 16 | n.getScope().get().accept(this, arg); 17 | printer.print("."); 18 | } 19 | printAnnotations(n.getAnnotations(), false, arg); 20 | 21 | n.getName().accept(this, arg); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/visitor/NeverReachableHoleMarker.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer.visitor; 2 | 3 | import com.github.javaparser.ast.expr.MethodCallExpr; 4 | import com.github.javaparser.ast.stmt.ExpressionStmt; 5 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter; 6 | import jattack.data.Data; 7 | import jattack.util.JPUtil; 8 | 9 | /** 10 | * Visitor to mark the holes that will never be reached. 11 | */ 12 | public class NeverReachableHoleMarker extends VoidVisitorAdapter { 13 | 14 | @Override 15 | public void visit(ExpressionStmt stmt, Void arg) { 16 | if (JPUtil.isHole(stmt)) { 17 | Data.addToNeverReachableHoles(JPUtil.getHoleId(stmt)); 18 | } else { 19 | super.visit(stmt, arg); 20 | } 21 | } 22 | 23 | @Override 24 | public void visit(MethodCallExpr expr, Void arg) { 25 | if (JPUtil.isHole(expr)) { 26 | Data.addToNeverReachableHoles(JPUtil.getHoleId(expr)); 27 | } else { 28 | super.visit(expr, arg); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/visitor/RemoveVisitor.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer.visitor; 2 | 3 | import com.github.javaparser.ast.expr.AnnotationExpr; 4 | import com.github.javaparser.ast.expr.MarkerAnnotationExpr; 5 | import com.github.javaparser.ast.expr.NormalAnnotationExpr; 6 | import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; 7 | import com.github.javaparser.ast.visitor.ModifierVisitor; 8 | import com.github.javaparser.ast.visitor.Visitable; 9 | import jattack.Constants; 10 | 11 | /** 12 | * Remove those apis we do not want to appear in generated programs, 13 | * such as @Entry, @Argument and so on. 14 | */ 15 | public class RemoveVisitor extends ModifierVisitor { 16 | 17 | /** 18 | * Remove any @Entry annotation. 19 | */ 20 | @Override 21 | public Visitable visit(MarkerAnnotationExpr annotation, Void arg) { 22 | if (isEntryAnnotation(annotation)) { 23 | return null; 24 | } 25 | return super.visit(annotation, arg); 26 | } 27 | 28 | /** 29 | * Remove any @Entry()/@Argument(value=[n]) annotation. 30 | */ 31 | @Override 32 | public Visitable visit(NormalAnnotationExpr annotation, Void arg) { 33 | if (isEntryAnnotation(annotation) || isArgumentAnnotation(annotation)) { 34 | return null; 35 | } 36 | return super.visit(annotation, arg); 37 | } 38 | 39 | /** 40 | * Remove any @Argument([n]) annotation. 41 | */ 42 | @Override 43 | public Visitable visit(SingleMemberAnnotationExpr annotation, Void arg) { 44 | if (isArgumentAnnotation(annotation)) { 45 | return null; 46 | } 47 | return super.visit(annotation, arg); 48 | } 49 | 50 | /** 51 | * Returns ture if the given annotation is @Entry. 52 | */ 53 | public static boolean isEntryAnnotation(AnnotationExpr annotation) { 54 | String name = annotation.getNameAsString(); 55 | return name.equals(Constants.ENTRY_ANNOT) 56 | || name.equals(Constants.ENTRY_ANNOT_FULL_NAME); 57 | } 58 | 59 | /** 60 | * Returns ture if the given annotation is @Argument. 61 | */ 62 | public static boolean isArgumentAnnotation(AnnotationExpr annotation) { 63 | String name = annotation.getNameAsString(); 64 | return name.equals(Constants.ARGUMENT_ANNOT) 65 | || name.equals(Constants.ARGUMENT_ANNOT_FULL_NAME); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/transformer/visitor/RenameVisitor.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer.visitor; 2 | 3 | import com.github.javaparser.ast.expr.Name; 4 | import com.github.javaparser.ast.expr.SimpleName; 5 | import com.github.javaparser.ast.visitor.ModifierVisitor; 6 | import com.github.javaparser.ast.visitor.Visitable; 7 | 8 | /** 9 | * Rename every usage of the template class. 10 | */ 11 | public class RenameVisitor extends ModifierVisitor { 12 | 13 | private final String inClzName; 14 | private final String outClzName; 15 | 16 | public RenameVisitor(String inClzName, String outClzName) { 17 | this.inClzName = inClzName; 18 | this.outClzName = outClzName; 19 | } 20 | 21 | @Override 22 | public Visitable visit(SimpleName name, Void arg) { 23 | if (name.getIdentifier().equals(inClzName)) { 24 | name.setIdentifier(outClzName); 25 | } 26 | return super.visit(name, arg); 27 | } 28 | 29 | @Override 30 | public Visitable visit(Name name, Void arg) { 31 | if (name.getIdentifier().equals(inClzName)) { 32 | name.setIdentifier(outClzName); 33 | } 34 | return super.visit(name, arg); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/util/IOUtil.java: -------------------------------------------------------------------------------- 1 | package jattack.util; 2 | 3 | import java.io.IOException; 4 | import java.nio.charset.StandardCharsets; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.nio.file.Paths; 8 | import java.nio.file.StandardOpenOption; 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | /** 14 | * Utility class for IO. 15 | */ 16 | public class IOUtil { 17 | 18 | /** 19 | * Write the given code to the given file under the given 20 | * directory and sub-directories, always overwriting the file. 21 | */ 22 | public static void writeToFile( 23 | String dir, String file, String code, String... subDirs) { 24 | writeToFile(dir, file, code, false, subDirs); 25 | } 26 | 27 | /** 28 | * Write the given code to the given file under the given 29 | * directory and sub-directories. 30 | */ 31 | public static void writeToFile( 32 | String dir, String file, String code, boolean append, String... subDirs) { 33 | List dirs = new ArrayList<>(); 34 | dirs.addAll(Arrays.asList(subDirs)); 35 | dirs.add(file); 36 | try { 37 | writeToFile(Paths.get(dir, dirs.toArray(String[]::new)), 38 | code.getBytes(StandardCharsets.UTF_8), 39 | append); 40 | } catch (IOException e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | 45 | public static void writeToFile(Path path, byte[] bytes, boolean append) 46 | throws IOException{ 47 | Path dir = path.getParent(); 48 | if (Files.notExists(dir)) { 49 | Files.createDirectories(dir); 50 | } 51 | if (append) { 52 | Files.write(path, bytes, StandardOpenOption.APPEND); 53 | } else { 54 | Files.write(path, bytes); 55 | } 56 | } 57 | 58 | public static void saveBytecodeToFile(byte[] classfileBuffer, String name) 59 | throws IOException { 60 | Files.write(Paths.get(name + ".class"), classfileBuffer); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/util/JPUtil.java: -------------------------------------------------------------------------------- 1 | package jattack.util; 2 | 3 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 4 | import com.github.javaparser.ast.body.MethodDeclaration; 5 | import com.github.javaparser.ast.expr.Expression; 6 | import com.github.javaparser.ast.expr.MethodCallExpr; 7 | import com.github.javaparser.ast.stmt.ExpressionStmt; 8 | import jattack.Constants; 9 | 10 | import java.util.Optional; 11 | 12 | /** 13 | * Utility class for JavaParser. 14 | */ 15 | public class JPUtil { 16 | 17 | public static Expression getHoleBody(ExpressionStmt stmt) { 18 | return getHoleBody(stmt.getExpression().asMethodCallExpr()); 19 | } 20 | 21 | public static Expression getHoleBody(MethodCallExpr expr) { 22 | if (expr.getScope().isEmpty()) { 23 | throw new RuntimeException("This is not valid hole: " + expr); 24 | } 25 | return expr.getScope().get(); 26 | } 27 | 28 | public static int getHoleId(ExpressionStmt stmt) { 29 | return getHoleId(stmt.getExpression().asMethodCallExpr()); 30 | } 31 | 32 | public static int getHoleId(MethodCallExpr expr) { 33 | if (expr.getArguments().size() != 1 34 | || !expr.getArgument(0).isIntegerLiteralExpr()) { 35 | throw new RuntimeException("There is no identifier found in this hole: " + expr); 36 | } 37 | return expr.getArgument(0).asIntegerLiteralExpr().asNumber().intValue(); 38 | } 39 | 40 | 41 | /** 42 | * Returns true if the given expression statement wraps 43 | * a method call expression matching the format 44 | * {@code [some api].eval(...)}. 45 | */ 46 | public static boolean isHole(ExpressionStmt stmt) { 47 | return isHole(stmt.getExpression()); 48 | } 49 | 50 | /** 51 | * Returns true if the given expression is a hole. 52 | */ 53 | public static boolean isHole(Expression expr) { 54 | if (!expr.isMethodCallExpr()) { 55 | return false; 56 | } 57 | return isHole(expr.asMethodCallExpr()); 58 | } 59 | 60 | /** 61 | * Returns true if the given method call expression matches the 62 | * format {@code [some api].eval(...)}. 63 | */ 64 | public static boolean isHole(MethodCallExpr expr) { 65 | // TODO: this is still not 100% accurate but sufficient for 66 | // now. Revisit it if we come across any issues. 67 | // name is "eval" 68 | return expr.getNameAsString().equals(Constants.EVAL_METH_NAME) 69 | // scope ends with one of our apis 70 | && expr.getScope().isPresent() 71 | && expr.getScope().get().isMethodCallExpr() 72 | && Constants.API_NAMES.contains( 73 | expr.getScope().get().asMethodCallExpr().getNameAsString()); 74 | } 75 | 76 | /** 77 | * Returns true if the given method declaration is a main method. 78 | */ 79 | public static boolean isMainMethod(MethodDeclaration methodDeclaration) { 80 | String str = methodDeclaration.getDeclarationAsString(true, false, false); 81 | return str.equals("public static void main(String[])") 82 | || str.equals("public static void main(String...)"); 83 | } 84 | 85 | /** 86 | * Get the main method declaration from the given class. 87 | */ 88 | public static Optional getMain(ClassOrInterfaceDeclaration clz) { 89 | return clz.findFirst(MethodDeclaration.class, JPUtil::isMainMethod); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /tool/api/src/main/java/jattack/util/Z3Util.java: -------------------------------------------------------------------------------- 1 | package jattack.util; 2 | 3 | import com.microsoft.z3.BoolExpr; 4 | import com.microsoft.z3.Context; 5 | import com.microsoft.z3.Solver; 6 | import com.microsoft.z3.Status; 7 | 8 | /** 9 | * Utility class for Z3 solver. 10 | */ 11 | public class Z3Util { 12 | 13 | public enum SatSatus { 14 | VALID, 15 | UNSATISFIABLE, 16 | CONTINGENT, 17 | UNKNOWN 18 | } 19 | 20 | @SuppressWarnings("unchecked") 21 | public static SatSatus check(BoolExpr f, Context ctx) { 22 | Solver s = ctx.mkSolver("QF_BV"); 23 | s.add(f); 24 | Status res = s.check(); 25 | if (res == Status.UNKNOWN) { 26 | return SatSatus.UNKNOWN; 27 | } 28 | if (res == Status.UNSATISFIABLE) { 29 | return SatSatus.UNSATISFIABLE; 30 | } 31 | // Satisfiable 32 | s.reset(); 33 | s.add(ctx.mkNot(f)); 34 | res = s.check(); 35 | if (res == Status.UNKNOWN) { 36 | return SatSatus.UNKNOWN; 37 | } 38 | if (res == Status.UNSATISFIABLE) { 39 | return SatSatus.VALID; 40 | } 41 | return SatSatus.CONTINGENT; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/ast/Z3Test.java: -------------------------------------------------------------------------------- 1 | package jattack.ast; 2 | 3 | import com.microsoft.z3.BoolExpr; 4 | import com.microsoft.z3.Expr; 5 | import org.junit.Assert; 6 | import org.junit.BeforeClass; 7 | import org.junit.Test; 8 | import jattack.ast.exp.Exp; 9 | import jattack.ast.visitor.Z3ExprBuilder; 10 | import jattack.driver.Driver; 11 | import jattack.util.Z3Util; 12 | 13 | import static jattack.Boom.*; 14 | 15 | /** 16 | * Test Z3 solver. 17 | */ 18 | public class Z3Test { 19 | @BeforeClass 20 | public static void configurate() { 21 | Driver.isDriven = true; 22 | } 23 | 24 | @Test 25 | public void testContingent() { 26 | Exp exp = relation(intId("x"), intId("y"), GT); 27 | exp.stepRand(); 28 | Assert.assertEquals(Z3Util.SatSatus.CONTINGENT, checkSat(exp)); 29 | } 30 | 31 | @Test 32 | public void testValid() { 33 | Exp exp = relation(intId("z"), intId("z"), GE); 34 | exp.stepRand(); 35 | Assert.assertEquals(Z3Util.SatSatus.VALID, checkSat(exp)); 36 | } 37 | 38 | @Test 39 | public void testUnsat() { 40 | Exp exp = relation(intId("x"), intId("x"), NE); 41 | exp.stepRand(); 42 | Assert.assertEquals(Z3Util.SatSatus.UNSATISFIABLE, checkSat(exp)); 43 | } 44 | 45 | @Test 46 | public void testArray() { 47 | Exp exp = relation(asIntArrAccess("arr[0]"), asIntArrAccess("arr[0]"), LT); 48 | exp.stepRand(); 49 | Assert.assertEquals(Z3Util.SatSatus.UNSATISFIABLE, checkSat(exp)); 50 | } 51 | 52 | @Test 53 | public void testUnsatLogicExpWithBool() { 54 | Exp exp = logic(boolId("b"), asBool(false), AND); 55 | exp.stepRand(); 56 | Assert.assertEquals(Z3Util.SatSatus.UNSATISFIABLE, checkSat(exp)); 57 | } 58 | 59 | @Test 60 | public void testValidLogicExpWithBool() { 61 | Exp exp = logic(boolId("b"), asBool(true), OR); 62 | exp.stepRand(); 63 | Assert.assertEquals(Z3Util.SatSatus.VALID, checkSat(exp)); 64 | } 65 | 66 | @Test 67 | public void testContingentLogicExpWithBool() { 68 | Exp exp = logic(boolId("b"), asBool(true), AND); 69 | exp.stepRand(); 70 | Assert.assertEquals(Z3Util.SatSatus.CONTINGENT, checkSat(exp)); 71 | } 72 | 73 | @Test 74 | public void testExpWithIntVal() { 75 | Exp exp = relation(asInt(10), asInt(10), GT); 76 | exp.stepRand(); 77 | Assert.assertEquals(Z3Util.SatSatus.UNSATISFIABLE, checkSat(exp)); 78 | } 79 | 80 | private static Z3Util.SatSatus checkSat(Exp exp) { 81 | Z3ExprBuilder v = new Z3ExprBuilder(); 82 | exp.accept(v); 83 | Expr z3expr = v.getZ3Expr(); 84 | return z3expr == null ? 85 | null : 86 | Z3Util.check((BoolExpr) z3expr, v.getContext()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArgumentAnnotation.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | import jattack.exception.InvokedFromNotDriverException; 6 | 7 | import static jattack.Boom.*; 8 | 9 | public class SkTestArgumentAnnotation { 10 | 11 | @Entry 12 | static void m(int x, String s, double... ys) { 13 | if (x != 1) { 14 | throw new InvokedFromNotDriverException(); 15 | } 16 | int y = intId().eval(); 17 | String z = refId(String.class).eval(); 18 | double l = doubleArrAccessExp().eval(); 19 | if (!s.equals("hello")) { 20 | throw new InvokedFromNotDriverException(); 21 | } 22 | } 23 | 24 | @Argument(1) 25 | static int arg1() { 26 | return 1; 27 | } 28 | 29 | @Argument(2) 30 | static String argSecond() { 31 | return "hello"; 32 | } 33 | 34 | @Argument(3) 35 | static double[] arg3rd() { 36 | return new double[]{1.1, 2.2, 3.3}; 37 | } 38 | } -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArgumentWithGenericTypeUsingArgumentAnnotation.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | 6 | import java.util.List; 7 | 8 | import static jattack.Boom.*; 9 | 10 | public class SkTestArgumentWithGenericTypeUsingArgumentAnnotation { 11 | 12 | @Entry 13 | public static void m(List> s) { 14 | int x = intVal().eval(); 15 | } 16 | 17 | @Argument(1) 18 | public static List> arg1() { 19 | return List.of(List.of("hello")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArgumentWithGenericTypeUsingArgumentsAnnotation.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Arguments; 4 | import jattack.annotation.Entry; 5 | 6 | import java.util.List; 7 | 8 | import static jattack.Boom.*; 9 | 10 | public class SkTestArgumentWithGenericTypeUsingArgumentsAnnotation { 11 | 12 | @Entry 13 | public static void m(List> s) { 14 | int x = intVal().eval(); 15 | } 16 | 17 | @Arguments() 18 | public static Object[] args() { 19 | return new Object[]{ List.of(List.of("hello")) }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArgumentsAnnotation.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Arguments; 4 | import jattack.annotation.Entry; 5 | import jattack.exception.InvokedFromNotDriverException; 6 | 7 | import static jattack.Boom.*; 8 | 9 | public class SkTestArgumentsAnnotation { 10 | 11 | @Entry 12 | static void m(int x, String s, double... ys) { 13 | if (x != 1) { 14 | throw new InvokedFromNotDriverException(); 15 | } 16 | int y = intId().eval(); 17 | String z = refId(String.class).eval(); 18 | double l = doubleArrAccessExp().eval(); 19 | if (!s.equals("hello")) { 20 | throw new InvokedFromNotDriverException(); 21 | } 22 | } 23 | 24 | @Arguments 25 | static Object[] args() { 26 | return new Object[] {1, "hello", new double[]{1.1, 2.2, 3.3}}; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArithmeticWithDouble.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import static jattack.Boom.*; 5 | 6 | public class SkTestArithmeticWithDouble { 7 | 8 | private static int s1 = 0; 9 | 10 | @Entry 11 | public static double m() { 12 | double a = arithmetic(doubleVal(), doubleVal(), ADD).eval(); 13 | return a + 1.0; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArrayIndexOutOfBoundExceptionWhenGetting.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import static jattack.Boom.*; 5 | 6 | public class SkTestArrayIndexOutOfBoundExceptionWhenGetting { 7 | 8 | @Entry 9 | static void m() { 10 | int[] arr = { 1, 2 }; 11 | int x = intArrAccessExp("arr", intVal(3, 10)).eval(); 12 | int y = intVal().eval(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArrayIndexOutOfBoundExceptionWhenSetting.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import static jattack.Boom.*; 5 | 6 | public class SkTestArrayIndexOutOfBoundExceptionWhenSetting { 7 | 8 | @Entry 9 | static void m() { 10 | int[] arr = { 1, 2 }; 11 | assignStmt(intArrAccessExp("arr", intVal(3, 10)), intVal()).eval(); 12 | int y = intVal().eval(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestArrayNullPointerException.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestArrayNullPointerException { 8 | 9 | @Entry 10 | static void m() { 11 | int[] a = null; 12 | int l = intArrAccessExp(refId(int[].class), intVal()).eval(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestAssignmentApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestAssignmentApis { 8 | 9 | private static int s = 0; 10 | 11 | @Entry 12 | public static int m() { 13 | int x = 0; 14 | int y = 0; 15 | assignStmt(intId("x"), preIncIntExp("y")).eval(); 16 | assignStmt(intId("y"), preIncIntExp("x")).eval(); 17 | if (relation(intId("x"), intId("x"), GT).eval()) { 18 | // optSolverAid should work in this case to hide this hole. 19 | assignStmt(intId("x"), preIncIntExp("y")).eval(); 20 | } 21 | if (x == 2 && y == 2 && s == 0) { 22 | // allow only the first time reaching to prevent hotFilling 23 | // from getting into here from the second time 24 | return intVal().eval(); 25 | } 26 | s++; 27 | return s; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestBlockStmtApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestBlockStmtApis { 8 | 9 | private static int s = 0; 10 | 11 | @Entry 12 | public static void m() { 13 | testEmptyBlock(); 14 | testSimpleBlock(); 15 | testBlockAsBodyOfWhile(); 16 | testSolverAidWorksForBlock(); 17 | s++; 18 | } 19 | 20 | private static void testEmptyBlock() { 21 | block().eval(); 22 | } 23 | 24 | private static void testSimpleBlock() { 25 | int x = 0; 26 | int y = 0; 27 | block(preIncIntStmt("x"), preIncIntStmt("y")).eval(); 28 | if (x == y && s == 0) { 29 | y = x + intVal().eval(); 30 | } 31 | } 32 | 33 | private static void testBlockAsBodyOfWhile() { 34 | int x = 1; 35 | int y = 2; 36 | whileStmt(relation(intId("x"), intId("y"), LT), 37 | block( 38 | ifStmt(relation(arithmetic("x", 1, ADD), "y", GE), 39 | block(preIncIntStmt("x"))), 40 | assignStmt(intId("s"), intId()))).eval(); 41 | if (x == y && s == 0) { 42 | y = x + intVal().eval(); 43 | } 44 | } 45 | 46 | private static void testSolverAidWorksForBlock() { 47 | int x = 1; 48 | if (relation(intId("x"), intId("x"), GT).eval()) { 49 | // optSolverAid should work in this case to hide this hole. 50 | block(preIncIntStmt("x")).eval(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestBoolIdApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestBoolIdApis { 9 | 10 | private static boolean bs = false; 11 | 12 | @Entry 13 | public static int m(boolean b, int i) { 14 | int x = intId().eval(); 15 | if (logic(boolId(), boolId("bs")).eval()) { 16 | x += 1; 17 | } 18 | return x; 19 | } 20 | 21 | @Argument(1) 22 | public static boolean arg1() { 23 | return true; 24 | } 25 | 26 | @Argument(2) 27 | public static int arg2() { 28 | return 99; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestClassCastException.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | 5 | import jattack.annotation.Entry; 6 | 7 | public class SkTestClassCastException { 8 | 9 | @Entry 10 | static void m() { 11 | Object o = intVal().eval(); 12 | // OK 13 | int i = cast(Integer.class, refId(Object.class, "o")).eval(); 14 | // ClassCastException 15 | String s = cast(String.class, refId(Object.class, "o")).eval(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestDeadForLoopElimination.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestDeadForLoopElimination { 8 | 9 | static int s = 0; 10 | 11 | @Entry 12 | public static int m() { 13 | int i = 0; 14 | /* If we print intermediate hot filling source this loop is 15 | supposed to be eliminated. */ 16 | for (; relation(intId("s"), intId("s"), LT).eval() ;) { 17 | s += intVal().eval(); 18 | } 19 | s += intVal().eval(); 20 | return s; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestDividedByZeroException.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import static jattack.Boom.*; 5 | 6 | public class SkTestDividedByZeroException { 7 | 8 | @Entry 9 | static void m() { 10 | int x = arithmetic(intVal(), asInt(0), DIV, MOD).eval(); 11 | int y = intVal().eval(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestDoubleIdApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestDoubleIdApis { 9 | 10 | private static double s1 = 0.0; 11 | 12 | @Entry 13 | public static double m() { 14 | double x = 1.0; 15 | double y = 5.0; 16 | if (relation(doubleId("x"), doubleId("x"), LT).eval()) { 17 | throw new InvokedFromNotDriverException(); 18 | } else { 19 | s1 += doubleId().eval(); 20 | } 21 | return s1 + x + y; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestDoubleValApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestDoubleValApis { 9 | 10 | private static double s1 = 0; 11 | 12 | @Entry 13 | public static void m() { 14 | if (relation(doubleVal(-5.0, -3.0), 15 | doubleVal(3.0, 5.0), GT).eval()) { 16 | s1 += doubleVal().eval(); 17 | throw new InvokedFromNotDriverException(); 18 | } else { 19 | s1 += 1; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestDynamicUseCase.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestDynamicUseCase { 8 | 9 | static int decide(int x) { 10 | if (x < 0) { 11 | return 100; 12 | } else { 13 | return -100; 14 | } 15 | } 16 | 17 | @Entry 18 | static int m(int x) { 19 | return alt(decide(x), intVal()).eval(); 20 | } 21 | 22 | @Argument(1) 23 | static int arg1() { 24 | return -1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestEscapingSpecialChars.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.*; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestEscapingSpecialChars { 8 | 9 | @Entry 10 | static void m() { 11 | char c1 = asChar('\t').eval(); 12 | char c2 = asChar('\b').eval(); 13 | char c3 = asChar('\n').eval(); 14 | char c4 = asChar('\r').eval(); 15 | char c5 = asChar('\f').eval(); 16 | char c6 = asChar('\'').eval(); 17 | char c7 = asChar('\"').eval(); 18 | char c8 = asChar('\\').eval(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestExceptionCaughtInTemplate.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestExceptionCaughtInTemplate { 8 | 9 | @Entry 10 | static void m() { 11 | try { 12 | int x = arithmetic(asInt(1), intVal(-1, 2), DIV).eval(); 13 | } catch (ArithmeticException e) { 14 | // this exception is caught in the template, so it should 15 | // not be rethrown in an InvocationTargetException 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestExceptionInArgumentMethods.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | // Expect only one generated program but neither jattack nor generated 9 | // program should not crash when run as we already handled any 10 | // exception from application. 11 | public class SkTestExceptionInArgumentMethods { 12 | 13 | @Entry 14 | int m() { 15 | return intVal().eval(); 16 | } 17 | 18 | @Argument(0) 19 | static SkTestExceptionInArgumentMethods makeReceiver() { 20 | if (asBool(true).eval()) { 21 | throw new RuntimeException("Some error of application."); 22 | } 23 | return new SkTestExceptionInArgumentMethods(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestExceptionInArgumentsMethod.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Arguments; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | // Expect only one generated program but neither jattack nor generated 9 | // program should not crash when run as we already handled any 10 | // exception from application. 11 | public class SkTestExceptionInArgumentsMethod { 12 | 13 | @Entry 14 | int m() { 15 | return intVal().eval(); 16 | } 17 | 18 | @Arguments 19 | static Object[] makeReceiver() { 20 | if (asBool(true).eval()) { 21 | throw new RuntimeException("Some error of application."); 22 | } 23 | return new Object[]{ new SkTestExceptionInArgumentsMethod() }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestExceptionInEvaluatingMultiDimArrays.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestExceptionInEvaluatingMultiDimArrays { 9 | 10 | @Entry 11 | static void m() { 12 | int y = intVal(-3, 0).eval(); 13 | 14 | try { 15 | int[][] a1 = null; 16 | // a1[1] throws NullPointerException but the hole should 17 | // be filled 18 | int x1 = intArrAccessExp(refArrAccessExp(int[].class, int[][].class, refId(int[][].class, "a1"), asInt(1))).eval(); 19 | // but this hole should not be filled. 20 | y = intVal(1, 4).eval(); 21 | } catch (NullPointerException ignored) {} 22 | 23 | try { 24 | int[][] a2 = {{}}; 25 | // a2[1] throws ArrayIndexOutOfBoundException but the hole 26 | // should be filled 27 | int x2 = intArrAccessExp(refArrAccessExp(int[].class, int[][].class, refId(int[][].class, "a2"), asInt(1))).eval(); 28 | // but this hole should not be filled. 29 | y = intVal(1, 4).eval(); 30 | } catch (ArrayIndexOutOfBoundsException ignored) {} 31 | 32 | try { 33 | int[][] a3 = {{1}}; 34 | // a3[1] throws ArithmeticException but the hole should be 35 | // filled 36 | int x3 = intArrAccessExp(refArrAccessExp(int[].class, int[][].class, refId(int[][].class, "a3"), arithmetic(intId("y"), asInt(0), DIV))).eval(); 37 | // but this hole should not be filled. 38 | y = intVal(1, 4).eval(); 39 | } catch (ArithmeticException ignored) {} 40 | 41 | if (y > 0) { 42 | throw new InvokedFromNotDriverException(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestHoleInArgument.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestHoleInArgument { 9 | 10 | @Entry 11 | public static int m(int i) { 12 | return makeInt(); 13 | } 14 | 15 | @Argument(1) 16 | public static int arg1() { 17 | return makeInt(); 18 | } 19 | 20 | static int makeInt() { 21 | return intVal().eval(); 22 | } 23 | } -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestHoleInConstructor.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | 5 | import jattack.annotation.Entry; 6 | 7 | public class SkTestHoleInConstructor { 8 | 9 | @Entry 10 | static void m() { 11 | C c1 = new C(); 12 | C c2 = new C(true); 13 | } 14 | 15 | static class C extends D { 16 | private static final int I = 10; 17 | 18 | C(boolean b) { 19 | // test three invokespecials 20 | // the second one is the one that instantiates C 21 | this(new D(intId().eval()), // I 22 | intId().eval()); // I 23 | D d = new D(intId().eval()); // I 24 | } 25 | 26 | private C(D d, int i) { 27 | // i, I 28 | super(intId().eval()); 29 | } 30 | 31 | private C(int i) { 32 | // i, I 33 | super(intId().eval()); 34 | } 35 | 36 | C() { 37 | // I 38 | this(intId().eval()); 39 | } 40 | } 41 | 42 | static class D { 43 | private int i; 44 | 45 | D(int i) { 46 | // i 47 | this.i = intId().eval(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestHoleInStaticInitializer.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestHoleInStaticInitializer { 8 | 9 | static int f = makeInt(); 10 | 11 | static { 12 | f = intVal().eval(); 13 | } 14 | 15 | @Entry 16 | public static int m() { 17 | return makeInt(); 18 | } 19 | 20 | static int makeInt() { 21 | return intVal().eval(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestIdAutoInfer.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestIdAutoInfer { 8 | 9 | static class A {} 10 | static class B extends A {} 11 | 12 | @Entry 13 | static void m() { 14 | useDeclaringTypeToCheckAssignable(); 15 | useCast(); 16 | nullAssignableToCompatibleType(); 17 | nullNotAssignableToIncompatibleType(); 18 | } 19 | 20 | static void useDeclaringTypeToCheckAssignable() { 21 | A b1 = new B(); 22 | B b2 = new B(); 23 | // only one possibility, which is b2 24 | B b = refId(B.class).eval(); 25 | } 26 | 27 | static void useCast() { 28 | A b1 = new B(); 29 | B b = (B) refId(A.class).eval(); 30 | } 31 | 32 | static void useCastAPI() { 33 | A b1 = new B(); 34 | B b = cast(B.class, refId(A.class)).eval(); 35 | } 36 | 37 | static void nullAssignableToCompatibleType() { 38 | B b1 = null; 39 | A a = refId(A.class).eval(); 40 | } 41 | 42 | static void nullNotAssignableToIncompatibleType() { 43 | A a1 = null; 44 | B b1 = null; 45 | // only one possibility, which is b1 46 | B b = refId(B.class).eval(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestIfStmtApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestIfStmtApis { 8 | 9 | private static int s = 0; 10 | 11 | @Entry 12 | public static int m() { 13 | int x = 10; 14 | int y = x - 1; 15 | ifStmt(relation("x", "y", LT), preIncIntStmt("x"), preIncIntStmt("y")).eval(); 16 | if (x == y && s == 0) { 17 | x = intVal().eval(); 18 | } 19 | s++; 20 | if (relation(intId("x"), intId("x"), GT).eval()) { 21 | ifStmt(relation("x", "y", LT), preIncIntStmt("x"), preIncIntStmt("y")).eval(); 22 | } 23 | return x + y; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestImValApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.*; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestImValApis { 8 | 9 | // Only one generated program is possible. 10 | @Entry 11 | public static void m() { 12 | mBool(); 13 | mChar(); 14 | mByte(); 15 | mShort(); 16 | mInt(); 17 | mLong(); 18 | mFloat(); 19 | mDouble(); 20 | } 21 | 22 | private static void mBool() { 23 | boolean b = asBool(false).eval(); 24 | boolean x = logic(asBool(false), asBool(true), OR).eval(); 25 | } 26 | 27 | private static void mChar() { 28 | char c = asChar('a').eval(); 29 | int x = arithmetic( 30 | cast(Integer.class, asChar('a')), 31 | cast(Integer.class, asChar('b')), 32 | ADD).eval(); 33 | } 34 | 35 | private static void mByte() { 36 | byte b = asByte((byte) 10).eval(); 37 | int x = arithmetic( 38 | cast(Integer.class, asByte((byte) 10)), 39 | cast(Integer.class, asByte((byte) 11)), 40 | ADD).eval(); 41 | } 42 | 43 | private static void mShort() { 44 | short s = asShort((short) 10).eval(); 45 | int x = arithmetic( 46 | cast(Integer.class, asShort((short) 10)), 47 | cast(Integer.class, asShort((short) 11)), 48 | ADD).eval(); 49 | } 50 | 51 | private static void mInt() { 52 | int i = asInt(10).eval() + asInt(100).eval(); 53 | boolean b = relation(asInt(10), asInt(11), LT).eval(); 54 | } 55 | 56 | private static void mLong() { 57 | long l = asLong(10).eval() + asLong(100).eval(); 58 | boolean b = relation(asLong(10L), asLong(11L), LT).eval(); 59 | } 60 | 61 | private static void mFloat() { 62 | float f = asFloat(10.0f).eval() + asFloat(100.0f).eval(); 63 | boolean b = relation(asFloat(10.0f), asFloat(11.0f), LT).eval(); 64 | } 65 | 66 | private static void mDouble() { 67 | double d = asDouble(10.0).eval() + asDouble(100.0).eval(); 68 | boolean b = relation(asDouble(10.0), asDouble(11.0), LT).eval(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestIntArrRelatedApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestIntArrRelatedApis { 8 | 9 | @Entry() 10 | public static void m() { 11 | testIntArrValOnlyLenBounded(); 12 | testIntArrValFullyBounded(); 13 | testIntArrValWithLen0(); 14 | } 15 | 16 | private static void testIntArrValOnlyLenBounded() { 17 | int x = intArrAccessExp(intArrVal(1, 3)).eval(); 18 | } 19 | 20 | private static void testIntArrValFullyBounded() { 21 | int z = intArrAccessExp(intArrVal(1, 3, 0, 1)).eval(); 22 | } 23 | 24 | private static void testIntArrValWithLen0() { 25 | int y = intArrAccessExp(intArrVal(0, 2, 0, 1)).eval(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestIntValApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.*; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestIntValApis { 9 | 10 | @Entry 11 | public static int m() { 12 | int i = intVal().eval(); 13 | int j = intVal(0, 3).eval(); 14 | if (relation(intVal(-5, -1), intVal(1, 5), GT).eval()) { 15 | i += doubleVal().eval(); 16 | throw new InvokedFromNotDriverException(); 17 | } else { 18 | j += 1; 19 | } 20 | return i + j; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestLocalVariableShadowsField.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestLocalVariableShadowsField { 9 | 10 | double d = 0; 11 | 12 | @Entry 13 | void m(String d) { 14 | // field "d" should be shadowed and not used here 15 | int x = intVal().eval(); 16 | int y = intId().eval(); 17 | m1(); 18 | } 19 | 20 | void m1() { 21 | // field "d" should be found and used here 22 | int x = intVal().eval(); 23 | double y = doubleId().eval(); 24 | } 25 | 26 | @Argument(0) 27 | public static SkTestLocalVariableShadowsField receiver() { 28 | return new SkTestLocalVariableShadowsField(); 29 | } 30 | 31 | @Argument(1) 32 | public static String arg1() { 33 | return null; 34 | } 35 | } -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestMultiDimensionArrays.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestMultiDimensionArrays { 9 | 10 | @Entry 11 | static void m() { 12 | int[][] a = {{1, 2}, {3, 4}}; 13 | int x = 10 + intArrAccessExp(refArrAccessExp(int[].class, int[][].class)).eval(); 14 | assignStmt(intArrAccessExp(refArrAccessExp(int[].class, int[][].class)), intId()).eval(); 15 | for (int[] a1: a) { 16 | for (int e : a1) { 17 | if (e > 10) { 18 | // one element should be greater than 10 19 | return; 20 | } 21 | } 22 | } 23 | throw new InvokedFromNotDriverException(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestNonCompilableGeneratedProgram.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | import jattack.annotation.Entry; 5 | 6 | public class SkTestNonCompilableGeneratedProgram { 7 | 8 | static final int A = 0; 9 | static final int B = 0; 10 | static int s = 0; 11 | 12 | /* Only one generated program is possible, which is 13 | * A < y. Neither A < A nor B < B is able to compile so both 14 | * should be dropped during generation. */ 15 | @Entry 16 | static void m() { 17 | while (relation(intId("A"), intId(), LT).eval()) { 18 | s = 1; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestNonStaticEntryMethodWithSeparateArgumentMethods.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | 5 | import jattack.annotation.Argument; 6 | import jattack.annotation.Entry; 7 | import jattack.exception.InvokedFromNotDriverException; 8 | 9 | public class SkTestNonStaticEntryMethodWithSeparateArgumentMethods { 10 | 11 | @Entry 12 | int m(int x, String y) { 13 | if (x != arg1() || !y.equals(arg2())) { 14 | throw new InvokedFromNotDriverException(); 15 | } 16 | return intVal().eval(); 17 | } 18 | 19 | @Argument(0) 20 | static SkTestNonStaticEntryMethodWithSeparateArgumentMethods receiver() { 21 | return new SkTestNonStaticEntryMethodWithSeparateArgumentMethods(); 22 | } 23 | 24 | @Argument(1) 25 | static int arg1() { 26 | return 1; 27 | } 28 | 29 | @Argument(2) 30 | static String arg2() { 31 | return "hello"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestNonStaticEntryMethodWithSingleArgumentsMethod.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | 5 | import jattack.annotation.Arguments; 6 | import jattack.annotation.Entry; 7 | import jattack.exception.InvokedFromNotDriverException; 8 | 9 | public class SkTestNonStaticEntryMethodWithSingleArgumentsMethod { 10 | 11 | @Entry 12 | int m(int x, String y) { 13 | if (x != (int) args()[1] || !y.equals(args()[2])) { 14 | throw new InvokedFromNotDriverException(); 15 | } 16 | return intVal().eval(); 17 | } 18 | 19 | @Arguments 20 | static Object[] args() { 21 | return new Object[]{ 22 | new SkTestNonStaticEntryMethodWithSingleArgumentsMethod(), 23 | 1, 24 | "hello" 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestOptStopEarlyCorrectnessForCollection.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import static jattack.Boom.*; 9 | 10 | public class SkTestOptStopEarlyCorrectnessForCollection { 11 | 12 | static List l = new ArrayList<>(); 13 | 14 | @Entry 15 | static void testCollection() { 16 | if (!l.isEmpty()) { 17 | // This hole is supposed to be filled if the entry method 18 | // is invoked more than once. 19 | int x = intVal().eval(); 20 | return; 21 | } 22 | int y = intVal().eval(); 23 | // modify l 24 | l.add(1); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestOptStopEarlyCorrectnessForImmutable.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestOptStopEarlyCorrectnessForImmutable { 8 | 9 | static String s = "hello"; 10 | 11 | @Entry 12 | static void testInt() { 13 | if (!s.equals("hello")) { 14 | // This hole is supposed to be filled if the entry method 15 | // is invoked more than once. 16 | int x = intVal().eval(); 17 | return; 18 | } 19 | int y = intVal().eval(); 20 | // set i if i is 10 21 | s = "world"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestOptStopEarlyCorrectnessForJDKClass.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | import static jattack.Boom.*; 8 | 9 | public class SkTestOptStopEarlyCorrectnessForJDKClass { 10 | 11 | static AtomicReference c = new AtomicReference<>(null); 12 | 13 | static class C { 14 | int f = 0; 15 | } 16 | 17 | @Entry 18 | static void testObject() { 19 | if (c.get() != null) { 20 | // This hole is supposed to be filled if the entry method 21 | // is invoked more than once. 22 | // However, if stop early optimization does not work 23 | // correctly, it could be missed and would cause an 24 | // InvokedFromNotDriverException when executing generated 25 | // programs. 26 | int x = intVal().eval(); 27 | return; 28 | } 29 | int y = intVal().eval(); 30 | // set c 31 | c.compareAndSet(null, new C()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestOptStopEarlyCorrectnessForObject.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestOptStopEarlyCorrectnessForObject { 8 | 9 | static C c = new C(); 10 | 11 | static class C { 12 | int f = 0; 13 | } 14 | 15 | @Entry 16 | static void testObject() { 17 | if (c.f != 0) { 18 | // This hole is supposed to be filled if the entry method 19 | // is invoked more than once. 20 | // However, if stop early optimization does not work 21 | // correctly, it could be missed and would cause an 22 | // InvokedFromNotDriverException when executing generated 23 | // programs. 24 | int x = intVal().eval(); 25 | return; 26 | } 27 | int y = intVal().eval(); 28 | // set o if c.f is 0 29 | c.f = 2; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestPreIncApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestPreIncApis { 9 | 10 | private static int s = 0; 11 | 12 | @Entry 13 | public static int m() { 14 | int x = 0; 15 | int y = 0; 16 | preIncIntStmt("s").eval(); 17 | if (relation(intId("x"), intId("x"), GT).eval()) { 18 | preIncIntStmt().eval(); 19 | } 20 | if (s == 0) { 21 | throw new InvokedFromNotDriverException(); 22 | } 23 | return x + y; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestPrimitiveArrRelatedApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Arguments; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestPrimitiveArrRelatedApis { 9 | 10 | static boolean[] f_b = {false, false, true}; 11 | static char[] f_c = {'a', 'b', 'c'}; 12 | static byte[] f_by = {0, 1, 2}; 13 | static short[] f_s = {0, 1, 2}; 14 | static int[] f_i = {0, 1, 2}; 15 | static long[] f_l = {0L, 1L, 2L}; 16 | static float[] f_f = {0.0F, 1.0F, 2.0F}; 17 | static double[] f_d = {0.0, 1.0, 2.0}; 18 | 19 | @Entry 20 | static void m(boolean[] a_b, char[] a_c, byte[] a_by, short[] a_s, 21 | int[] a_i, long[] a_l, float[] a_f, double[] a_d) { 22 | boolean b = boolArrAccessExp().eval(); 23 | char c = charArrAccessExp().eval(); 24 | byte by = byteArrAccessExp().eval(); 25 | short s = shortArrAccessExp().eval(); 26 | int i = intArrAccessExp().eval(); 27 | long l = longArrAccessExp().eval(); 28 | float f = floatArrAccessExp().eval(); 29 | double d = doubleArrAccessExp().eval(); 30 | } 31 | 32 | @Arguments 33 | static Object[] args() { 34 | return new Object[]{ f_b, f_c, f_by, f_s, f_i, f_l, f_f, f_d }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestPrimitiveIdApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.*; 4 | import static jattack.Boom.*; 5 | 6 | public class SkTestPrimitiveIdApis { 7 | 8 | static boolean f_b; 9 | static char f_c; 10 | static byte f_by; 11 | static short f_s; 12 | static int f_i; 13 | static long f_l; 14 | static float f_f; 15 | static double f_d; 16 | 17 | @Entry 18 | public static void m(boolean a_b, char a_c, byte a_by, short a_s, 19 | int a_i, long a_l, float a_f, double a_d) { 20 | boolean b = boolId().eval(); 21 | char c = charId().eval(); 22 | byte by = byteId().eval(); 23 | short s = shortId().eval(); 24 | int i = intId().eval(); 25 | long l = longId().eval(); 26 | float f = floatId().eval(); 27 | double d = doubleId().eval(); 28 | } 29 | 30 | @Arguments 31 | static Object[] args() { 32 | return new Object[]{ f_b, f_c, f_by, f_s, f_i, f_l, f_f, f_d }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestPrimitiveValApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import jattack.exception.InvokedFromNotDriverException; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestPrimitiveValApis { 9 | 10 | @Entry 11 | public static void m() { 12 | boolean b = boolVal().eval(); 13 | char c = charVal().eval(); 14 | mByte(); 15 | mShort(); 16 | mInt(); 17 | mLong(); 18 | mFloat(); 19 | mDouble(); 20 | } 21 | 22 | private static void mByte() { 23 | byte n = byteVal().eval(); 24 | byte low = -10; 25 | byte high = 10; 26 | byte nRanged = byteVal(low, high).eval(); 27 | if (nRanged >= high || nRanged < low) { 28 | throw new InvokedFromNotDriverException(); 29 | } 30 | } 31 | 32 | private static void mShort() { 33 | short n = shortVal().eval(); 34 | short low = Byte.MIN_VALUE - 10; 35 | short high = Byte.MAX_VALUE + 10; 36 | short nRanged = shortVal(low, high).eval(); 37 | if (nRanged >= high || nRanged < low) { 38 | throw new InvokedFromNotDriverException(); 39 | } 40 | } 41 | 42 | private static void mInt() { 43 | int n = intVal().eval(); 44 | int low = Short.MIN_VALUE - 10; 45 | int high = Short.MAX_VALUE + 10; 46 | int nRanged = intVal(low, high).eval(); 47 | if (nRanged >= high || nRanged < low) { 48 | throw new InvokedFromNotDriverException(); 49 | } 50 | } 51 | 52 | private static void mLong() { 53 | long n = longVal().eval(); 54 | long low = Integer.MIN_VALUE - 10L; 55 | long high = Integer.MAX_VALUE + 10L; 56 | long nRanged = longVal(low, high).eval(); 57 | if (nRanged >= high || nRanged < low) { 58 | throw new InvokedFromNotDriverException(); 59 | } 60 | } 61 | 62 | private static void mFloat() { 63 | float n = floatVal().eval(); 64 | float low = -10.0F; 65 | float high = 10.0F; 66 | float nRanged = floatVal(low, high).eval(); 67 | if (nRanged >= high || nRanged < low) { 68 | throw new InvokedFromNotDriverException(); 69 | } 70 | } 71 | 72 | private static void mDouble() { 73 | double n = doubleVal().eval(); 74 | double low = -10.0; 75 | double high = 10.0; 76 | double nRanged = doubleVal(low, high).eval(); 77 | if (nRanged >= high || nRanged < low) { 78 | throw new InvokedFromNotDriverException(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestReceiverOfEntryMethodIsNull.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | 6 | import static jattack.Boom.*; 7 | 8 | public class SkTestReceiverOfEntryMethodIsNull { 9 | 10 | @Entry 11 | void m(int x) { 12 | } 13 | 14 | @Argument(0) 15 | public static SkTestReceiverOfEntryMethodIsNull receiver() { 16 | return null; 17 | } 18 | 19 | @Argument(1) 20 | public static int arg1() { 21 | return intVal().eval(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestRefArrRelatedApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestRefArrRelatedApis { 8 | 9 | static int s = 0; 10 | 11 | static class C { 12 | int i; 13 | C(int i) { 14 | this.i = i; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "C:" + i; 20 | } 21 | } 22 | 23 | @Entry 24 | public static void m() { 25 | testRefArrAccessExpWithoutGivenIds(); 26 | testRefArrAccessExpWithGivenIds(); 27 | testRefArrAccessExpWithGivenIndicies(); 28 | } 29 | 30 | private static void testRefArrAccessExpWithoutGivenIds() { 31 | C[] arr1 = { new C(1), new C(2), new C(3) }; 32 | C[] arr2 = { new C(10), new C(20), new C(30) }; 33 | C x = refArrAccessExp(C.class, C[].class).eval(); 34 | s += x.i; 35 | } 36 | 37 | private static void testRefArrAccessExpWithGivenIds() { 38 | C[] arr1 = { new C(1), new C(2), new C(3) }; 39 | C[] arr2 = { new C(10), new C(20), new C(30) }; 40 | C x = refArrAccessExp(C.class, C[].class, "arr1").eval(); 41 | s += x.i; 42 | } 43 | 44 | 45 | private static void testRefArrAccessExpWithGivenIndicies() { 46 | C[] arr1 = { new C(1), new C(2), new C(3) }; 47 | C[] arr2 = { new C(10), new C(20), new C(30) }; 48 | C x = refArrAccessExp(C.class, C[].class, "arr2", intVal(1, 3)).eval(); 49 | s += x.i; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestRefIdApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | import static jattack.Boom.*; 5 | 6 | public class SkTestRefIdApis { 7 | 8 | private static int s = 0; 9 | 10 | private static class C { 11 | private int f; 12 | 13 | private C(int f) { 14 | this.f = f; 15 | } 16 | } 17 | 18 | @Entry 19 | public static void m() { 20 | testStringClass(); 21 | testGeneralClass(); 22 | } 23 | 24 | private static void testStringClass() { 25 | String str1 = "Hello"; 26 | String str2 = "Hello"; 27 | if (refId(String.class).eval().equals(refId(String.class).eval())) { 28 | s += intVal().eval(); 29 | } else { 30 | s -= intVal().eval(); 31 | } 32 | } 33 | 34 | private static void testGeneralClass() { 35 | C c1 = new C(1); 36 | C c2 = new C(2); 37 | C c = refId(C.class).eval(); 38 | int x = c.f; 39 | if (x > 1) { 40 | s += intVal().eval(); 41 | } else { 42 | s -= intVal().eval(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestRefIdCastToSuperTypeWhenFilled.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestRefIdCastToSuperTypeWhenFilled { 8 | 9 | @Entry 10 | static void m() { 11 | String s = "hello"; 12 | overridedM(refId(Object.class).eval()); 13 | } 14 | 15 | // If we go to this method, then we will get an 16 | // InvokedFromNotDriverException 17 | static void overridedM(String s) { 18 | int x = intVal().eval(); 19 | } 20 | 21 | // should go to this method 22 | static void overridedM(Object o) { 23 | int x = intVal().eval(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestRefIdWorksWhenVarIsNull.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Argument; 4 | import jattack.annotation.Entry; 5 | import jattack.exception.InvokedFromNotDriverException; 6 | 7 | import static jattack.Boom.*; 8 | 9 | public class SkTestRefIdWorksWhenVarIsNull { 10 | 11 | @Entry 12 | static void m(String a) { 13 | String s = "hello"; 14 | assignStmt(refId(String.class, "s"), refId(String.class, "a")).eval(); 15 | String t = refId(String.class, "s").eval(); 16 | if (s != null || t != null) { 17 | throw new InvokedFromNotDriverException(); 18 | } 19 | } 20 | 21 | @Argument(1) 22 | static String arg1() { 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestShiftApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestShiftApis { 8 | 9 | private static int s1; 10 | 11 | @Entry 12 | public static int m() { 13 | int x = 1; 14 | int y = 10; 15 | int z = arithOrShift(intId(), intId()).eval(); 16 | z += shift(intId(), intId()).eval(); 17 | return x + y + z; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestShortCircuitEvaluation.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestShortCircuitEvaluation { 8 | 9 | @Entry 10 | public static void m() { 11 | int y = 0; 12 | if (logic(relation(10, 11, GE), 13 | /* ++y > 0 should not be evaluated due to short circuit. */ 14 | relation(preIncIntExp("y"), 0, GT), 15 | AND).eval()) {} 16 | if (y == 0) { 17 | // if y gets increased, which means short circuit failed, 18 | // this hole will not be filled, and we will see a 19 | // crash when running the generated program with the hole 20 | // unfilled. 21 | int z = intVal().eval(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestSolverAidWithArrays.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | import jattack.annotation.Entry; 5 | 6 | public class SkTestSolverAidWithArrays { 7 | 8 | static int s = 0; 9 | 10 | @Entry 11 | static void m() { 12 | int[] arr = { 1 }; 13 | /* If we print intermediate hot filling source code then this 14 | branch is supposed to be eliminated as it is unsatisfiable. 15 | */ 16 | if (relation(asIntArrAccess("arr[0]"), asIntArrAccess("arr[0]"), LT).eval()) { 17 | s += intVal().eval(); 18 | } else { 19 | s += intVal().eval(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestStaticFieldReset.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | import jattack.annotation.Entry; 5 | import jattack.exception.InvokedFromNotDriverException; 6 | 7 | /** 8 | * Test static fields can be re-initialized correctly before starting 9 | * generating a new program from the template. 10 | */ 11 | public class SkTestStaticFieldReset { 12 | 13 | private final static int primFinal = 1; 14 | private static int primWithInit = 1; 15 | private static long primWOInit; 16 | 17 | private final static String strFinal = "foo"; 18 | private static String strWithInit = "foo"; 19 | private static String strWOInit; 20 | 21 | private final static int[] finalArr = {0, 0, 0}; 22 | private static int[] arrWithInit = {0, 0, 0}; 23 | private static int[] arrWOInitializer; 24 | 25 | /** 26 | * If the state of the template was not well reset after the 27 | * generation of the first program completes, the next generated 28 | * programs will have all holes unfilled, which causes 29 | * InvokedFromDriver exception since these holes actually should 30 | * be filled. 31 | * We check primitives, strings, references as well as final, with 32 | * initializer and without initializer. 33 | */ 34 | @Entry 35 | public static void m() { 36 | // update static fields 37 | if (primWithInit == 1) { 38 | primWithInit = intVal(5, 10).eval(); 39 | } 40 | if (primWOInit == 0) { 41 | primWOInit = longVal(10L, 20L).eval(); 42 | } 43 | String hello = "hello"; 44 | if (strWithInit.equals("foo")) { 45 | strWithInit = refId(String.class, "hello").eval(); 46 | } 47 | if (strWOInit == null) { 48 | strWOInit = refId(String.class, "hello").eval(); 49 | } 50 | if (arrWithInit[1] == 0) { 51 | arrWithInit[1] = intVal(5, 10).eval(); 52 | } 53 | if (arrWOInitializer == null) { 54 | int[] a = {5, 6, 7}; 55 | arrWOInitializer = intArrId("a").eval(); 56 | } 57 | if (finalArr[1] == 0) { 58 | finalArr[1] = intVal(5, 10).eval(); 59 | } 60 | 61 | // check final 62 | if (primFinal != 1) { 63 | throw new InvokedFromNotDriverException(); 64 | } 65 | if (!strFinal.equals("foo")) { 66 | throw new InvokedFromNotDriverException(); 67 | } 68 | int x = intVal().eval(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestStaticFieldResetForNestedClass.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | import jattack.annotation.Entry; 5 | import jattack.exception.InvokedFromNotDriverException; 6 | 7 | /** 8 | * Test static fields of nested classes can be re-intialized correctly 9 | * before starting generating a new program from the template. 10 | */ 11 | public class SkTestStaticFieldResetForNestedClass { 12 | 13 | private static class C { 14 | private final static int primFinal = 1; 15 | private static int primWithInit = 1; 16 | private static long primWOInit; 17 | 18 | private final static String strFinal = "foo"; 19 | private static String strWithInit = "foo"; 20 | private static String strWOInit; 21 | 22 | private final static int[] finalArr = {0, 0, 0}; 23 | private static int[] arrWithInit = {0, 0, 0}; 24 | private static int[] arrWOInitializer; 25 | } 26 | 27 | /** 28 | * Same logic as {@link SkTestStaticFieldReset#m()}. 29 | */ 30 | @Entry 31 | public static void m() { 32 | // update static fields 33 | if (C.primWithInit == 1) { 34 | C.primWithInit = intVal(5, 10).eval(); 35 | } 36 | if (C.primWOInit == 0) { 37 | C.primWOInit = longVal(10L, 20L).eval(); 38 | } 39 | String hello = "hello"; 40 | if (C.strWithInit.equals("foo")) { 41 | C.strWithInit = refId(String.class, "hello").eval(); 42 | } 43 | if (C.strWOInit == null) { 44 | C.strWOInit = refId(String.class, "hello").eval(); 45 | } 46 | if (C.arrWithInit[1] == 0) { 47 | C.arrWithInit[1] = intVal(5, 10).eval(); 48 | } 49 | if (C.arrWOInitializer == null) { 50 | int[] a = {5, 6, 7}; 51 | C.arrWOInitializer = intArrId("a").eval(); 52 | } 53 | if (C.finalArr[1] == 0) { 54 | C.finalArr[1] = intVal(5, 10).eval(); 55 | } 56 | 57 | // check final 58 | if (C.primFinal != 1) { 59 | throw new InvokedFromNotDriverException(); 60 | } 61 | if (!C.strFinal.equals("foo")) { 62 | throw new InvokedFromNotDriverException(); 63 | } 64 | int x = intVal().eval(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestTryStmtApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestTryStmtApis { 8 | 9 | private static int s = 0; 10 | 11 | @Entry 12 | public static void m() { 13 | s++; 14 | testEmptyBlocks(); 15 | testSimpleTryStmt(); 16 | testTryInBodyOfWhile(); 17 | testSolverAidWorksForBlock(); 18 | } 19 | 20 | private static void testSolverAidWorksForBlock() { 21 | int x = 1; 22 | if (relation(intId("x"), intId("x"), GT).eval()) { 23 | // optSolverAid should work in this case to hide this hole. 24 | tryStmt(block(assignStmt(intId("x"), arithmetic("x", 0, DIV))), 25 | ArithmeticException.class, 26 | block(preIncIntStmt("x")), 27 | block(preIncIntStmt("x"))).eval(); 28 | } 29 | } 30 | 31 | private static void testTryInBodyOfWhile() { 32 | int x = 1; 33 | whileStmt(relation(intId("x"), 2, LE), 34 | tryStmt(block(assignStmt(intId("x"), arithmetic("x", 0, DIV))), 35 | ArithmeticException.class, 36 | block(preIncIntStmt("x")), 37 | block(preIncIntStmt("x")))).eval(); 38 | if (x == 3 && s == 1) { 39 | x += intVal().eval(); 40 | } 41 | } 42 | 43 | private static void testSimpleTryStmt() { 44 | int x = 10; 45 | tryStmt(block(assignStmt(intId("x"), arithmetic("x", 0, DIV))), 46 | ArithmeticException.class, 47 | block(assignStmt(intId("x"), asInt(-1))), 48 | block()).eval(); 49 | if (x == -1 && s == 1) { 50 | x = x + intVal().eval(); 51 | } 52 | } 53 | 54 | private static void testEmptyBlocks() { 55 | tryStmt(block(), Exception.class, block(), block()).eval(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestVoidReturnEntryMethod.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import static jattack.Boom.*; 4 | import jattack.annotation.Entry; 5 | 6 | public class SkTestVoidReturnEntryMethod { 7 | 8 | @Entry 9 | public static void m() { 10 | int x = intVal().eval(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/examples/SkTestWhileStmtApis.java: -------------------------------------------------------------------------------- 1 | package jattack.examples; 2 | 3 | import jattack.annotation.Entry; 4 | 5 | import static jattack.Boom.*; 6 | 7 | public class SkTestWhileStmtApis { 8 | 9 | private static int s = 0; 10 | 11 | @Entry 12 | public static int m() { 13 | int x = 1; 14 | whileStmt(relation("x", 10, LT), preIncIntStmt("x")).eval(); 15 | if (x == 10 && s == 0) { 16 | x = intVal().eval(); 17 | } 18 | s++; 19 | if (relation(intId("x"), intId("x"), GT).eval()) { 20 | // optSolverAid should work in this case to hide this hole. 21 | whileStmt(relation("x", 10, LT), preIncIntStmt("x")).eval(); 22 | } 23 | return x; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/log/LogTest.java: -------------------------------------------------------------------------------- 1 | package jattack.log; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.PrintStream; 7 | 8 | import org.junit.AfterClass; 9 | import org.junit.Before; 10 | import org.junit.BeforeClass; 11 | import org.junit.Test; 12 | 13 | public class LogTest { 14 | 15 | private static final String msg = "Message"; 16 | private static final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); 17 | 18 | private static Log.Level originalLevel; 19 | private static PrintStream originalOut; 20 | 21 | @BeforeClass 22 | public static void setUpClass() { 23 | originalOut = System.out; 24 | originalLevel = Log.getLevel(); 25 | System.setOut(new PrintStream(outContent)); 26 | } 27 | 28 | @Before 29 | public void setUp() { 30 | outContent.reset(); 31 | } 32 | 33 | @AfterClass 34 | public static void tearDown() { 35 | Log.setLevel(originalLevel); 36 | System.setOut(originalOut); 37 | } 38 | 39 | @Test 40 | public void testLogDebugAtDebugLevel() { 41 | Log.setLevel(Log.Level.DEBUG); 42 | Log.debug(msg); 43 | assertEquals(Log.getFullLogMessage(msg, Log.Level.DEBUG), 44 | outContent.toString()); 45 | } 46 | 47 | @Test 48 | public void testLogInfoAtDebugLevel() { 49 | Log.setLevel(Log.Level.DEBUG); 50 | Log.info(msg); 51 | assertEquals(Log.getFullLogMessage(msg, Log.Level.INFO), 52 | outContent.toString()); 53 | } 54 | 55 | @Test 56 | public void testLogErrorAtDebugLevel() { 57 | Log.setLevel(Log.Level.DEBUG); 58 | Log.error(msg); 59 | assertEquals(Log.getFullLogMessage(msg, Log.Level.ERROR), 60 | outContent.toString()); 61 | } 62 | 63 | @Test 64 | public void testLogDebugAtInfoLevel() { 65 | Log.setLevel(Log.Level.INFO); 66 | Log.debug(msg); 67 | assertEquals("", outContent.toString()); 68 | } 69 | 70 | @Test 71 | public void testLogInfoAtInfoLevel() { 72 | Log.setLevel(Log.Level.INFO); 73 | Log.info(msg); 74 | assertEquals(Log.getFullLogMessage(msg, Log.Level.INFO), 75 | outContent.toString()); 76 | } 77 | 78 | @Test 79 | public void testLogErrorAtInfoLevel() { 80 | Log.setLevel(Log.Level.INFO); 81 | Log.error(msg); 82 | assertEquals(Log.getFullLogMessage(msg, Log.Level.ERROR), 83 | outContent.toString()); 84 | } 85 | 86 | @Test 87 | public void testLogDebugAtErrorLevel() { 88 | Log.setLevel(Log.Level.ERROR); 89 | Log.debug(msg); 90 | assertEquals("", outContent.toString()); 91 | } 92 | 93 | @Test 94 | public void testLogInfoAtErrorLevel() { 95 | Log.setLevel(Log.Level.ERROR); 96 | Log.info(msg); 97 | assertEquals("", outContent.toString()); 98 | } 99 | 100 | @Test 101 | public void testLogErrorAtErrorLevel() { 102 | Log.setLevel(Log.Level.ERROR); 103 | Log.error(msg); 104 | assertEquals(Log.getFullLogMessage(msg, Log.Level.ERROR), 105 | outContent.toString()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/transformer/HoleExtractorTest.java: -------------------------------------------------------------------------------- 1 | package jattack.transformer; 2 | 3 | import com.github.javaparser.StaticJavaParser; 4 | import com.github.javaparser.ast.CompilationUnit; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | import jattack.Constants; 8 | import jattack.ast.exp.BAriExp; 9 | import jattack.ast.exp.LogExp; 10 | import jattack.compiler.CompilationException; 11 | import jattack.compiler.InMemoryCompiler; 12 | import jattack.data.Data; 13 | import jattack.util.TypeUtil; 14 | 15 | import java.lang.reflect.InvocationTargetException; 16 | 17 | public class HoleExtractorTest { 18 | 19 | @Test 20 | public void test() { 21 | // Extraction looks right 22 | CompilationUnit origCu = StaticJavaParser.parse( 23 | "import " + Constants.ENTRY_ANNOT_FULL_NAME + ";\n" + 24 | "import static " + Constants.BOOM_CLZ + ".*;\n" + 25 | "public class Sk {\n" + 26 | " static int s1;\n" + 27 | " @Entry\n" + 28 | " public static int m() {\n" + 29 | " if (logic(relation(intId(), intId()), relation(intId(), intId())).eval(1)) {\n" + 30 | " s1 = arithmetic(intId(), intId()).eval(2);\n" + 31 | " }\n" + 32 | " return s1;\n" + 33 | " }\n" + 34 | "}"); 35 | CompilationUnit expectedCu = StaticJavaParser.parse(String.format( 36 | "import " + Constants.ENTRY_ANNOT_FULL_NAME + ";\n" + 37 | "import static " + Constants.BOOM_CLZ + ".*;\n" + 38 | "public class %s {\n" + 39 | " public static void %s() {\n" + 40 | " %s.%s().put(1, logic(relation(intId(), intId()), relation(intId(), intId())));\n" + 41 | "%s.%s().put(2, arithmetic(intId(), intId()));" + 42 | " }\n" + 43 | "}", 44 | HoleExtractor.CLASS_NAME, 45 | HoleExtractor.METHOD_NAME, 46 | Constants.DATA_CLZ, 47 | Constants.GET_AST_CACHE_METHOD, 48 | Constants.DATA_CLZ, 49 | Constants.GET_AST_CACHE_METHOD)); 50 | HoleExtractor he = new HoleExtractor(origCu); 51 | he.transform(); 52 | CompilationUnit actualCu = he.getCu(); 53 | Assert.assertEquals(expectedCu, actualCu); 54 | 55 | // Extraction executes right 56 | Data.clearASTCache(); 57 | InMemoryCompiler compiler = new InMemoryCompiler(); 58 | try { 59 | System.err.println(he.getSrcCode()); 60 | ClassLoader cl = compiler.compileAndRedefine( 61 | HoleExtractor.CLASS_NAME, he.getSrcCode()); 62 | Class clz = TypeUtil.loadClz(HoleExtractor.CLASS_NAME, true, cl); 63 | clz.getDeclaredMethod(HoleExtractor.METHOD_NAME).invoke(null); 64 | } catch (CompilationException e) { 65 | Assert.fail("Not compile!"); 66 | } catch (ClassNotFoundException 67 | | NoSuchMethodException 68 | | IllegalAccessException 69 | | InvocationTargetException e) { 70 | throw new RuntimeException(e); 71 | } 72 | Assert.assertTrue(Data.getASTOfHole(1) instanceof LogExp); 73 | Assert.assertTrue(Data.getASTOfHole(2) instanceof BAriExp); 74 | Data.clearASTCache(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tool/api/src/test/java/jattack/util/UniqueListTest.java: -------------------------------------------------------------------------------- 1 | package jattack.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class UniqueListTest { 10 | 11 | @Test 12 | public void testAddNew() { 13 | UniqueList ul = new UniqueList<>(Arrays.asList("a", "b")); 14 | ul.add("c"); 15 | List expected = Arrays.asList("a", "b", "c"); 16 | Assert.assertTrue("UniqueList is not equal to " + expected, 17 | assertUniqueListEquals(ul, expected)); 18 | } 19 | 20 | @Test 21 | public void testAddExisting() { 22 | UniqueList ul = new UniqueList<>(Arrays.asList("a", "b")); 23 | ul.add("b"); 24 | List expected = Arrays.asList("a", "b"); 25 | Assert.assertTrue("UniqueList is not equal to " + expected, 26 | assertUniqueListEquals(ul, expected)); 27 | } 28 | 29 | @Test 30 | public void testRemoveLast() { 31 | UniqueList ul = new UniqueList<>(Arrays.asList("a", "b", "c")); 32 | ul.remove("c"); 33 | List expected = Arrays.asList("a", "b"); 34 | Assert.assertTrue("UniqueList is not equal to " + expected, 35 | assertUniqueListEquals(ul, expected)); 36 | } 37 | 38 | @Test 39 | public void testRemoveFirst() { 40 | UniqueList ul = new UniqueList<>(Arrays.asList("a", "b", "c")); 41 | ul.remove("a"); 42 | List expected = Arrays.asList("b", "c"); 43 | Assert.assertTrue("UniqueList " + ul + " is not equal to " + expected + ".", 44 | assertUniqueListEquals(ul, expected)); 45 | } 46 | 47 | @Test 48 | public void testRemoveMiddle() { 49 | UniqueList ul = new UniqueList<>(Arrays.asList("a", "b", "c")); 50 | ul.remove("b"); 51 | List expected = Arrays.asList("a", "c"); 52 | Assert.assertTrue("UniqueList is not equal to " + expected, 53 | assertUniqueListEquals(ul, expected)); 54 | } 55 | 56 | @Test 57 | public void testAddRemoveSequence() { 58 | UniqueList ul = new UniqueList<>(); 59 | ul.add("a"); 60 | ul.add("b"); 61 | ul.remove("a"); 62 | ul.add("b"); 63 | List expected = Arrays.asList("b"); 64 | Assert.assertTrue("UniqueList is not equal to " + expected, 65 | assertUniqueListEquals(ul, expected)); 66 | 67 | } 68 | 69 | private boolean assertUniqueListEquals( 70 | UniqueList ul1, List ul2) { 71 | if (ul1.size() != ul2.size()) { 72 | return false; 73 | } 74 | for (int i = 0; i < ul1.size(); i++) { 75 | if (!ul1.get(i).equals(ul2.get(i))) { 76 | return false; 77 | } 78 | } 79 | return true; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tool/csutil/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Java Library project to get you started. 5 | * For more details take a look at the Java Libraries chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/6.0.1/userguide/java_library_plugin.html 7 | */ 8 | 9 | plugins { 10 | id 'java-library' 11 | } 12 | 13 | group 'csutil' 14 | version '' 15 | 16 | repositories { 17 | mavenCentral() 18 | } 19 | 20 | dependencies { 21 | testImplementation 'junit:junit:4.12' 22 | } 23 | 24 | java { 25 | sourceCompatibility = JavaVersion.VERSION_11 26 | targetCompatibility = JavaVersion.VERSION_11 27 | } 28 | -------------------------------------------------------------------------------- /tool/csutil/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EngineeringSoftware/jattack/212ce3ebbc4ebc80691aecfcb94c3c2995f2bc9e/tool/csutil/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /tool/csutil/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /tool/csutil/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/6.0.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'csutil' 11 | -------------------------------------------------------------------------------- /tool/csutil/src/main/java/org/csutil/Helper.java: -------------------------------------------------------------------------------- 1 | package org.csutil; 2 | 3 | import java.io.IOException; 4 | import java.nio.charset.StandardCharsets; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | 8 | public class Helper { 9 | public static String outFilePath = "checksum.txt"; 10 | public static int nItrs= Integer.MAX_VALUE; 11 | 12 | public static void parseArgs(String[] args) { 13 | for (String arg : args) { 14 | if (!arg.startsWith("--")) { 15 | throw new RuntimeException("Argument does NOT start with --: " + arg + "!"); 16 | } 17 | String opt = arg.substring(2); // remove "--" 18 | if (opt.isEmpty()) { 19 | throw new RuntimeException("Nothing following --: " + arg + "!"); 20 | } 21 | int pos = opt.indexOf('='); 22 | String key = ""; 23 | String value = ""; 24 | if (pos == -1) { 25 | // no "=" 26 | key = opt; 27 | } else { 28 | if (pos == opt.length() - 1) { 29 | throw new RuntimeException("Nothing following key: " + arg + "!"); 30 | } 31 | key = opt.substring(0, pos); 32 | value = opt.substring(pos + 1); 33 | } 34 | switch (key) { 35 | case "outFilePath": { 36 | outFilePath = value; 37 | break; 38 | } 39 | case "nItrs": { 40 | nItrs = Integer.parseInt(value); 41 | break; 42 | } 43 | default: 44 | throw new RuntimeException("Unrecognized option: " + key); 45 | } 46 | } 47 | } 48 | 49 | public static void write(long checksumValue) { 50 | try { 51 | Files.write(Path.of(outFilePath), 52 | (checksumValue + "\n").getBytes(StandardCharsets.UTF_8)); 53 | } catch (IOException e) { 54 | throw new RuntimeException(e); 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /tool/csutil/src/main/java/org/csutil/log/Log.java: -------------------------------------------------------------------------------- 1 | package org.csutil.log; 2 | 3 | /** 4 | * Utility class for logging. 5 | */ 6 | public class Log { 7 | 8 | public enum Level { 9 | DEBUG("DEBUG", 2), 10 | INFO("INFO", 1), 11 | ERROR("ERROR", 0); 12 | 13 | private final String name; 14 | private final int order; 15 | 16 | Level(String name, int order) { 17 | this.name = name; 18 | this.order = order; 19 | } 20 | } 21 | 22 | private static final String MSG_PREFIX = "CSUTIL:"; 23 | 24 | private static Level level = Level.ERROR; 25 | 26 | public static void setLevel(String newLevel) { 27 | switch (newLevel) { 28 | case "debug": 29 | setLevel(Level.DEBUG); 30 | break; 31 | case "info": 32 | setLevel(Level.INFO); 33 | break; 34 | case "error": 35 | setLevel(Level.ERROR); 36 | break; 37 | default: 38 | throw new RuntimeException("Unrecognized logging level: " + newLevel + "!"); 39 | } 40 | } 41 | 42 | public static void setLevel(Level newLevel) { 43 | level = newLevel; 44 | } 45 | 46 | public static Level getLevel() { 47 | return level; 48 | } 49 | 50 | public static void debug(Object msg) { 51 | log(msg, Level.DEBUG); 52 | } 53 | 54 | public static void info(Object msg) { 55 | log(msg, Level.INFO); 56 | } 57 | 58 | public static void error(Object msg) { 59 | log(msg, Level.ERROR); 60 | } 61 | 62 | // We want to use this method in tests so I made it 63 | // package-private. 64 | static String getFullLogMessage(Object msg, Level logLevel) { 65 | return MSG_PREFIX + logLevel.name + ": " + msg + System.lineSeparator(); 66 | } 67 | 68 | private static void log(Object msg, Level logLevel) { 69 | if (level.order < logLevel.order) { 70 | return; 71 | } 72 | System.out.print(getFullLogMessage(msg, logLevel)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tool/csutil/src/main/java/org/csutil/util/ByteBufferUtil.java: -------------------------------------------------------------------------------- 1 | package org.csutil.util; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /** 6 | * Convert a primitive type to ByteBuffer. 7 | */ 8 | public class ByteBufferUtil { 9 | 10 | public static ByteBuffer toByteBuffer(boolean val) { 11 | ByteBuffer byteBuffer = ByteBuffer.allocate(1); 12 | byte byteVal = (byte) (val ? 0x1 : 0x0); 13 | byteBuffer.put(byteVal); 14 | byteBuffer.rewind(); 15 | return byteBuffer; 16 | } 17 | 18 | public static ByteBuffer toByteBuffer(byte val) { 19 | ByteBuffer byteBuffer = ByteBuffer.allocate(1); 20 | byteBuffer.put(val); 21 | byteBuffer.rewind(); 22 | return byteBuffer; 23 | } 24 | 25 | public static ByteBuffer toByteBuffer(char val) { 26 | ByteBuffer byteBuffer = ByteBuffer.allocate(2); 27 | byteBuffer.putChar(val); 28 | byteBuffer.rewind(); 29 | return byteBuffer; 30 | } 31 | 32 | public static ByteBuffer toByteBuffer(double val) { 33 | // Treat all NaN the same as the canonical one 34 | if (Double.isNaN(val)) { 35 | val = Double.NaN; 36 | } 37 | ByteBuffer byteBuffer = ByteBuffer.allocate(8); 38 | byteBuffer.putDouble(val); 39 | byteBuffer.rewind(); 40 | return byteBuffer; 41 | } 42 | 43 | public static ByteBuffer toByteBuffer(float val) { 44 | // Treat all NaN the same as the canonical one 45 | if (Float.isNaN(val)) { 46 | val = Float.NaN; 47 | } 48 | ByteBuffer byteBuffer = ByteBuffer.allocate(4); 49 | byteBuffer.putFloat(val); 50 | byteBuffer.rewind(); 51 | return byteBuffer; 52 | } 53 | 54 | public static ByteBuffer toByteBuffer(int val) { 55 | ByteBuffer byteBuffer = ByteBuffer.allocate(4); 56 | byteBuffer.putInt(val); 57 | byteBuffer.rewind(); 58 | return byteBuffer; 59 | } 60 | 61 | public static ByteBuffer toByteBuffer(long val) { 62 | ByteBuffer byteBuffer = ByteBuffer.allocate(8); 63 | byteBuffer.putLong(val); 64 | byteBuffer.rewind(); 65 | return byteBuffer; 66 | } 67 | 68 | public static ByteBuffer toByteBuffer(short val) { 69 | ByteBuffer byteBuffer = ByteBuffer.allocate(2); 70 | byteBuffer.putShort(val); 71 | byteBuffer.rewind(); 72 | return byteBuffer; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tool/csutil/src/test/java/org/csutil/util/ExtRandom.java: -------------------------------------------------------------------------------- 1 | package org.csutil.util; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Extended Random class that generates random byte/char/short. 7 | */ 8 | public class ExtRandom extends Random { 9 | 10 | public byte nextByte() { 11 | return (byte) next(8); 12 | } 13 | 14 | public char nextChar() { 15 | return (char) next(16); // non-negative 16 | } 17 | 18 | public short nextShort() { 19 | return (short) next(16); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tool/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | readonly _DIR="$( cd -P "$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )" )" && pwd )" 4 | 5 | set -e 6 | 7 | ### Build JAttack jar. Java >=11 8 | echo "Build JAttack jar..." 9 | pushd "${_DIR}"/api >/dev/null 10 | ./gradlew -q clean shadowJar 11 | popd >/dev/null 12 | cp "${_DIR}"/api/build/libs/jattack-*-all.jar "${_DIR}"/jattack-all.jar 13 | 14 | ### Install python packages. Python 3.8 15 | echo "Install python packages..." 16 | pip install -qr "${_DIR}"/requirements.txt 17 | 18 | ### Create executable script. 19 | exec="${_DIR}"/jattack 20 | echo "#!/bin/bash" >"$exec" 21 | echo 'readonly _DIR="$( cd -P "$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )" )" && pwd )"' >>"$exec" 22 | echo 'python3 ${_DIR}/jattack.py "$@"' >>"$exec" 23 | chmod +x "$exec" 24 | -------------------------------------------------------------------------------- /tool/requirements.txt: -------------------------------------------------------------------------------- 1 | jsonargparse==4.17.0 2 | natsort==8.2.0 3 | seutil==0.8.6 4 | --------------------------------------------------------------------------------