diff --git a/.gitignore b/.gitignore index 1cc71e473..409614f8f 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 b9eb75366..a915c2248 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 8e27e018a..4f2844e69 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 d6bf9c5de..738743f1c 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 4306af47c..2a1a45add 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 c80426a04..c24b2d099 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 5b7d9aa9d..50553efec 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 38519ecd5..f8123ee84 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 3e2f0ea90..2fbc08b1f 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 5f8cea075..37f1daf9e 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 000000000..63312b84d --- /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 29d55a524..d9391b53a 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 e4735221c..381789eac 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 037b6422e..552bbecec 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 8a604e8a4..1b0390135 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 b08ad41f1..22faa3023 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 9619a1552..e14deb0f8 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 e0ea7abce..e47e09154 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 c7cded515..a422b53a1 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 10064c04c..64b043d2e 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 0b8742f53..428ed727c 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 566482fec..18ce06198 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 0d0d59d30..42d9a76a9 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 d0dec9612..f07ee57f8 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 ecee13f83..678575cf9 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 afd67ef12..26c266844 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 68f0fd1b5..b5f30eeb4 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 f07eaa45f..58df4579d 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 429558405..3c86839a2 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 24173d558..a3a73943b 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 e9fb52189..17942a5fd 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 2f89cdfd4..8b5f47073 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 000000000..78f6dbace --- /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 000000000..83f126d4a --- /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 000000000..39569bbe0 --- /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 000000000..ff171729f --- /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 000000000..c62bb8edf --- /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 000000000..dc56fe680 --- /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 000000000..e4957dca6 --- /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 000000000..39ddc4aea --- /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 000000000..3a3663fbf --- /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 000000000..3e4135847 --- /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 000000000..d00c68fed --- /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 000000000..d417fef0c --- /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 000000000..662a9d727 --- /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 000000000..d8847fb62 --- /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 23d61519b..5730f8555 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 000000000..5e184ee3f --- /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(); +}