panic_recovery_test.c (1946B)
1 /* panic_recovery_test - nested public panic boundaries under sanitizers. */ 2 3 #include <kit/core.h> 4 #include <kit/frontend.h> 5 #include <string.h> 6 7 #include "lib/kit_unit.h" 8 9 static KitUnit g_u; 10 #define EXPECT(c, ...) CU_EXPECT(&g_u, c, __VA_ARGS__) 11 12 typedef struct PanicRecovery { 13 int inner_ran; 14 int outer_recovered; 15 } PanicRecovery; 16 17 static KitSrcLoc no_loc(void) { 18 KitSrcLoc loc; 19 loc.file_id = 0; 20 loc.line = 0; 21 loc.col = 0; 22 return loc; 23 } 24 25 static KitStatus inner_fatal(KitCompiler* c, void* user) { 26 PanicRecovery* r = (PanicRecovery*)user; 27 r->inner_ran++; 28 kit_frontend_fatal(c, no_loc(), "inner expected fatal"); 29 } 30 31 static KitStatus outer_then_fatal(KitCompiler* c, void* user) { 32 PanicRecovery* r = (PanicRecovery*)user; 33 KitStatus st = kit_frontend_run(c, inner_fatal, r); 34 EXPECT(st == KIT_ERR, "inner fatal recovered as KIT_ERR"); 35 EXPECT(strstr(g_u.last_diag, "inner expected fatal") != NULL, 36 "inner fatal diagnostic captured"); 37 38 r->outer_recovered++; 39 kit_frontend_fatal(c, no_loc(), "outer expected fatal"); 40 } 41 42 static void check_nested_recovery(void) { 43 KitCompiler* c = NULL; 44 PanicRecovery r; 45 KitStatus st; 46 47 memset(&r, 0, sizeof r); 48 EXPECT(kit_unit_compiler_new( 49 &g_u, kit_unit_target(KIT_ARCH_X86_64, KIT_OS_LINUX, KIT_OBJ_ELF), 50 &c) == KIT_OK, 51 "compiler init"); 52 if (!c) return; 53 54 g_u.suppress_fatal = 1; 55 st = kit_frontend_run(c, outer_then_fatal, &r); 56 g_u.suppress_fatal = 0; 57 58 EXPECT(st == KIT_ERR, "outer fatal recovered as KIT_ERR"); 59 EXPECT(r.inner_ran == 1, "inner body ran once"); 60 EXPECT(r.outer_recovered == 1, "outer continued after inner recovery"); 61 EXPECT(strstr(g_u.last_diag, "outer expected fatal") != NULL, 62 "outer fatal diagnostic captured"); 63 kit_compiler_free(c); 64 } 65 66 int main(void) { 67 kit_unit_init(&g_u); 68 check_nested_recovery(); 69 kit_unit_summary(&g_u, "panic_recovery_test"); 70 return kit_unit_status(&g_u); 71 }