|  | // Copyright Microsoft and CHERIoT Contributors. | 
|  | // SPDX-License-Identifier: MIT | 
|  |  | 
|  | #define TEST_NAME "Compartment calls (inner compartment)" | 
|  | #include "compartment_calls.h" | 
|  | #include "tests.hh" | 
|  | #include <cheri.hh> | 
|  | #include <errno.h> | 
|  | #include <tuple> | 
|  |  | 
|  | using namespace CHERI; | 
|  |  | 
|  | std::tuple expectedArguments = {ConstantValue, | 
|  | ConstantValue, | 
|  | ConstantValue, | 
|  | ConstantValue, | 
|  | ConstantValue, | 
|  | ConstantValue, | 
|  | ConstantValue}; | 
|  |  | 
|  | template<typename T, size_t I = std::tuple_size_v<T> - 1> | 
|  | __attribute__((always_inline)) void check_tuple(T &args) | 
|  | { | 
|  | auto arg      = std::get<I>(args); | 
|  | auto expected = std::get<I>(expectedArguments); | 
|  | TEST( | 
|  | arg == expected, "argument == {}, expected value == {}", arg, expected); | 
|  | if constexpr (I > 0) | 
|  | { | 
|  | check_tuple<T, I - 1>(args); | 
|  | } | 
|  | } | 
|  | template<typename... Args> | 
|  | __attribute__((always_inline)) void verify_arguments(Args... args) | 
|  | { | 
|  | auto a = std::forward_as_tuple(args...); | 
|  | check_tuple(a); | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int x0) | 
|  | { | 
|  | debug_log("One argument"); | 
|  | verify_arguments(x0); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int x0, int x1) | 
|  | { | 
|  | debug_log("Two arguments"); | 
|  | verify_arguments(x0, x1); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int x0, int x1, const int *x2) | 
|  | { | 
|  | debug_log("Three arguments"); | 
|  | verify_arguments(x0, x1, *x2); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int x0, int x1, const int *x2, int x3) | 
|  | { | 
|  | debug_log("Four arguments"); | 
|  | verify_arguments(x0, x1, *x2, x3); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int x0, int x1, const int *x2, int x3, const int *x4) | 
|  | { | 
|  | debug_log("Five arguments"); | 
|  | verify_arguments(x0, x1, *x2, x3, *x4); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int        x0, | 
|  | int        x1, | 
|  | const int *x2, | 
|  | int        x3, | 
|  | const int *x4, | 
|  | int        x5) | 
|  | { | 
|  | debug_log("Six arguments"); | 
|  | verify_arguments(x0, x1, *x2, x3, *x4, x5); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int compartment_call_inner(int        x0, | 
|  | int        x1, | 
|  | const int *x2, | 
|  | int        x3, | 
|  | const int *x4, | 
|  | int        x5, | 
|  | int        x6) | 
|  | { | 
|  | debug_log("Seven arguments"); | 
|  | verify_arguments(x0, x1, *x2, x3, *x4, x5, x6); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void test_incorrect_export_table(__cheri_callback void (*fn)(), | 
|  | bool *outTestFailed) | 
|  | { | 
|  | /* | 
|  | * Trigger a cross-compartment call with an invalid export entry. | 
|  | */ | 
|  |  | 
|  | debug_log("test an incorrect export table entry"); | 
|  |  | 
|  | *outTestFailed = true; | 
|  |  | 
|  | fn(); | 
|  |  | 
|  | *outTestFailed = false; | 
|  | } |