diff --git a/.gitignore b/.gitignore index 1cc71e4737..409614f8f8 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,5 @@ unittests/PhasarLLVM/ifdside/Problems/IFDSTaintAnalysisTest unittests/PhasarLLVM/Pointer/LLVMTypeHierarchyTest unittests/Utils/LLVMShorthandsTest unittests/Utils/PAMMTest + +.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index b9eb753662..a915c22483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,7 +155,14 @@ if (NOT PHASAR_IN_TREE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) endif() -if (LLVM_ENABLE_LIBCXX) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(PHASAR_STD_FILESYSTEM stdc++) + set(LLVM_INSTALL_PATH "/opt/homebrew/opt/llvm@14") + set(LDFLAGS "-L${LLVM_INSTALL_PATH}/lib") + set(CPPFLAGS "-I${LLVM_INSTALL_PATH}/include") + set(LLVM_DIR "/opt/homebrew/opt/llvm@14/lib/cmake/llvm") + set(PATH "${LLVM_INSTALL_PATH}/bin:$ENV{PATH}") +elseif (LLVM_ENABLE_LIBCXX) set(PHASAR_STD_FILESYSTEM c++fs) else() set(PHASAR_STD_FILESYSTEM stdc++fs) diff --git a/README.md b/README.md index 8e27e018aa..4f2844e697 100644 --- a/README.md +++ b/README.md @@ -98,8 +98,19 @@ Done! ### Installing PhASAR a MacOS system -Due to unfortunate updates to MacOS and the handling of C++, especially on the newer M1 processors, we can't support native development on Mac. -The easiest solution to develop PhASAR on a Mac right now is to use [dockers development environments](https://docs.docker.com/desktop/dev-environments/). Clone this repository as described in their documentation. Afterwards, you have to login once manually, as a root user by running `docker exec -it -u root /bin/bash` to complete the rest of the install process as described in this readme (install submodules, run bootstrap.sh, ...). +To install PhASAR on a Mac you need to follow these steps: +1. Install both LLVM 14 and LLVM 17 on your system using e.g. homebrew. +2. Setup LLVM 17 as your compiler to compile PhASAR with using the following environment variables + +``` +// this must point to LLVM 17 ! +CC=/opt/homebrew/opt/llvm/bin/clang +CXX=/opt/homebrew/opt/llvm/bin/clang++ +``` +3. Check the default settings for `LDFLAGS`, `CPPFLAGS`, and `PATH` in PhASAR's CMakeLists.txt if they point to your LLVM 14 installation. The default install path is `/opt/homebrew/opt/llvm@14` +4. Run `cmake .. -DCMAKE_CXX_COMPILER=$CXX -DPHASAR_BUILD_UNITTESTS=0 -DPHASAR_BUILD_IR=0 -G Ninja` and `ninja` to build PhASAR (currently unit tests break the build, because cmake tries to use LLVM 17 to create the IR. We are working on a solution for this) + +The easiest solution to develop PhASAR on a Mac still is to use [dockers development environments](https://docs.docker.com/desktop/dev-environments/). Clone this repository as described in their documentation. Afterwards, you have to login once manually, as a root user by running `docker exec -it -u root /bin/bash` to complete the rest of the install process as described in this readme (install submodules, run bootstrap.sh, ...). Now you can just attach your docker container to VS Code or any other IDE, which supports remote development. ### Compiling PhASAR (if not already done using the installation scripts) @@ -163,6 +174,7 @@ When using CMake to compile PhASAR the following optional parameters can be used | **PHASAR_BUILD_UNITTESTS** : BOOL | Build PhASAR unit tests (default is ON) | | **PHASAR_BUILD_IR** : BOOL | Build PhASAR IR (required for running the unit tests) (default is ON) | | **PHASAR_BUILD_OPENSSL_TS_UNITTESTS** : BOOL | Build PhASAR unit tests that require OpenSSL (default is OFF) | +| **BUILD_SWIFT_TESTS** : BOOL | Builds the Swift tests (Swift compiler has to be installed manually beforehand!) (default is OFF) | | **PHASAR_ENABLE_PAMM** : STRING | Enable the performance measurement mechanism ('Off', 'Core' or 'Full', default is Off) | | **PHASAR_ENABLE_PIC** : BOOL | Build Position-Independed Code (default is ON) | | **PHASAR_ENABLE_WARNINGS** : BOOL | Enable compiler warnings (default is ON) | diff --git a/include/phasar/Utils/MemoryResource.h b/include/phasar/Utils/MemoryResource.h index d6bf9c5de7..738743f1ca 100644 --- a/include/phasar/Utils/MemoryResource.h +++ b/include/phasar/Utils/MemoryResource.h @@ -2,7 +2,7 @@ /// a workaround here #ifndef HAS_MEMORY_RESOURCE -#if !defined(__has_include) || __has_include() +#if !defined(__has_include) || __has_include() && !defined(__APPLE__) #define HAS_MEMORY_RESOURCE 1 #include #else diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index 4306af47ca..2a1a45add1 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -203,6 +203,10 @@ auto IFDSTaintAnalysis::getNormalFlowFunction(n_t Curr, return transferFlow(Cast, Cast->getOperand(0)); } + if (const auto *Insert = llvm::dyn_cast(Curr)) { + return generateFlow(Insert, Insert->getInsertedValueOperand()); + } + // Otherwise we do not care and leave everything as it is return Identity::getInstance(); } @@ -261,7 +265,6 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, // result should be tainted if (DestFun->getName().equals("$sSS1poiyS2S_SStFZ")) { const auto *CS = llvm::cast(CallSite); - return generateFlowIf(CallSite, [CS](d_t Source) { return ((Source == CS->getArgOperand(1)) || (Source == CS->getArgOperand(3))); diff --git a/test/llvm_swift_test_code/CMakeLists.txt b/test/llvm_swift_test_code/CMakeLists.txt index c80426a04a..c24b2d099c 100644 --- a/test/llvm_swift_test_code/CMakeLists.txt +++ b/test/llvm_swift_test_code/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(linear_constant) +add_subdirectory(taint_analysis) diff --git a/test/llvm_swift_test_code/linear_constant/CMakeLists.txt b/test/llvm_swift_test_code/linear_constant/CMakeLists.txt index 5b7d9aa9db..50553efec8 100644 --- a/test/llvm_swift_test_code/linear_constant/CMakeLists.txt +++ b/test/llvm_swift_test_code/linear_constant/CMakeLists.txt @@ -1,9 +1,15 @@ file(GLOB lca_files *.swift) -set(SWIFT_COMPILE_IR_FLAGS -emit-ir -suppress-warnings -g -parse-as-library -Onone -Xfrontend -disable-llvm-optzns -Xfrontend -disable-swift-specific-llvm-optzns) +set(SWIFT_COMPILE_IR_FLAGS -emit-ir -suppress-warnings -g -parse-as-library -Onone) foreach(TEST_SRC ${lca_files}) get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME_WE) - add_executable(${TEST_SRC_FILE}.ll ${TEST_SRC}) - target_compile_options(${TEST_SRC_FILE}.ll PRIVATE ${SWIFT_COMPILE_IR_FLAGS}) + set(TEST_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${TEST_SRC_FILE}.ll") + add_custom_command( + OUTPUT ${TEST_OUTPUT} + COMMAND swiftc ${SWIFT_COMPILE_IR_FLAGS} -o ${TEST_OUTPUT} ${TEST_SRC} + DEPENDS ${TEST_SRC} + ) + add_custom_target(${TEST_SRC_FILE} DEPENDS ${TEST_OUTPUT}) + add_dependencies(PhasarUnitTests ${TEST_SRC_FILE}) endforeach(TEST_SRC) diff --git a/test/llvm_swift_test_code/linear_constant/call_05.swift b/test/llvm_swift_test_code/linear_constant/call_05.swift index 38519ecd54..f8123ee84e 100644 --- a/test/llvm_swift_test_code/linear_constant/call_05.swift +++ b/test/llvm_swift_test_code/linear_constant/call_05.swift @@ -1,6 +1,6 @@ @main struct MyMain { static func main() { - var i = CommandLine.arguments.count + var i = CommandLine.arguments.count } } diff --git a/test/llvm_swift_test_code/linear_constant/call_11.swift b/test/llvm_swift_test_code/linear_constant/call_11.swift index 3e2f0ea906..2fbc08b1fc 100644 --- a/test/llvm_swift_test_code/linear_constant/call_11.swift +++ b/test/llvm_swift_test_code/linear_constant/call_11.swift @@ -1,10 +1,10 @@ @main struct MyMain { - static func bar(_ b: Int)-> Int { + static func bar(_ b: Int) -> Int { return b } - static func foo(_ a: Int)-> Int { + static func foo(_ a: Int) -> Int { return bar(a) } diff --git a/test/llvm_swift_test_code/linear_constant/for_01.swift b/test/llvm_swift_test_code/linear_constant/for_01.swift index 5f8cea075d..37f1daf9e0 100644 --- a/test/llvm_swift_test_code/linear_constant/for_01.swift +++ b/test/llvm_swift_test_code/linear_constant/for_01.swift @@ -1,10 +1,9 @@ - @main struct MyMain { static func main() { - var a = 0 - for i in 0...9 { - a += i - } + var a = 0 + for i in 0...9 { + a += i + } } } diff --git a/test/llvm_swift_test_code/linear_constant/global_00.swift b/test/llvm_swift_test_code/linear_constant/global_00.swift new file mode 100644 index 0000000000..63312b84de --- /dev/null +++ b/test/llvm_swift_test_code/linear_constant/global_00.swift @@ -0,0 +1,7 @@ +var y = 42 +@main +struct MyMain { + static func main() { + y += 1 + } +} diff --git a/test/llvm_swift_test_code/linear_constant/global_01.swift b/test/llvm_swift_test_code/linear_constant/global_01.swift index 29d55a5249..d9391b53aa 100644 --- a/test/llvm_swift_test_code/linear_constant/global_01.swift +++ b/test/llvm_swift_test_code/linear_constant/global_01.swift @@ -5,8 +5,8 @@ var g3 = 3.1415 @main struct MyMain { static func main() { - var i = 666 - g1 = 42 - g2 = g1 + var i = 666 + g1 = 42 + g2 = g1 } } diff --git a/test/llvm_swift_test_code/linear_constant/global_02.swift b/test/llvm_swift_test_code/linear_constant/global_02.swift index e4735221c3..381789eac0 100644 --- a/test/llvm_swift_test_code/linear_constant/global_02.swift +++ b/test/llvm_swift_test_code/linear_constant/global_02.swift @@ -3,8 +3,8 @@ var g = 10 @main struct MyMain { static func main() { - var i = g - i -= 20 - g = i + var i = g + i -= 20 + g = i } } diff --git a/test/llvm_swift_test_code/linear_constant/global_03.swift b/test/llvm_swift_test_code/linear_constant/global_03.swift index 037b6422e0..552bbececd 100644 --- a/test/llvm_swift_test_code/linear_constant/global_03.swift +++ b/test/llvm_swift_test_code/linear_constant/global_03.swift @@ -3,12 +3,12 @@ var g = 0 @main struct MyMain { - static func foo() { - g += 1 - } + static func foo() { + g += 1 + } static func main() { - var i = 42 - g += 1 - foo() + var i = 42 + g += 1 + foo() } } diff --git a/test/llvm_swift_test_code/linear_constant/global_04.swift b/test/llvm_swift_test_code/linear_constant/global_04.swift index 8a604e8a48..1b03901352 100644 --- a/test/llvm_swift_test_code/linear_constant/global_04.swift +++ b/test/llvm_swift_test_code/linear_constant/global_04.swift @@ -3,12 +3,12 @@ var g = 0 @main struct MyMain { - static func foo (_ a: Int)-> Int { - return a + 1 - } + static func foo(_ a: Int) -> Int { + return a + 1 + } static func main() { - g += 1 - var i = foo(g) + g += 1 + var i = foo(g) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_06.swift b/test/llvm_swift_test_code/linear_constant/global_06.swift index b08ad41f19..22faa3023d 100644 --- a/test/llvm_swift_test_code/linear_constant/global_06.swift +++ b/test/llvm_swift_test_code/linear_constant/global_06.swift @@ -3,12 +3,12 @@ var g = 0 @main struct MyMain { - static func foo ()-> Int { - return g + 1 - } + static func foo() -> Int { + return g + 1 + } static func main() { - g += 1 - var i = foo() + g += 1 + var i = foo() } } diff --git a/test/llvm_swift_test_code/linear_constant/global_07.swift b/test/llvm_swift_test_code/linear_constant/global_07.swift index 9619a15524..e14deb0f8a 100644 --- a/test/llvm_swift_test_code/linear_constant/global_07.swift +++ b/test/llvm_swift_test_code/linear_constant/global_07.swift @@ -3,21 +3,21 @@ var g = 0 @main struct MyMain { - static func foo (_ a: Int)-> Int { - var x = a - x += g - return x - } + static func foo(_ a: Int) -> Int { + var x = a + x += g + return x + } - static func bar (_ b: Int)-> Int { - g += 1 - return b + 1 - } + static func bar(_ b: Int) -> Int { + g += 1 + return b + 1 + } static func main() { - g += 1 - var i = 0 - i = foo(10) - i = bar(3) + g += 1 + var i = 0 + i = foo(10) + i = bar(3) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_08.swift b/test/llvm_swift_test_code/linear_constant/global_08.swift index e0ea7abcef..e47e091540 100644 --- a/test/llvm_swift_test_code/linear_constant/global_08.swift +++ b/test/llvm_swift_test_code/linear_constant/global_08.swift @@ -3,21 +3,21 @@ var g = 1 @main struct MyMain { - static func baz (_ c: Int)-> Int { - return g + c - } + static func baz(_ c: Int) -> Int { + return g + c + } - static func bar (_ b: Int)-> Int { - return baz(b + 1) - } + static func bar(_ b: Int) -> Int { + return baz(b + 1) + } - static func foo (_ a: Int)-> Int { - return bar(a + 1) - } + static func foo(_ a: Int) -> Int { + return bar(a + 1) + } static func main() { - g += 1 - var i = 0 - i = foo(1) + g += 1 + var i = 0 + i = foo(1) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_09.swift b/test/llvm_swift_test_code/linear_constant/global_09.swift index c7cded5155..a422b53a16 100644 --- a/test/llvm_swift_test_code/linear_constant/global_09.swift +++ b/test/llvm_swift_test_code/linear_constant/global_09.swift @@ -3,26 +3,26 @@ var g1 = 1 @main struct MyMain { - static func baz (_ c: Int)-> Int { - return c + 3 - } + static func baz(_ c: Int) -> Int { + return c + 3 + } - static func bar (_ b: Int)-> Int { - g1 += 1 - return b + 1 - } + static func bar(_ b: Int) -> Int { + g1 += 1 + return b + 1 + } - static func foo (_ a: Int)-> Int { - var x = a - x+=g1 - return x - } + static func foo(_ a: Int) -> Int { + var x = a + x += g1 + return x + } static func main() { - g1 += 1 - var i = 0 - i = foo(10) - i = bar(3) - i = baz(39) + g1 += 1 + var i = 0 + i = foo(10) + i = bar(3) + i = baz(39) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_11.swift b/test/llvm_swift_test_code/linear_constant/global_11.swift index 10064c04c6..64b043d2ea 100644 --- a/test/llvm_swift_test_code/linear_constant/global_11.swift +++ b/test/llvm_swift_test_code/linear_constant/global_11.swift @@ -4,15 +4,14 @@ var g2 = 9001 @main struct MyMain { - static func foo (_ x: Int)-> Int { - var a = x - a = a + 1 - return a - } - + static func foo(_ x: Int) -> Int { + var a = x + a = a + 1 + return a + } static func main() { - var a = 13 - a = foo(a) + var a = 13 + a = foo(a) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_12.swift b/test/llvm_swift_test_code/linear_constant/global_12.swift index 0b8742f538..428ed727ca 100644 --- a/test/llvm_swift_test_code/linear_constant/global_12.swift +++ b/test/llvm_swift_test_code/linear_constant/global_12.swift @@ -7,14 +7,14 @@ var g = 0 @main struct MyMain { - static func foo (_ x: Int)-> Int { - var a = x - a = a + 1 - return a - } + static func foo(_ x: Int) -> Int { + var a = x + a = a + 1 + return a + } static func main() { - var a = g - a = foo(a) + var a = g + a = foo(a) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_13.swift b/test/llvm_swift_test_code/linear_constant/global_13.swift index 566482fece..18ce061982 100644 --- a/test/llvm_swift_test_code/linear_constant/global_13.swift +++ b/test/llvm_swift_test_code/linear_constant/global_13.swift @@ -10,14 +10,14 @@ var g = 0 @main struct MyMain { - static func foo (_ x: Int)-> Int { - var a = x - a = a + 1 - return a - } + static func foo(_ x: Int) -> Int { + var a = x + a = a + 1 + return a + } static func main() { - var a = g - var b = foo(a) + var a = g + var b = foo(a) } } diff --git a/test/llvm_swift_test_code/linear_constant/global_14.swift b/test/llvm_swift_test_code/linear_constant/global_14.swift index 0d0d59d30f..42d9a76a9a 100644 --- a/test/llvm_swift_test_code/linear_constant/global_14.swift +++ b/test/llvm_swift_test_code/linear_constant/global_14.swift @@ -1,23 +1,23 @@ var g = 0 struct X { - init() { - g = 1024 - } + init() { + g = 1024 + } } var v = X() @main struct MyMain { - static func foo (_ x: Int)-> Int { - var a = x - a = a + 1 - return a - } + static func foo(_ x: Int) -> Int { + var a = x + a = a + 1 + return a + } - static func main() { - var a = g - a = foo(a) - } + static func main() { + var a = g + a = foo(a) + } } diff --git a/test/llvm_swift_test_code/linear_constant/global_15.swift b/test/llvm_swift_test_code/linear_constant/global_15.swift index d0dec9612b..f07ee57f89 100644 --- a/test/llvm_swift_test_code/linear_constant/global_15.swift +++ b/test/llvm_swift_test_code/linear_constant/global_15.swift @@ -2,18 +2,18 @@ var g1 = 0 var g2 = 99 struct X { - init() { - g1 = 1024 - } + init() { + g1 = 1024 + } } class Y { - init() { - g2 = g2 + 1 - } - deinit { - g1 = g2 + 13 - } + init() { + g2 = g2 + 1 + } + deinit { + g1 = g2 + 13 + } } var v = X() @@ -21,16 +21,16 @@ var w = Y() @main struct MyMain { - static func foo (_ x: Int)-> Int { - var a = x - a = a + 1 - return a - } + static func foo(_ x: Int) -> Int { + var a = x + a = a + 1 + return a + } - static func main() { - var a = g1 - var b = g2 - a = foo(a) - a = a + 30 - } + static func main() { + var a = g1 + var b = g2 + a = foo(a) + a = a + 30 + } } diff --git a/test/llvm_swift_test_code/linear_constant/global_16.swift b/test/llvm_swift_test_code/linear_constant/global_16.swift index ecee13f83b..678575cf9e 100644 --- a/test/llvm_swift_test_code/linear_constant/global_16.swift +++ b/test/llvm_swift_test_code/linear_constant/global_16.swift @@ -3,15 +3,14 @@ var g = 15 @main struct MyMain { - static func foo (_ x: Int)-> Int { - var a = x - a = a + 1 - return a - } - + static func foo(_ x: Int) -> Int { + var a = x + a = a + 1 + return a + } static func main() { - var a = g - a = foo(a) + var a = g + a = foo(a) } } diff --git a/test/llvm_swift_test_code/linear_constant/overflow_add.swift b/test/llvm_swift_test_code/linear_constant/overflow_add.swift index afd67ef122..26c2668442 100644 --- a/test/llvm_swift_test_code/linear_constant/overflow_add.swift +++ b/test/llvm_swift_test_code/linear_constant/overflow_add.swift @@ -5,7 +5,7 @@ struct MyMain { } static func wrapper(_ x: UInt64) -> UInt64 { - var i: UInt64 = 18446744073709551614 + var i: UInt64 = 18_446_744_073_709_551_614 var j: UInt64 = i &+ 8 return j } diff --git a/test/llvm_swift_test_code/linear_constant/recursion_01.swift b/test/llvm_swift_test_code/linear_constant/recursion_01.swift index 68f0fd1b55..b5f30eeb40 100644 --- a/test/llvm_swift_test_code/linear_constant/recursion_01.swift +++ b/test/llvm_swift_test_code/linear_constant/recursion_01.swift @@ -6,9 +6,9 @@ struct MyMain { } static func decrement(_ i: Int) -> Int { - if(cond) { - return decrement(i - 1) - } - return -1 + if cond { + return decrement(i - 1) + } + return -1 } } diff --git a/test/llvm_swift_test_code/linear_constant/recursion_02.swift b/test/llvm_swift_test_code/linear_constant/recursion_02.swift index f07eaa45fc..58df4579d9 100644 --- a/test/llvm_swift_test_code/linear_constant/recursion_02.swift +++ b/test/llvm_swift_test_code/linear_constant/recursion_02.swift @@ -5,9 +5,9 @@ struct MyMain { } static func fac(_ i: Int) -> Int { - if(i == 0) { - return 1 - } - return i * fac(i-1) + if i == 0 { + return 1 + } + return i * fac(i - 1) } } diff --git a/test/llvm_swift_test_code/linear_constant/recursion_03.swift b/test/llvm_swift_test_code/linear_constant/recursion_03.swift index 4295584051..3c86839a2d 100644 --- a/test/llvm_swift_test_code/linear_constant/recursion_03.swift +++ b/test/llvm_swift_test_code/linear_constant/recursion_03.swift @@ -5,9 +5,9 @@ struct MyMain { } static func foo(_ i: Int) -> Int { - if(i == 0) { - return 1 - } - return foo(i-1) + if i == 0 { + return 1 + } + return foo(i - 1) } } diff --git a/test/llvm_swift_test_code/linear_constant/while_01.swift b/test/llvm_swift_test_code/linear_constant/while_01.swift index 24173d5583..a3a73943b8 100644 --- a/test/llvm_swift_test_code/linear_constant/while_01.swift +++ b/test/llvm_swift_test_code/linear_constant/while_01.swift @@ -2,8 +2,8 @@ struct MyMain { static func main() { var i = 42 - while ( i > 0) { - i = i + 2 + while i > 0 { + i = i + 2 } } } diff --git a/test/llvm_swift_test_code/linear_constant/while_03.swift b/test/llvm_swift_test_code/linear_constant/while_03.swift index e9fb52189e..17942a5fd1 100644 --- a/test/llvm_swift_test_code/linear_constant/while_03.swift +++ b/test/llvm_swift_test_code/linear_constant/while_03.swift @@ -2,8 +2,8 @@ struct MyMain { static func main() { var i = 42 - while ( i > 0) { - i = i + 2 + while i > 0 { + i = i + 2 } var a = i a = 13 diff --git a/test/llvm_swift_test_code/linear_constant/while_04.swift b/test/llvm_swift_test_code/linear_constant/while_04.swift index 2f89cdfd44..8b5f470733 100644 --- a/test/llvm_swift_test_code/linear_constant/while_04.swift +++ b/test/llvm_swift_test_code/linear_constant/while_04.swift @@ -2,9 +2,9 @@ struct MyMain { static func main() { var i = 42 - while ( i > 0) { - var a = 0 - i = i + 2 + while i > 0 { + var a = 0 + i = i + 2 } } } diff --git a/test/llvm_swift_test_code/taint_analysis/CMakeLists.txt b/test/llvm_swift_test_code/taint_analysis/CMakeLists.txt new file mode 100644 index 0000000000..78f6dbaceb --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/CMakeLists.txt @@ -0,0 +1,15 @@ +file(GLOB taint_files *.swift) + +set(SWIFT_COMPILE_IR_FLAGS -emit-ir -suppress-warnings -g -parse-as-library -Onone) + +foreach(TEST_SRC ${taint_files}) + get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME_WE) + set(TEST_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${TEST_SRC_FILE}.ll") + add_custom_command( + OUTPUT ${TEST_OUTPUT} + COMMAND swiftc ${SWIFT_COMPILE_IR_FLAGS} -o ${TEST_OUTPUT} ${TEST_SRC} + DEPENDS ${TEST_SRC} + ) + add_custom_target(${TEST_SRC_FILE} DEPENDS ${TEST_OUTPUT}) + add_dependencies(PhasarUnitTests ${TEST_SRC_FILE}) +endforeach(TEST_SRC) diff --git a/test/llvm_swift_test_code/taint_analysis/taint_01.swift b/test/llvm_swift_test_code/taint_analysis/taint_01.swift new file mode 100644 index 0000000000..83f126d4a3 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_01.swift @@ -0,0 +1,13 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +@main +struct MyMain { + static func main() { + var a = source() + sink(a) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_02.swift b/test/llvm_swift_test_code/taint_analysis/taint_02.swift new file mode 100644 index 0000000000..39569bbe0a --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_02.swift @@ -0,0 +1,14 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: [String]) + +@main +struct MyMain { + static func main() { + // We changed this from the original C++ test + // which checked argc. + sink(CommandLine.arguments) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_03.swift b/test/llvm_swift_test_code/taint_analysis/taint_03.swift new file mode 100644 index 0000000000..ff171729fb --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_03.swift @@ -0,0 +1,13 @@ +@main +struct MyMain { + static func source() -> Int { + return 0 + } + static func sink(_ p: Int) { + print(p) + } + static func main() { + var a = source() + sink(a) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_04.swift b/test/llvm_swift_test_code/taint_analysis/taint_04.swift new file mode 100644 index 0000000000..c62bb8edf8 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_04.swift @@ -0,0 +1,15 @@ +@main +struct MyMain { + static func source() -> Int { + return 0 + } + static func sink(_ p: Int) { + print(p) + } + static func main() { + var a = source() + sink(a) + var b = a + sink(b) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_05.swift b/test/llvm_swift_test_code/taint_analysis/taint_05.swift new file mode 100644 index 0000000000..dc56fe6807 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_05.swift @@ -0,0 +1,13 @@ +@main +struct MyMain { + static func source() -> Int { + return 0 + } + static func sink(_ p: Int) { + var b = p + } + static func main() { + var a = source() + sink(a) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_06.swift b/test/llvm_swift_test_code/taint_analysis/taint_06.swift new file mode 100644 index 0000000000..e4957dca69 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_06.swift @@ -0,0 +1,12 @@ +@main +struct MyMain { + static func source() -> Int { + return 0 + } + static func sink(_ p: [String]) { + print(p) + } + static func main() { + sink(CommandLine.arguments) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_04.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_04.swift new file mode 100644 index 0000000000..39ddc4aea8 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_04.swift @@ -0,0 +1,27 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data = 0 // Swift does not support uninitilized variables as given in the C++ test case + do { + var s = S(0) + try s.test() + data = source() + } catch { + + } + sink(data) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_05.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_05.swift new file mode 100644 index 0000000000..3a3663fbfc --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_05.swift @@ -0,0 +1,27 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data = 0 + do { + var s = S(0) + try s.test() + + } catch { + data = source() + } + sink(data) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_06.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_06.swift new file mode 100644 index 0000000000..3e4135847b --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_06.swift @@ -0,0 +1,26 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data = source() + do { + var s = S(0) + try s.test() + sink(data) + } catch { + + } + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_07.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_07.swift new file mode 100644 index 0000000000..d00c68fed5 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_07.swift @@ -0,0 +1,25 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data = source() + do { + var s = S(0) + try s.test() + } catch { + sink(data) + } + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_08.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_08.swift new file mode 100644 index 0000000000..d417fef0c1 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_08.swift @@ -0,0 +1,30 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data = 0 // Swift does not support uninitilized variables as given in the C++ test case + do { + var s = S(0) + try s.test() + do { + data = source() + try s.test() + } catch {} + } catch { + + } + sink(data) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_09.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_09.swift new file mode 100644 index 0000000000..662a9d7272 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_09.swift @@ -0,0 +1,32 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data: Int = 0 // Swift does not support uninitilized variables as given in the C++ test case + do { + var s = S(0) + try s.test() + do { + var s = S(0) + try s.test() + } catch { + data = source() + } + } catch { + + } + sink(data) + } +} diff --git a/test/llvm_swift_test_code/taint_analysis/taint_exception_10.swift b/test/llvm_swift_test_code/taint_analysis/taint_exception_10.swift new file mode 100644 index 0000000000..d8847fb624 --- /dev/null +++ b/test/llvm_swift_test_code/taint_analysis/taint_exception_10.swift @@ -0,0 +1,32 @@ +@_silgen_name("source") +func source() -> Int + +@_silgen_name("sink") +func sink(_ p: Int) + +struct S { + var data: Int + init(_ data: Int) { + self.data = data + } + func test() throws {} +} +@main +struct MyMain { + static func main() { + var data: Int = 0 // Swift does not support uninitilized variables as given in the C++ test case + do { + var s = S(0) + try s.test() + } catch { + data = source() + } + do { + var s = S(0) + try s.test() + } catch { + sink(data) + } + + } +} diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt index 23d61519be..5730f8555b 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt @@ -13,19 +13,6 @@ if(PHASAR_BUILD_OPENSSL_TS_UNITTESTS) IDEExtendedTaintAnalysisTest.cpp IDEGeneralizedLCATest.cpp ) -elseif(BUILD_SWIFT_TESTS) - set(IfdsIdeProblemSources - IFDSConstAnalysisTest.cpp - IFDSTaintAnalysisTest.cpp - IDEInstInteractionAnalysisTest.cpp - IDELinearConstantAnalysisTest.cpp - IDELinearConstantAnalysis_DotTest.cpp - IFDSUninitializedVariablesTest.cpp - IDEGeneralizedLCATest.cpp - IDEExtendedTaintAnalysisTest.cpp - IDETSAnalysisFileIOTest.cpp - IDELinearConstantAnalysisSwiftTest.cpp - ) else() set(IfdsIdeProblemSources IFDSConstAnalysisTest.cpp @@ -40,6 +27,14 @@ elseif(BUILD_SWIFT_TESTS) ) endif(PHASAR_BUILD_OPENSSL_TS_UNITTESTS) +if(BUILD_SWIFT_TESTS) +set(SwiftTests + IDELinearConstantAnalysisSwiftTest.cpp + IFDSTaintAnalysisSwiftTest.cpp +) +list(APPEND IfdsIdeProblemSources ${SwiftTests}) +endif(BUILD_SWIFT_TESTS) + test_require_config_file("DOTGraphConfig.json") foreach(TEST_SRC ${IfdsIdeProblemSources}) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisSwiftTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisSwiftTest.cpp new file mode 100644 index 0000000000..5e184ee3f1 --- /dev/null +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisSwiftTest.cpp @@ -0,0 +1,233 @@ +#include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h" +#include "phasar/PhasarLLVM/HelperAnalyses.h" +#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" +#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" +#include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" +#include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" +#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" + +#include + +using namespace std; +using namespace psr; + +/* ============== TEST FIXTURE ============== */ + +class IFDSTaintAnalysisTest : public ::testing::Test { +protected: + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SWIFT_SUBFOLDER("taint_analysis/"); + const std::vector EntryPoints = {"main"}; + + std::optional HA; + + std::optional TaintProblem; + std::optional TSF; + + IFDSTaintAnalysisTest() = default; + ~IFDSTaintAnalysisTest() override = default; + + void initialize(const llvm::Twine &IRFile) { + HA.emplace(IRFile, EntryPoints); + LLVMTaintConfig::TaintDescriptionCallBackTy SourceCB = + [](const llvm::Instruction *Inst) { + std::set Ret; + if (const auto *Call = llvm::dyn_cast(Inst); + Call && Call->getCalledFunction() && + // Swift provides CLI arguments through a method call to + // this method to the program. + // TODO: handle this in the analysis, like this we need + // to include the method explicitly in every taint config + // which is not ideal + (Call->getCalledFunction()->getName() == "source" || + Call->getCalledFunction()->getName().contains_insensitive( + "MyMainV6sourceSi") || + Call->getCalledFunction()->getName().equals( + "$ss11CommandLineO9argumentsSaySSGvgZ"))) { + Ret.insert(Call); + } + return Ret; + }; + LLVMTaintConfig::TaintDescriptionCallBackTy SinkCB = + [](const llvm::Instruction *Inst) { + std::set Ret; + if (const auto *Call = llvm::dyn_cast(Inst); + Call && Call->getCalledFunction() && + // Swift generates different function names whether a function is + // externaly declared or actually present in the code + (Call->getCalledFunction()->getName() == "sink" || + Call->getCalledFunction()->getName().contains_insensitive( + "MyMainV4sinkyySiFZ"))) { + assert(Call->arg_size() > 0); + Ret.insert(Call->getArgOperand(0)); + } + return Ret; + }; + TSF.emplace(std::move(SourceCB), std::move(SinkCB)); + TaintProblem = + createAnalysisProblem(*HA, &*TSF, EntryPoints); + } + + void SetUp() override { ValueAnnotationPass::resetValueID(); } + + void TearDown() override {} + + void compareResults(map> &GroundTruth) { + // std::map> Leaks; + map> FoundLeaks; + for (const auto &Leak : TaintProblem->Leaks) { + int SinkId = stoi(getMetaDataID(Leak.first)); + set LeakedValueIds; + for (const auto *LV : Leak.second) { + LeakedValueIds.insert(getMetaDataID(LV)); + } + FoundLeaks.insert(make_pair(SinkId, LeakedValueIds)); + } + EXPECT_EQ(FoundLeaks, GroundTruth); + } +}; // Test Fixture + +TEST_F(IFDSTaintAnalysisTest, TaintTest_01) { + initialize({PathToLlFiles + "taint_01.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + // sink --> taint + GroundTruth[23] = set{"20"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { + GTEST_SKIP() << "Swift taint tests with CLI arguments are not supported yet"; + initialize({PathToLlFiles + "taint_02.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[15] = set{"14"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { + + initialize({PathToLlFiles + "taint_03.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[91] = set{"88"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { + initialize({PathToLlFiles + "taint_04.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + // This test case is a bit different than the C++ one + // the assignemt a = b is ignored in Swift-based + // LLVM IR and thus the same value is tainted for + // both sink calls + GroundTruth[95] = set{"92"}; + GroundTruth[100] = set{"92"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { + initialize({PathToLlFiles + "taint_05.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[42] = set{"39"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_06) { + GTEST_SKIP() << "Swift taint tests with CLI arguments are not supported yet"; + initialize({PathToLlFiles + "taint_06.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[5] = set{"main.0"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_04.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[77] = set{"72"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_05.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + + map> GroundTruth; + GroundTruth[33] = set{"32"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_06.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[15] = set{"14"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_07.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[31] = set{"30"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_08.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[33] = set{"32"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_09.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[64] = set{"63"}; + compareResults(GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { + GTEST_SKIP() << "Swift taint tests with Exceptions are not supported yet"; + initialize({PathToLlFiles + "taint_exception_10.ll"}); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + map> GroundTruth; + GroundTruth[62] = set{"61"}; + compareResults(GroundTruth); +} + +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + return RUN_ALL_TESTS(); +}