From f8cd981c04e60530b99c9f360c3e79041d75ca96 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 31 Oct 2019 17:24:22 -0400 Subject: use -fsanitize=undefined for C code in safe build modes closes #3569 --- src/codegen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 1b77f0752a..b828410181 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8973,6 +8973,9 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa switch (g->build_mode) { case BuildModeDebug: + args.append("-fsanitize=undefined"); + args.append("-fsanitize-trap=undefined"); + // windows c runtime requires -D_DEBUG if using debug libraries args.append("-D_DEBUG"); @@ -8985,6 +8988,9 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa } break; case BuildModeSafeRelease: + args.append("-fsanitize=undefined"); + args.append("-fsanitize-trap=undefined"); + // See the comment in the BuildModeFastRelease case for why we pass -O2 rather // than -O3 here. args.append("-O2"); -- cgit v1.2.3 From 839b3a61ad51b385ac28a0123b6cc63d90ef83f8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 16 Dec 2019 13:51:21 -0500 Subject: expose the ability to disable C sanitization and disable C sanitization when building libcs. Empirically, they seem to trigger undef-sanitization. --- lib/std/build.zig | 5 +++++ src/all_types.hpp | 8 ++++++++ src/codegen.cpp | 31 +++++++++++++++++++++++++------ src/main.cpp | 9 +++++++++ src/target.cpp | 4 ++++ src/target.hpp | 1 + 6 files changed, 52 insertions(+), 6 deletions(-) (limited to 'src/codegen.cpp') diff --git a/lib/std/build.zig b/lib/std/build.zig index e54a23d8ab..f7e4756e90 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1034,6 +1034,7 @@ pub const LibExeObjStep = struct { disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, + disable_sanitize_c: bool, c_std: Builder.CStd, override_lib_dir: ?[]const u8, main_pkg_path: ?[]const u8, @@ -1183,6 +1184,7 @@ pub const LibExeObjStep = struct { .disable_gen_h = false, .bundle_compiler_rt = false, .disable_stack_probing = false, + .disable_sanitize_c = false, .output_dir = null, .need_system_paths = false, .single_threaded = false, @@ -1822,6 +1824,9 @@ pub const LibExeObjStep = struct { if (self.disable_stack_probing) { try zig_args.append("-fno-stack-check"); } + if (self.disable_sanitize_c) { + try zig_args.append("-fno-sanitize-c"); + } switch (self.target) { .Native => {}, diff --git a/src/all_types.hpp b/src/all_types.hpp index 5f0211df74..bcef45f718 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1928,6 +1928,12 @@ enum WantStackCheck { WantStackCheckEnabled, }; +enum WantCSanitize { + WantCSanitizeAuto, + WantCSanitizeDisabled, + WantCSanitizeEnabled, +}; + struct CFile { ZigList args; const char *source_path; @@ -2096,6 +2102,7 @@ struct CodeGen { WantPIC want_pic; WantStackCheck want_stack_check; + WantCSanitize want_sanitize_c; CacheHash cache_hash; ErrColor err_color; uint32_t next_unresolved_index; @@ -2170,6 +2177,7 @@ struct CodeGen { bool have_pic; bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic bool have_stack_probing; + bool have_sanitize_c; bool function_sections; bool enable_dump_analysis; bool enable_doc_generation; diff --git a/src/codegen.cpp b/src/codegen.cpp index b828410181..edc2c7f435 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8261,6 +8261,20 @@ static bool detect_stack_probing(CodeGen *g) { zig_unreachable(); } +static bool detect_sanitize_c(CodeGen *g) { + if (!target_supports_sanitize_c(g->zig_target)) + return false; + switch (g->want_sanitize_c) { + case WantCSanitizeDisabled: + return false; + case WantCSanitizeEnabled: + return true; + case WantCSanitizeAuto: + return g->build_mode == BuildModeSafeRelease || g->build_mode == BuildModeDebug; + } + zig_unreachable(); +} + // Returns TargetSubsystemAuto to mean "no subsystem" TargetSubsystem detect_subsystem(CodeGen *g) { if (g->subsystem != TargetSubsystemAuto) @@ -8297,6 +8311,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { g->have_dynamic_link = detect_dynamic_link(g); g->have_pic = detect_pic(g); g->have_stack_probing = detect_stack_probing(g); + g->have_sanitize_c = detect_sanitize_c(g); g->is_single_threaded = detect_single_threaded(g); g->have_err_ret_tracing = detect_err_ret_tracing(g); @@ -8582,6 +8597,7 @@ static void init(CodeGen *g) { g->have_dynamic_link = detect_dynamic_link(g); g->have_pic = detect_pic(g); g->have_stack_probing = detect_stack_probing(g); + g->have_sanitize_c = detect_sanitize_c(g); g->is_single_threaded = detect_single_threaded(g); g->have_err_ret_tracing = detect_err_ret_tracing(g); @@ -8971,11 +8987,13 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-fomit-frame-pointer"); } + if (g->have_sanitize_c) { + args.append("-fsanitize=undefined"); + args.append("-fsanitize-trap=undefined"); + } + switch (g->build_mode) { case BuildModeDebug: - args.append("-fsanitize=undefined"); - args.append("-fsanitize-trap=undefined"); - // windows c runtime requires -D_DEBUG if using debug libraries args.append("-D_DEBUG"); @@ -8988,9 +9006,6 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa } break; case BuildModeSafeRelease: - args.append("-fsanitize=undefined"); - args.append("-fsanitize-trap=undefined"); - // See the comment in the BuildModeFastRelease case for why we pass -O2 rather // than -O3 here. args.append("-O2"); @@ -9312,6 +9327,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose cache_bool(cache_hash, g->strip_debug_symbols); cache_int(cache_hash, g->build_mode); cache_bool(cache_hash, g->have_pic); + cache_bool(cache_hash, g->have_sanitize_c); cache_bool(cache_hash, want_valgrind_support(g)); cache_bool(cache_hash, g->function_sections); for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { @@ -10090,6 +10106,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_bool(ch, g->have_pic); cache_bool(ch, g->have_dynamic_link); cache_bool(ch, g->have_stack_probing); + cache_bool(ch, g->have_sanitize_c); cache_bool(ch, g->is_dummy_so); cache_bool(ch, g->function_sections); cache_bool(ch, g->enable_dump_analysis); @@ -10210,6 +10227,7 @@ void codegen_build_and_link(CodeGen *g) { g->have_pic = detect_pic(g); g->is_single_threaded = detect_single_threaded(g); g->have_err_ret_tracing = detect_err_ret_tracing(g); + g->have_sanitize_c = detect_sanitize_c(g); detect_libc(g); detect_dynamic_linker(g); @@ -10398,6 +10416,7 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o child_gen->root_out_name = buf_create_from_str(name); child_gen->disable_gen_h = true; child_gen->want_stack_check = WantStackCheckDisabled; + child_gen->want_sanitize_c = WantCSanitizeDisabled; child_gen->verbose_tokenize = parent_gen->verbose_tokenize; child_gen->verbose_ast = parent_gen->verbose_ast; child_gen->verbose_link = parent_gen->verbose_link; diff --git a/src/main.cpp b/src/main.cpp index a6b26893b9..2cda18f7a0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --enable-valgrind include valgrind client requests release builds\n" " -fstack-check enable stack probing in unsafe builds\n" " -fno-stack-check disable stack probing in safe builds\n" + " -fsanitize-c enable C undefined behavior detection in unsafe builds\n" + " -fno-sanitize-c disable C undefined behavior detection in safe builds\n" " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" " -fPIC enable Position Independent Code\n" " -fno-PIC disable Position Independent Code\n" @@ -524,6 +526,7 @@ int main(int argc, char **argv) { ValgrindSupport valgrind_support = ValgrindSupportAuto; WantPIC want_pic = WantPICAuto; WantStackCheck want_stack_check = WantStackCheckAuto; + WantCSanitize want_sanitize_c = WantCSanitizeAuto; bool function_sections = false; ZigList llvm_argv = {0}; @@ -722,6 +725,10 @@ int main(int argc, char **argv) { want_stack_check = WantStackCheckEnabled; } else if (strcmp(arg, "-fno-stack-check") == 0) { want_stack_check = WantStackCheckDisabled; + } else if (strcmp(arg, "-fsanitize-c") == 0) { + want_sanitize_c = WantCSanitizeEnabled; + } else if (strcmp(arg, "-fno-sanitize-c") == 0) { + want_sanitize_c = WantCSanitizeDisabled; } else if (strcmp(arg, "--system-linker-hack") == 0) { system_linker_hack = true; } else if (strcmp(arg, "--single-threaded") == 0) { @@ -1093,6 +1100,7 @@ int main(int argc, char **argv) { g->valgrind_support = valgrind_support; g->want_pic = want_pic; g->want_stack_check = want_stack_check; + g->want_sanitize_c = want_sanitize_c; g->want_single_threaded = want_single_threaded; Buf *builtin_source = codegen_generate_builtin_source(g); if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { @@ -1192,6 +1200,7 @@ int main(int argc, char **argv) { g->valgrind_support = valgrind_support; g->want_pic = want_pic; g->want_stack_check = want_stack_check; + g->want_sanitize_c = want_sanitize_c; g->subsystem = subsystem; g->enable_time_report = timing_info; diff --git a/src/target.cpp b/src/target.cpp index 03815a20fe..82d5467e26 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1606,6 +1606,10 @@ bool target_supports_stack_probing(const ZigTarget *target) { return target->os != OsWindows && target->os != OsUefi && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64); } +bool target_supports_sanitize_c(const ZigTarget *target) { + return true; +} + bool target_requires_pic(const ZigTarget *target, bool linking_libc) { // This function returns whether non-pic code is completely invalid on the given target. return target_is_android(target) || target->os == OsWindows || target->os == OsUefi || target_os_requires_libc(target->os) || diff --git a/src/target.hpp b/src/target.hpp index f72b44a277..50611bc853 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -194,6 +194,7 @@ bool target_is_riscv(const ZigTarget *target); bool target_is_android(const ZigTarget *target); bool target_is_single_threaded(const ZigTarget *target); bool target_supports_stack_probing(const ZigTarget *target); +bool target_supports_sanitize_c(const ZigTarget *target); bool target_has_debug_info(const ZigTarget *target); const char *target_arch_musl_name(ZigLLVM_ArchType arch); bool target_supports_libunwind(const ZigTarget *target); -- cgit v1.2.3