| ... | @@ -4457,9 +4457,18 @@ pub fn addCCArgs( | ... | @@ -4457,9 +4457,18 @@ pub fn addCCArgs( |
| 4457 | if (comp.sanitize_c and !comp.bin_file.options.tsan) { | 4457 | if (comp.sanitize_c and !comp.bin_file.options.tsan) { |
| 4458 | try argv.append("-fsanitize=undefined"); | 4458 | try argv.append("-fsanitize=undefined"); |
| 4459 | try argv.append("-fsanitize-trap=undefined"); | 4459 | try argv.append("-fsanitize-trap=undefined"); |
| | 4460 | // It is very common, and well-defined, for a pointer on one side of a C ABI |
| | 4461 | // to have a different but compatible element type. Examples include: |
| | 4462 | // `char*` vs `uint8_t*` on a system with 8-bit bytes |
| | 4463 | // `const char*` vs `char*` |
| | 4464 | // `char*` vs `unsigned char*` |
| | 4465 | // Without this flag, Clang would invoke UBSAN when such an extern |
| | 4466 | // function was called. |
| | 4467 | try argv.append("-fno-sanitize=function"); |
| 4460 | } else if (comp.sanitize_c and comp.bin_file.options.tsan) { | 4468 | } else if (comp.sanitize_c and comp.bin_file.options.tsan) { |
| 4461 | try argv.append("-fsanitize=undefined,thread"); | 4469 | try argv.append("-fsanitize=undefined,thread"); |
| 4462 | try argv.append("-fsanitize-trap=undefined"); | 4470 | try argv.append("-fsanitize-trap=undefined"); |
| | 4471 | try argv.append("-fno-sanitize=function"); |
| 4463 | } else if (!comp.sanitize_c and comp.bin_file.options.tsan) { | 4472 | } else if (!comp.sanitize_c and comp.bin_file.options.tsan) { |
| 4464 | try argv.append("-fsanitize=thread"); | 4473 | try argv.append("-fsanitize=thread"); |
| 4465 | } | 4474 | } |