tests: catch up with compiler warnings
diff --git a/tests/allocator-test.cc b/tests/allocator-test.cc index 98de832..8a5887d 100644 --- a/tests/allocator-test.cc +++ b/tests/allocator-test.cc
@@ -101,8 +101,7 @@ "Checked that all allocations have been deallocated ({} of {})", static_cast<int>(i), static_cast<int>(TestIterations)); - Timeout t{1}; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to sleep"); } allocations.clear(); } @@ -122,8 +121,7 @@ freeStart.wait(0); // One extra sleep to make sure that we're really in the blocking // sleep. - Timeout t{2}; - thread_sleep(&t); + TEST(sleep(2) >= 0, "Failed to sleep"); debug_log( "Deallocation thread resuming, freeing pool of allocations"); // Free all of the allocations to make space. @@ -131,7 +129,9 @@ { if (allocation != nullptr) { - heap_free(MALLOC_CAPABILITY, allocation); + TEST_EQUAL(heap_free(MALLOC_CAPABILITY, allocation), + 0, + "Could not free allocation"); } } // Notify the parent thread that we're done. @@ -426,6 +426,7 @@ void test_hazards() { + int sleeps; debug_log("Before allocating, quota left: {}", heap_quota_remaining(SECOND_HEAP)); Timeout longTimeout{1000}; @@ -446,21 +447,22 @@ // Exiting this task will cause this closure to be freed, which // will collect dangling hazard pointers. Wait for long enough for // the heap check to work. - t = 1; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to sleep"); }); // Allow the async function to run and establish hazards + sleeps = 0; while (state.load() != 1) { - Timeout t{1}; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to sleep"); + TEST(sleeps++ < 100, + "Background thread failed to establish hazards"); } debug_log("Before freeing, quota left: {}", heap_quota_remaining(SECOND_HEAP)); - heap_free(SECOND_HEAP, ptr); + TEST_EQUAL(heap_free(SECOND_HEAP, ptr), 0, "First free failed"); debug_log("After free 1, quota left: {}", heap_quota_remaining(SECOND_HEAP)); - heap_free(SECOND_HEAP, ptr2); + TEST_EQUAL(heap_free(SECOND_HEAP, ptr2), 0, "Second free failed"); debug_log("After free 2, quota left: {}", heap_quota_remaining(SECOND_HEAP)); TEST(Capability{ptr}.is_valid(), @@ -471,21 +473,21 @@ ptr2); state = 2; // Yield to allow the hazards to be dropped. - Timeout t{1}; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to yield to drop hazards"); // Try a double free. This may logically succeed, but should not affect // our quota. - heap_free(SECOND_HEAP, ptr); + TEST_EQUAL(heap_free(SECOND_HEAP, ptr), + -EPERM, + "Attempt to free freed but hazarded pointer not EPERM"); // Sleep again to make sure that the lambda from our async is gone. // The logs may make it take more than one quantum in debug builds. // The next test requires all memory allocated from the malloc // capability to be freed before it starts. - int sleeps = 0; + sleeps = 0; while (heap_quota_remaining(MALLOC_CAPABILITY) < MALLOC_QUOTA && heap_quota_remaining(MALLOC_CAPABILITY) > 0) { - Timeout t{1}; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to sleep"); TEST(sleeps++ < 100, "Sleeping for too long waiting for async lambda to be freed"); } @@ -712,7 +714,7 @@ TEST(ret == 0, "Freeing array failed: {}", ret); test_blocking_allocator(); - heap_quarantine_empty(); + TEST_EQUAL(heap_quarantine_empty(), 0, "Could not flush quarantine"); test_revoke(); test_fuzz(); allocations.clear();
diff --git a/tests/compartment_calls-test.cc b/tests/compartment_calls-test.cc index a8ed1ee..d8c8368 100644 --- a/tests/compartment_calls-test.cc +++ b/tests/compartment_calls-test.cc
@@ -68,7 +68,10 @@ test_number_of_arguments(); - test_incorrect_export_table(nullptr, &outTestFailed); + TEST_EQUAL( + test_incorrect_export_table(nullptr, &outTestFailed), + 0, + "Test incorrect entry point without error handler bad return value"); TEST(outTestFailed == false, "Test incorrect entry point without error handler failed"); return 0;
diff --git a/tests/compartment_calls.h b/tests/compartment_calls.h index b740f31..6e4103d 100644 --- a/tests/compartment_calls.h +++ b/tests/compartment_calls.h
@@ -38,11 +38,10 @@ const int *x4, int x5, int x6); -__cheri_compartment("compartment_calls_inner") void test_incorrect_export_table( +__cheri_compartment("compartment_calls_inner") int test_incorrect_export_table( __cheri_callback void (*fn)(), bool *outTestFailed); __cheri_compartment( "compartment_calls_inner_with_" "handler") int test_incorrect_export_table_with_handler(__cheri_callback int (*fn)()); -__cheri_compartment("compartment_calls_outer") void compartment_call_outer(); constexpr int ConstantValue = 0x41414141;
diff --git a/tests/compartment_calls_inner.cc b/tests/compartment_calls_inner.cc index 43fd9d0..efd6138 100644 --- a/tests/compartment_calls_inner.cc +++ b/tests/compartment_calls_inner.cc
@@ -97,8 +97,8 @@ return 0; } -void test_incorrect_export_table(__cheri_callback void (*fn)(), - bool *outTestFailed) +int test_incorrect_export_table(__cheri_callback void (*fn)(), + bool *outTestFailed) { /* * Trigger a cross-compartment call with an invalid export entry. @@ -111,4 +111,6 @@ fn(); *outTestFailed = false; + + return 0; }
diff --git a/tests/crash_recovery-test.cc b/tests/crash_recovery-test.cc index cc67b24..1de2977 100644 --- a/tests/crash_recovery-test.cc +++ b/tests/crash_recovery-test.cc
@@ -49,7 +49,7 @@ int test_crash_recovery() { debug_log("Calling crashy compartment indirectly"); - test_crash_recovery_outer(0); + TEST_EQUAL(test_crash_recovery_outer(0), 0, "Indirect crash failed"); check_stack(); TEST(crashes == 0, "Ran crash handler for outer compartment"); debug_log("Compartment with no error handler returned normally after "
diff --git a/tests/crash_recovery.h b/tests/crash_recovery.h index 9c2c7bd..ebbdb56 100644 --- a/tests/crash_recovery.h +++ b/tests/crash_recovery.h
@@ -6,7 +6,7 @@ __cheri_compartment("crash_recovery_inner") void *test_crash_recovery_inner( int); -__cheri_compartment("crash_recovery_outer") void test_crash_recovery_outer(int); +__cheri_compartment("crash_recovery_outer") int test_crash_recovery_outer(int); /** * Checks that the stack is entirely full of zeroes below the current stack
diff --git a/tests/crash_recovery_outer.cc b/tests/crash_recovery_outer.cc index 9d3513d..6b59b7e 100644 --- a/tests/crash_recovery_outer.cc +++ b/tests/crash_recovery_outer.cc
@@ -6,7 +6,7 @@ #include <cheri.hh> #include <errno.h> -void test_crash_recovery_outer(int) +int test_crash_recovery_outer(int) { debug_log( "Calling crashy compartment from compartment with no error handler"); @@ -19,4 +19,5 @@ debug_log("Calling crashy compartment returned to compartment with no " "error handler. Return value: {}", ret); + return 0; }
diff --git a/tests/futex-test.cc b/tests/futex-test.cc index 4abfe6c..433f110 100644 --- a/tests/futex-test.cc +++ b/tests/futex-test.cc
@@ -25,6 +25,7 @@ { static uint32_t futex; int ret; + int sleeps; // Make sure that waking a futex with no sleepers doesn't crash! ret = futex_wake(&futex, 1); TEST(ret == 0, "Waking a futex with no sleepers should return 0"); @@ -32,7 +33,7 @@ // has been set to 1. async([]() { futex = 1; - futex_wake(&futex, 1); + (void)futex_wake(&futex, 1); }); debug_log("Calling blocking futex_wait"); ret = futex_wait(&futex, 0); @@ -123,7 +124,7 @@ while (state != 1) { Timeout t{3}; - thread_sleep(&t); + (void)thread_sleep(&t); } debug_log("Consuming all CPU on medium-priority thread"); state = 2; @@ -144,27 +145,31 @@ debug_log("Low-priority thread finished, unlocking"); state = 4; futex = 0; - futex_wake(&futex, 1); + (void)futex_wake(&futex, 1); } }; async(priorityBug); async(priorityBug); debug_log("Waiting for background threads to enter the right state"); - while (state != 2) + for (sleeps = 0; (sleeps < 100) && (state != 2); sleeps++) { - Timeout t{3}; - thread_sleep(&t); + TEST(sleep(3) >= 0, "Failed to sleep"); } + TEST(sleeps < 100, "Waited too long for background threads"); debug_log("High-priority thread attempting to acquire futex owned by " "low-priority thread without priority propagation"); state = 3; t.remaining = 1; - futex_timed_wait(&t, &futex, futex, FutexNone); + TEST_EQUAL(futex_timed_wait(&t, &futex, futex, FutexNone), + -ETIMEDOUT, + "futex_timed_wait failed"); TEST(futex != 0, "Made progress surprisingly!"); debug_log("High-priority thread attempting to acquire futex owned by " "low-priority thread with priority propagation"); t.remaining = 4; - futex_timed_wait(&t, &futex, futex, FutexPriorityInheritance); + TEST_EQUAL(futex_timed_wait(&t, &futex, futex, FutexPriorityInheritance), + 0, + "futex_timed_wait failed"); TEST(futex == 0, "Failed to make progress!"); futex = 1234;
diff --git a/tests/list-test.cc b/tests/list-test.cc index 5ea7700..bf6f66a 100644 --- a/tests/list-test.cc +++ b/tests/list-test.cc
@@ -174,7 +174,10 @@ // we do not use here), not to the removed element. LinkedObject::ObjectRing *removedCell = objects.first(); ds::linked_list::remove(objects.first()); - heap_free(MALLOC_CAPABILITY, LinkedObject::from_ring(removedCell)); + TEST_EQUAL( + heap_free(MALLOC_CAPABILITY, LinkedObject::from_ring(removedCell)), + 0, + "Failed to free removed cell"); TEST(LinkedObject::from_ring(objects.first())->data == 1, "First element of the list is incorrect after removing the first " "element, expected {}, got {}", @@ -191,7 +194,8 @@ { struct LinkedObject *o = LinkedObject::from_ring(cell); cell = cell->cell_next(); - heap_free(MALLOC_CAPABILITY, o); + TEST_EQUAL( + heap_free(MALLOC_CAPABILITY, o), 0, "Failed to free list object"); counter++; } @@ -213,7 +217,10 @@ // removed cell. This is great here because we will free the // object anyways. We could also use `remove` here. auto l = ds::linked_list::unsafe_remove(cell); - heap_free(MALLOC_CAPABILITY, LinkedObject::from_ring(cell)); + TEST_EQUAL( + heap_free(MALLOC_CAPABILITY, LinkedObject::from_ring(cell)), + 0, + "Failed to free searched object"); // `l` is the predecessor of `cell` in the residual ring, so // this does exactly what we want when `::search` iterates. cell = l; @@ -221,7 +228,9 @@ return false; }); // `::search` does not visit the element passed (`middle`) - heap_free(MALLOC_CAPABILITY, LinkedObject::from_ring(middle)); + TEST_EQUAL(heap_free(MALLOC_CAPABILITY, LinkedObject::from_ring(middle)), + 0, + "Failed to free middle object"); counter++; TEST(counter == NumberOfListElements - 1,
diff --git a/tests/multiwaiter-test.cc b/tests/multiwaiter-test.cc index b6b77dd..16cbc04 100644 --- a/tests/multiwaiter-test.cc +++ b/tests/multiwaiter-test.cc
@@ -47,7 +47,7 @@ sleep(1); debug_log("Waking futex from background thread"); *futexWord = value; - futex_wake(futexWord, 1); + TEST(futex_wake(futexWord, 1) >= 0, "futex_wait failed"); }); };
diff --git a/tests/stack-test.cc b/tests/stack-test.cc index b3b894f..205a398 100644 --- a/tests/stack-test.cc +++ b/tests/stack-test.cc
@@ -27,16 +27,17 @@ return ErrorRecoveryBehaviour::ForceUnwind; } -__cheri_callback void test_trusted_stack_exhaustion() +__cheri_callback int test_trusted_stack_exhaustion() { - exhaust_trusted_stack(&test_trusted_stack_exhaustion, - &threadStackTestFailed); + return exhaust_trusted_stack(&test_trusted_stack_exhaustion, + &threadStackTestFailed); } -__cheri_callback void cross_compartment_call() +__cheri_callback int cross_compartment_call() { TEST(false, "Cross compartment call with invalid CSP shouldn't be reachable"); + return -EINVAL; } namespace @@ -70,7 +71,10 @@ void expect_handler(bool handlerExpected) { debug_log("Expected to invoke the handler? {}", handlerExpected); - set_expected_behaviour(&threadStackTestFailed, handlerExpected); + TEST_EQUAL( + set_expected_behaviour(&threadStackTestFailed, handlerExpected), + 0, + "Failed to set expectations"); } __attribute__((used)) extern "C" int test_small_stack() @@ -114,7 +118,7 @@ // Defeat the compiler optimisation that may turn our first call to this into a // call. If the compiler does this then we will fail on an even number of // cross-compartment calls not an odd number. -__cheri_callback void (*volatile crossCompartmentCall)(); +__cheri_callback int (*volatile crossCompartmentCall)(); /* * The stack tests should cover the edge-cases scenarios for both @@ -139,7 +143,7 @@ TEST(ret == -ENOTENOUGHSTACK, "test_with_small_stack failed, returned {} with 128-byte stack", ret); - __cheri_callback void (*callback)() = cross_compartment_call; + __cheri_callback int (*callback)() = cross_compartment_call; crossCompartmentCall = test_trusted_stack_exhaustion; debug_log("exhaust trusted stack, do self recursion with a cheri_callback"); @@ -148,12 +152,15 @@ debug_log("exhausting the compartment stack"); expect_handler(false); - exhaust_thread_stack(); + TEST_EQUAL( + exhaust_thread_stack(), -ECOMPARTMENTFAIL, "exhaust_thread_stack failed"); debug_log("exhausting the compartment stack during a switcher call"); expect_handler(false); threadStackTestFailed = true; - exhaust_thread_stack_spill(callback); + TEST_EQUAL(exhaust_thread_stack_spill(callback), + 0, + "exhaust_thread_stack_spill failed"); TEST(threadStackTestFailed == false, "switcher did not return error"); debug_log("modifying stack permissions on fault"); @@ -164,7 +171,9 @@ compartmentStackPermissions.without(permissionToRemove); debug_log("Permissions: {}", permissions); expect_handler(stack_is_mostly_valid(permissions)); - set_csp_permissions_on_fault(permissions); + TEST_EQUAL(set_csp_permissions_on_fault(permissions), + -ECOMPARTMENTFAIL, + "Unexpected success with restricted permissions"); } debug_log("modifying stack permissions on cross compartment call"); @@ -173,16 +182,22 @@ auto permissions = compartmentStackPermissions.without(permissionToRemove); debug_log("Permissions: {}", permissions); - set_csp_permissions_on_call(permissions, callback); + TEST_EQUAL(set_csp_permissions_on_call(permissions, callback), + -ECOMPARTMENTFAIL, + "Unexpected success with restricted permissions"); } debug_log("invalid stack on fault"); expect_handler(false); - test_stack_invalid_on_fault(); + TEST_EQUAL(test_stack_invalid_on_fault(), + -ECOMPARTMENTFAIL, + "stack_invalid_on_fault failed"); debug_log("invalid stack on cross compartment call"); expect_handler(false); + TEST_EQUAL(test_stack_invalid_on_call(callback), + -ECOMPARTMENTFAIL, + "stack_invalid_on_call failed"); - test_stack_invalid_on_call(callback); return 0; }
diff --git a/tests/stack_integrity_thread.cc b/tests/stack_integrity_thread.cc index c897432..ee9f427 100644 --- a/tests/stack_integrity_thread.cc +++ b/tests/stack_integrity_thread.cc
@@ -64,14 +64,16 @@ * Set up the handler expectations. Takes the caller's error flag and * whether the handler is expected as arguments. */ -void set_expected_behaviour(bool *outTestFailed, bool handlerExpected) +int set_expected_behaviour(bool *outTestFailed, bool handlerExpected) { expectedHandler = handlerExpected; threadStackTestFailed = outTestFailed; *outTestFailed = handlerExpected; + + return 0; } -void exhaust_thread_stack() +int exhaust_thread_stack() { /* Move the compartment's stack near its end, in order to * trigger stack exhaustion while the switcher handles @@ -92,6 +94,8 @@ *threadStackTestFailed = true; TEST(false, "Should be unreachable"); + + return 0; } /** @@ -99,7 +103,7 @@ * callee-saved state. The result should simply be an error return, rather than * a forced-unwind. */ -void exhaust_thread_stack_spill(__cheri_callback void (*fn)()) +int exhaust_thread_stack_spill(__cheri_callback int (*fn)()) { register auto rfn asm("ct1") = fn; register uintptr_t res asm("ca0") = 0; @@ -126,52 +130,59 @@ *threadStackTestFailed = false; TEST(res == -ENOTENOUGHSTACK, "Bad return {}", res); + + return 0; } -void set_csp_permissions_on_fault(PermissionSet newPermissions) +int set_csp_permissions_on_fault(PermissionSet newPermissions) { __asm__ volatile( "candperm csp, csp, %0\n" "csh zero, 0(cnull)\n" ::"r"(newPermissions.as_raw())); TEST(false, "Should be unreachable"); + return -EINVAL; } -void set_csp_permissions_on_call(PermissionSet newPermissions, - __cheri_callback void (*fn)()) +int set_csp_permissions_on_call(PermissionSet newPermissions, + __cheri_callback int (*fn)()) { CALL_CHERI_CALLBACK(fn, "candperm csp, csp, %1\n", newPermissions.as_raw()); TEST(false, "Should be unreachable"); + return -EINVAL; } -void test_stack_invalid_on_fault() +int test_stack_invalid_on_fault() { __asm__ volatile("ccleartag csp, csp\n" "csh zero, 0(cnull)\n"); *threadStackTestFailed = true; TEST(false, "Should be unreachable"); + return -EINVAL; } -void test_stack_invalid_on_call(__cheri_callback void (*fn)()) +int test_stack_invalid_on_call(__cheri_callback int (*fn)()) { // the `move zero, %1` is a no-op, just to have an operand CALL_CHERI_CALLBACK(fn, "move zero, %1\nccleartag csp, csp\n", 0); *threadStackTestFailed = true; TEST(false, "Should be unreachable"); + return -EINVAL; } -void self_recursion(__cheri_callback void (*fn)()) +int self_recursion(__cheri_callback int (*fn)()) { (*fn)(); + return 0; } -void exhaust_trusted_stack(__cheri_callback void (*fn)(), - bool *outLeakedSwitcherCapability) +int exhaust_trusted_stack(__cheri_callback int (*fn)(), + bool *outLeakedSwitcherCapability) { - self_recursion(fn); + return self_recursion(fn); } int test_stack_requirement()
diff --git a/tests/stack_tests.h b/tests/stack_tests.h index 93ad94b..90b49df 100644 --- a/tests/stack_tests.h +++ b/tests/stack_tests.h
@@ -4,28 +4,27 @@ using namespace CHERI; -__cheri_compartment("stack_integrity_thread") void exhaust_trusted_stack( - __cheri_callback void (*fn)(), +__cheri_compartment("stack_integrity_thread") int exhaust_trusted_stack( + __cheri_callback int (*fn)(), bool *outLeakedSwitcherCapability); -__cheri_compartment("stack_integrity_thread") void exhaust_thread_stack(); -__cheri_compartment("stack_integrity_thread") void exhaust_thread_stack_spill( - __cheri_callback void (*fn)()); -__cheri_compartment("stack_integrity_thread") void set_csp_permissions_on_fault( +__cheri_compartment("stack_integrity_thread") int exhaust_thread_stack(); +__cheri_compartment("stack_integrity_thread") int exhaust_thread_stack_spill( + __cheri_callback int (*fn)()); +__cheri_compartment("stack_integrity_thread") int set_csp_permissions_on_fault( PermissionSet newPermissions); -__cheri_compartment("stack_integrity_thread") void set_csp_permissions_on_call( +__cheri_compartment("stack_integrity_thread") int set_csp_permissions_on_call( PermissionSet newPermissions, - __cheri_callback void (*fn)()); -__cheri_compartment( - "stack_integrity_thread") void test_stack_invalid_on_fault(); -__cheri_compartment("stack_integrity_thread") void test_stack_invalid_on_call( - __cheri_callback void (*fn)()); + __cheri_callback int (*fn)()); +__cheri_compartment("stack_integrity_thread") int test_stack_invalid_on_fault(); +__cheri_compartment("stack_integrity_thread") int test_stack_invalid_on_call( + __cheri_callback int (*fn)()); /** * Sets what we expect to happen for this test. Is a fault expected to invoke * the handler? The fault handler will set or clear `*outTestFailed` when a * fault is received, depending on whether it was expected. */ -__cheri_compartment("stack_integrity_thread") void set_expected_behaviour( +__cheri_compartment("stack_integrity_thread") int set_expected_behaviour( bool *outTestFailed, bool handlerExpected);
diff --git a/tests/test-runner.cc b/tests/test-runner.cc index 37d2958..6d89591 100644 --- a/tests/test-runner.cc +++ b/tests/test-runner.cc
@@ -79,7 +79,7 @@ /** * Test suite entry point. Runs all of the tests that we have defined. */ -void __cheri_compartment("test_runner") run_tests() +int __cheri_compartment("test_runner") run_tests() { // magic_enum is a pretty powerful stress-test of various bits of linkage. // In generating `enum_values`, it generates constant strings and pointers
diff --git a/tests/tests.hh b/tests/tests.hh index 14780ed..79779b7 100644 --- a/tests/tests.hh +++ b/tests/tests.hh
@@ -56,6 +56,6 @@ inline Ticks sleep(Ticks ticks) { Timeout t{ticks}; - thread_sleep(&t); + TEST(thread_sleep(&t) >= 0, "Failed to sleep"); return t.elapsed; };
diff --git a/tests/thread_pool-test.cc b/tests/thread_pool-test.cc index 52a08e0..00377b3 100644 --- a/tests/thread_pool-test.cc +++ b/tests/thread_pool-test.cc
@@ -75,8 +75,7 @@ int sleeps = 0; while (counter < 2) { - Timeout t{1}; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to sleep"); TEST(sleeps < 100, "Gave up after too many sleeps"); } debug_log("Yielded {} times for the thread pool to run our jobs", sleeps); @@ -125,8 +124,7 @@ { if (!asyncThread) { - Timeout t{1}; - thread_sleep(&t); + TEST(sleep(1) >= 0, "Failed to sleep"); } } TEST(asyncThread, "Worker thread did not provide thread pointer"); @@ -134,8 +132,7 @@ bool ret = switcher_interrupt_thread(asyncThread); interruptStarted = true; TEST(ret, "Interrupting worker thread failed: {}", ret); - Timeout t{3}; - thread_sleep(&t); + TEST(sleep(3) >= 0, "Failed to sleep"); TEST(interrupted, "Worker thread was not interrupted"); return 0; static cheriot::atomic<uint32_t> barrier{3};