@@ -1287,7 +1287,14 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
12871287 const any_unwind_tables = options .config .any_unwind_tables or options .root_mod .unwind_tables != .none ;
12881288 const any_non_single_threaded = options .config .any_non_single_threaded or ! options .root_mod .single_threaded ;
12891289 const any_sanitize_thread = options .config .any_sanitize_thread or options .root_mod .sanitize_thread ;
1290- const any_sanitize_c = options .config .any_sanitize_c or options .root_mod .sanitize_c ;
1290+ const any_sanitize_c : std.zig.SanitizeC = switch (options .config .any_sanitize_c ) {
1291+ .off = > options .root_mod .sanitize_c ,
1292+ .trap = > if (options .root_mod .sanitize_c == .full )
1293+ .full
1294+ else
1295+ .trap ,
1296+ .full = > .full ,
1297+ };
12911298 const any_fuzz = options .config .any_fuzz or options .root_mod .fuzz ;
12921299
12931300 const link_eh_frame_hdr = options .link_eh_frame_hdr or any_unwind_tables ;
@@ -1346,7 +1353,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13461353 // and this reduces unnecessary bloat.
13471354 const ubsan_rt_strat : RtStrat = s : {
13481355 const is_spirv = options .root_mod .resolved_target .result .cpu .arch .isSpirV ();
1349- const want_ubsan_rt = options .want_ubsan_rt orelse (! is_spirv and any_sanitize_c and is_exe_or_dyn_lib );
1356+ const want_ubsan_rt = options .want_ubsan_rt orelse (! is_spirv and any_sanitize_c == .full and is_exe_or_dyn_lib );
13501357 if (! want_ubsan_rt ) break :s .none ;
13511358 if (options .skip_linker_dependencies ) break :s .none ;
13521359 if (have_zcu ) break :s .zcu ;
@@ -1418,6 +1425,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
14181425 cache .hash .add (options .config .lto );
14191426 cache .hash .add (options .config .link_mode );
14201427 cache .hash .add (options .config .any_unwind_tables );
1428+ cache .hash .add (options .config .any_non_single_threaded );
1429+ cache .hash .add (options .config .any_sanitize_thread );
1430+ cache .hash .add (options .config .any_sanitize_c );
1431+ cache .hash .add (options .config .any_fuzz );
14211432 cache .hash .add (options .function_sections );
14221433 cache .hash .add (options .data_sections );
14231434 cache .hash .add (link_libc );
@@ -6048,7 +6059,7 @@ pub fn addCCArgs(
60486059 {
60496060 var san_arg : std .ArrayListUnmanaged (u8 ) = .empty ;
60506061 const prefix = "-fsanitize=" ;
6051- if (mod .sanitize_c ) {
6062+ if (mod .sanitize_c != .off ) {
60526063 if (san_arg .items .len == 0 ) try san_arg .appendSlice (arena , prefix );
60536064 try san_arg .appendSlice (arena , "undefined," );
60546065 }
@@ -6064,37 +6075,33 @@ pub fn addCCArgs(
60646075 if (san_arg .pop ()) | _ | {
60656076 try argv .append (san_arg .items );
60666077
6067- // These args have to be added after the `-fsanitize` arg or
6068- // they won't take effect.
6069- if (mod .sanitize_c ) {
6070- // This check requires implementing the Itanium C++ ABI.
6071- // We would make it `-fsanitize-trap=vptr`, however this check requires
6072- // a full runtime due to the type hashing involved.
6073- try argv .append ("-fno-sanitize=vptr" );
6074-
6075- // It is very common, and well-defined, for a pointer on one side of a C ABI
6076- // to have a different but compatible element type. Examples include:
6077- // `char*` vs `uint8_t*` on a system with 8-bit bytes
6078- // `const char*` vs `char*`
6079- // `char*` vs `unsigned char*`
6080- // Without this flag, Clang would invoke UBSAN when such an extern
6081- // function was called.
6082- try argv .append ("-fno-sanitize=function" );
6083-
6084- if (mod .optimize_mode == .ReleaseSafe ) {
6085- // It's recommended to use the minimal runtime in production
6086- // environments due to the security implications of the full runtime.
6087- // The minimal runtime doesn't provide much benefit over simply
6088- // trapping, however, so we do that instead.
6078+ switch (mod .sanitize_c ) {
6079+ .off = > {},
6080+ .trap = > {
60896081 try argv .append ("-fsanitize-trap=undefined" );
6090- } else {
6082+ },
6083+ .full = > {
6084+ // This check requires implementing the Itanium C++ ABI.
6085+ // We would make it `-fsanitize-trap=vptr`, however this check requires
6086+ // a full runtime due to the type hashing involved.
6087+ try argv .append ("-fno-sanitize=vptr" );
6088+
6089+ // It is very common, and well-defined, for a pointer on one side of a C ABI
6090+ // to have a different but compatible element type. Examples include:
6091+ // `char*` vs `uint8_t*` on a system with 8-bit bytes
6092+ // `const char*` vs `char*`
6093+ // `char*` vs `unsigned char*`
6094+ // Without this flag, Clang would invoke UBSAN when such an extern
6095+ // function was called.
6096+ try argv .append ("-fno-sanitize=function" );
6097+
60916098 // This is necessary because, by default, Clang instructs LLVM to embed
60926099 // a COFF link dependency on `libclang_rt.ubsan_standalone.a` when the
60936100 // UBSan runtime is used.
60946101 if (target .os .tag == .windows ) {
60956102 try argv .append ("-fno-rtlib-defaultlib" );
60966103 }
6097- }
6104+ },
60986105 }
60996106 }
61006107
@@ -6797,7 +6804,7 @@ pub fn build_crt_file(
67976804 .strip = comp .compilerRtStrip (),
67986805 .stack_check = false ,
67996806 .stack_protector = 0 ,
6800- .sanitize_c = false ,
6807+ .sanitize_c = .off ,
68016808 .sanitize_thread = false ,
68026809 .red_zone = comp .root_mod .red_zone ,
68036810 // Some libcs (e.g. musl) are opinionated about -fomit-frame-pointer.
0 commit comments