| author | |
| committer | |
| log | 35b9db3b1549668c5a3a464f97aed1441b18d791 |
| tree | 446b9a52420255c82adad39a9d1eb150ae7dfc1b |
| parent | 931178494f4c77631e5eb9c567f64492d6592eeb |
11 files changed, 195 insertions(+), 60 deletions(-)
lib/ubsan_rt.zig+151-27| ... | ... | @@ -79,12 +79,16 @@ const Value = extern struct { |
| 79 | 79 | }; |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | fn getFloat(value: Value) c_longdouble { | |
| 82 | fn getFloat(value: Value) f128 { | |
| 83 | 83 | assert(value.td.kind == .float); |
| 84 | 84 | const size = value.td.info.float; |
| 85 | 85 | const max_inline_size = @bitSizeOf(ValueHandle); |
| 86 | 86 | if (size <= max_inline_size) { |
| 87 | return @bitCast(@intFromPtr(value.handle)); | |
| 87 | return @as(switch (@bitSizeOf(usize)) { | |
| 88 | 32 => f32, | |
| 89 | 64 => f64, | |
| 90 | else => @compileError("unsupported target"), | |
| 91 | }, @bitCast(@intFromPtr(value.handle))); | |
| 88 | 92 | } |
| 89 | 93 | return @floatCast(switch (size) { |
| 90 | 94 | 64 => @as(*const f64, @alignCast(@ptrCast(value.handle))).*, |
| ... | ... | @@ -122,6 +126,11 @@ const Value = extern struct { |
| 122 | 126 | ) !void { |
| 123 | 127 | comptime assert(fmt.len == 0); |
| 124 | 128 | |
| 129 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) { | |
| 130 | try writer.writeAll("(unknown)"); | |
| 131 | return; | |
| 132 | } | |
| 133 | ||
| 125 | 134 | switch (value.td.kind) { |
| 126 | 135 | .integer => { |
| 127 | 136 | if (value.td.isSigned()) { |
| ... | ... | @@ -146,6 +155,14 @@ fn overflowHandler( |
| 146 | 155 | comptime operator: []const u8, |
| 147 | 156 | ) void { |
| 148 | 157 | const S = struct { |
| 158 | fn abort( | |
| 159 | data: *const OverflowData, | |
| 160 | lhs_handle: ValueHandle, | |
| 161 | rhs_handle: ValueHandle, | |
| 162 | ) callconv(.c) noreturn { | |
| 163 | handler(data, lhs_handle, rhs_handle); | |
| 164 | } | |
| 165 | ||
| 149 | 166 | fn handler( |
| 150 | 167 | data: *const OverflowData, |
| 151 | 168 | lhs_handle: ValueHandle, |
| ... | ... | @@ -167,7 +184,14 @@ fn overflowHandler( |
| 167 | 184 | } |
| 168 | 185 | }; |
| 169 | 186 | |
| 170 | exportHandler(&S.handler, sym_name, true); | |
| 187 | exportHandlerWithAbort(&S.handler, &S.abort, sym_name); | |
| 188 | } | |
| 189 | ||
| 190 | fn negationHandlerAbort( | |
| 191 | data: *const OverflowData, | |
| 192 | value_handle: ValueHandle, | |
| 193 | ) callconv(.c) noreturn { | |
| 194 | negationHandler(data, value_handle); | |
| 171 | 195 | } |
| 172 | 196 | |
| 173 | 197 | fn negationHandler( |
| ... | ... | @@ -181,6 +205,14 @@ fn negationHandler( |
| 181 | 205 | ); |
| 182 | 206 | } |
| 183 | 207 | |
| 208 | fn divRemHandlerAbort( | |
| 209 | data: *const OverflowData, | |
| 210 | lhs_handle: ValueHandle, | |
| 211 | rhs_handle: ValueHandle, | |
| 212 | ) callconv(.c) noreturn { | |
| 213 | divRemHandler(data, lhs_handle, rhs_handle); | |
| 214 | } | |
| 215 | ||
| 184 | 216 | fn divRemHandler( |
| 185 | 217 | data: *const OverflowData, |
| 186 | 218 | lhs_handle: ValueHandle, |
| ... | ... | @@ -203,6 +235,20 @@ const AlignmentAssumptionData = extern struct { |
| 203 | 235 | td: *const TypeDescriptor, |
| 204 | 236 | }; |
| 205 | 237 | |
| 238 | fn alignmentAssumptionHandlerAbort( | |
| 239 | data: *const AlignmentAssumptionData, | |
| 240 | pointer: ValueHandle, | |
| 241 | alignment_handle: ValueHandle, | |
| 242 | maybe_offset: ?ValueHandle, | |
| 243 | ) callconv(.c) noreturn { | |
| 244 | alignmentAssumptionHandler( | |
| 245 | data, | |
| 246 | pointer, | |
| 247 | alignment_handle, | |
| 248 | maybe_offset, | |
| 249 | ); | |
| 250 | } | |
| 251 | ||
| 206 | 252 | fn alignmentAssumptionHandler( |
| 207 | 253 | data: *const AlignmentAssumptionData, |
| 208 | 254 | pointer: ValueHandle, |
| ... | ... | @@ -248,6 +294,14 @@ const ShiftOobData = extern struct { |
| 248 | 294 | rhs_type: *const TypeDescriptor, |
| 249 | 295 | }; |
| 250 | 296 | |
| 297 | fn shiftOobAbort( | |
| 298 | data: *const ShiftOobData, | |
| 299 | lhs_handle: ValueHandle, | |
| 300 | rhs_handle: ValueHandle, | |
| 301 | ) callconv(.c) noreturn { | |
| 302 | shiftOob(data, lhs_handle, rhs_handle); | |
| 303 | } | |
| 304 | ||
| 251 | 305 | fn shiftOob( |
| 252 | 306 | data: *const ShiftOobData, |
| 253 | 307 | lhs_handle: ValueHandle, |
| ... | ... | @@ -285,7 +339,17 @@ const OutOfBoundsData = extern struct { |
| 285 | 339 | index_type: *const TypeDescriptor, |
| 286 | 340 | }; |
| 287 | 341 | |
| 288 | fn outOfBounds(data: *const OutOfBoundsData, index_handle: ValueHandle) callconv(.c) noreturn { | |
| 342 | fn outOfBoundsAbort( | |
| 343 | data: *const OutOfBoundsData, | |
| 344 | index_handle: ValueHandle, | |
| 345 | ) callconv(.c) noreturn { | |
| 346 | outOfBounds(data, index_handle); | |
| 347 | } | |
| 348 | ||
| 349 | fn outOfBounds( | |
| 350 | data: *const OutOfBoundsData, | |
| 351 | index_handle: ValueHandle, | |
| 352 | ) callconv(.c) noreturn { | |
| 289 | 353 | const index: Value = .{ .handle = index_handle, .td = data.index_type }; |
| 290 | 354 | logMessage( |
| 291 | 355 | "index {} out of bounds for type {s}", |
| ... | ... | @@ -297,6 +361,14 @@ const PointerOverflowData = extern struct { |
| 297 | 361 | loc: SourceLocation, |
| 298 | 362 | }; |
| 299 | 363 | |
| 364 | fn pointerOverflowAbort( | |
| 365 | data: *const PointerOverflowData, | |
| 366 | base: usize, | |
| 367 | result: usize, | |
| 368 | ) callconv(.c) noreturn { | |
| 369 | pointerOverflow(data, base, result); | |
| 370 | } | |
| 371 | ||
| 300 | 372 | fn pointerOverflow( |
| 301 | 373 | _: *const PointerOverflowData, |
| 302 | 374 | base: usize, |
| ... | ... | @@ -375,6 +447,13 @@ const TypeMismatchData = extern struct { |
| 375 | 447 | }, |
| 376 | 448 | }; |
| 377 | 449 | |
| 450 | fn typeMismatchAbort( | |
| 451 | data: *const TypeMismatchData, | |
| 452 | pointer: ?ValueHandle, | |
| 453 | ) callconv(.c) noreturn { | |
| 454 | typeMismatch(data, pointer); | |
| 455 | } | |
| 456 | ||
| 378 | 457 | fn typeMismatch( |
| 379 | 458 | data: *const TypeMismatchData, |
| 380 | 459 | pointer: ?ValueHandle, |
| ... | ... | @@ -416,6 +495,9 @@ const NonNullReturnData = extern struct { |
| 416 | 495 | attribute_loc: SourceLocation, |
| 417 | 496 | }; |
| 418 | 497 | |
| 498 | fn nonNullReturnAbort(data: *const NonNullReturnData) callconv(.c) noreturn { | |
| 499 | nonNullReturn(data); | |
| 500 | } | |
| 419 | 501 | fn nonNullReturn(_: *const NonNullReturnData) callconv(.c) noreturn { |
| 420 | 502 | logMessage("null pointer returned from function declared to never return null", .{}); |
| 421 | 503 | } |
| ... | ... | @@ -426,6 +508,10 @@ const NonNullArgData = extern struct { |
| 426 | 508 | arg_index: i32, |
| 427 | 509 | }; |
| 428 | 510 | |
| 511 | fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn { | |
| 512 | nonNullArg(data); | |
| 513 | } | |
| 514 | ||
| 429 | 515 | fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn { |
| 430 | 516 | logMessage( |
| 431 | 517 | "null pointer passed as argument {}, which is declared to never be null", |
| ... | ... | @@ -438,6 +524,13 @@ const InvalidValueData = extern struct { |
| 438 | 524 | td: *const TypeDescriptor, |
| 439 | 525 | }; |
| 440 | 526 | |
| 527 | fn loadInvalidValueAbort( | |
| 528 | data: *const InvalidValueData, | |
| 529 | value_handle: ValueHandle, | |
| 530 | ) callconv(.c) noreturn { | |
| 531 | loadInvalidValue(data, value_handle); | |
| 532 | } | |
| 533 | ||
| 441 | 534 | fn loadInvalidValue( |
| 442 | 535 | data: *const InvalidValueData, |
| 443 | 536 | value_handle: ValueHandle, |
| ... | ... | @@ -456,6 +549,9 @@ const InvalidBuiltinData = extern struct { |
| 456 | 549 | clz, |
| 457 | 550 | }, |
| 458 | 551 | }; |
| 552 | fn invalidBuiltinAbort(data: *const InvalidBuiltinData) callconv(.c) noreturn { | |
| 553 | invalidBuiltin(data); | |
| 554 | } | |
| 459 | 555 | |
| 460 | 556 | fn invalidBuiltin(data: *const InvalidBuiltinData) callconv(.c) noreturn { |
| 461 | 557 | logMessage( |
| ... | ... | @@ -469,6 +565,13 @@ const VlaBoundNotPositive = extern struct { |
| 469 | 565 | td: *const TypeDescriptor, |
| 470 | 566 | }; |
| 471 | 567 | |
| 568 | fn vlaBoundNotPositiveAbort( | |
| 569 | data: *const VlaBoundNotPositive, | |
| 570 | bound_handle: ValueHandle, | |
| 571 | ) callconv(.c) noreturn { | |
| 572 | vlaBoundNotPositive(data, bound_handle); | |
| 573 | } | |
| 574 | ||
| 472 | 575 | fn vlaBoundNotPositive( |
| 473 | 576 | data: *const VlaBoundNotPositive, |
| 474 | 577 | bound_handle: ValueHandle, |
| ... | ... | @@ -491,6 +594,13 @@ const FloatCastOverflowDataV2 = extern struct { |
| 491 | 594 | to: *const TypeDescriptor, |
| 492 | 595 | }; |
| 493 | 596 | |
| 597 | fn floatCastOverflowAbort( | |
| 598 | data_handle: *align(8) const anyopaque, | |
| 599 | from_handle: ValueHandle, | |
| 600 | ) callconv(.c) noreturn { | |
| 601 | floatCastOverflow(data_handle, from_handle); | |
| 602 | } | |
| 603 | ||
| 494 | 604 | fn floatCastOverflow( |
| 495 | 605 | data_handle: *align(8) const anyopaque, |
| 496 | 606 | from_handle: ValueHandle, |
| ... | ... | @@ -514,22 +624,31 @@ fn floatCastOverflow( |
| 514 | 624 | } |
| 515 | 625 | |
| 516 | 626 | inline fn logMessage(comptime fmt: []const u8, args: anytype) noreturn { |
| 517 | std.debug.panicExtra(null, @returnAddress(), fmt, args); | |
| 627 | std.debug.panicExtra(@returnAddress(), fmt, args); | |
| 518 | 628 | } |
| 519 | 629 | |
| 520 | 630 | fn exportHandler( |
| 521 | 631 | handler: anytype, |
| 522 | 632 | comptime sym_name: []const u8, |
| 523 | comptime abort: bool, | |
| 524 | 633 | ) void { |
| 525 | const linkage = if (builtin.is_test) .internal else .weak; | |
| 634 | const linkage = if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) .internal else .weak; | |
| 635 | const N = "__ubsan_handle_" ++ sym_name; | |
| 636 | @export(handler, .{ .name = N, .linkage = linkage }); | |
| 637 | } | |
| 638 | ||
| 639 | fn exportHandlerWithAbort( | |
| 640 | handler: anytype, | |
| 641 | abort_handler: anytype, | |
| 642 | comptime sym_name: []const u8, | |
| 643 | ) void { | |
| 644 | const linkage = if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) .internal else .weak; | |
| 526 | 645 | { |
| 527 | 646 | const N = "__ubsan_handle_" ++ sym_name; |
| 528 | 647 | @export(handler, .{ .name = N, .linkage = linkage }); |
| 529 | 648 | } |
| 530 | if (abort) { | |
| 649 | { | |
| 531 | 650 | const N = "__ubsan_handle_" ++ sym_name ++ "_abort"; |
| 532 | @export(handler, .{ .name = N, .linkage = linkage }); | |
| 651 | @export(abort_handler, .{ .name = N, .linkage = linkage }); | |
| 533 | 652 | } |
| 534 | 653 | } |
| 535 | 654 | |
| ... | ... | @@ -539,24 +658,29 @@ const can_build_ubsan = switch (builtin.zig_backend) { |
| 539 | 658 | }; |
| 540 | 659 | |
| 541 | 660 | comptime { |
| 542 | overflowHandler("add_overflow", "+"); | |
| 543 | overflowHandler("mul_overflow", "*"); | |
| 544 | overflowHandler("sub_overflow", "-"); | |
| 545 | exportHandler(&alignmentAssumptionHandler, "alignment_assumption", true); | |
| 546 | exportHandler(&builtinUnreachable, "builtin_unreachable", false); | |
| 547 | exportHandler(&divRemHandler, "divrem_overflow", true); | |
| 548 | exportHandler(&floatCastOverflow, "float_cast_overflow", true); | |
| 549 | exportHandler(&invalidBuiltin, "invalid_builtin", true); | |
| 550 | exportHandler(&loadInvalidValue, "load_invalid_value", true); | |
| 551 | exportHandler(&missingReturn, "missing_return", false); | |
| 552 | exportHandler(&negationHandler, "negate_overflow", true); | |
| 553 | exportHandler(&nonNullArg, "nonnull_arg", true); | |
| 554 | exportHandler(&nonNullReturn, "nonnull_return_v1", true); | |
| 555 | exportHandler(&outOfBounds, "out_of_bounds", true); | |
| 556 | exportHandler(&pointerOverflow, "pointer_overflow", true); | |
| 557 | exportHandler(&shiftOob, "shift_out_of_bounds", true); | |
| 558 | exportHandler(&typeMismatch, "type_mismatch_v1", true); | |
| 559 | exportHandler(&vlaBoundNotPositive, "vla_bound_not_positive", true); | |
| 661 | if (can_build_ubsan) { | |
| 662 | overflowHandler("add_overflow", "+"); | |
| 663 | overflowHandler("mul_overflow", "*"); | |
| 664 | overflowHandler("sub_overflow", "-"); | |
| 665 | exportHandlerWithAbort(&alignmentAssumptionHandler, &alignmentAssumptionHandlerAbort, "alignment_assumption"); | |
| 666 | ||
| 667 | exportHandlerWithAbort(&divRemHandler, &divRemHandlerAbort, "divrem_overflow"); | |
| 668 | exportHandlerWithAbort(&floatCastOverflow, &floatCastOverflowAbort, "float_cast_overflow"); | |
| 669 | exportHandlerWithAbort(&invalidBuiltin, &invalidBuiltinAbort, "invalid_builtin"); | |
| 670 | exportHandlerWithAbort(&loadInvalidValue, &loadInvalidValueAbort, "load_invalid_value"); | |
| 671 | ||
| 672 | exportHandlerWithAbort(&negationHandler, &negationHandlerAbort, "negate_overflow"); | |
| 673 | exportHandlerWithAbort(&nonNullArg, &nonNullArgAbort, "nonnull_arg"); | |
| 674 | exportHandlerWithAbort(&nonNullReturn, &nonNullReturnAbort, "nonnull_return_v1"); | |
| 675 | exportHandlerWithAbort(&outOfBounds, &outOfBoundsAbort, "out_of_bounds"); | |
| 676 | exportHandlerWithAbort(&pointerOverflow, &pointerOverflowAbort, "pointer_overflow"); | |
| 677 | exportHandlerWithAbort(&shiftOob, &shiftOobAbort, "shift_out_of_bounds"); | |
| 678 | exportHandlerWithAbort(&typeMismatch, &typeMismatchAbort, "type_mismatch_v1"); | |
| 679 | exportHandlerWithAbort(&vlaBoundNotPositive, &vlaBoundNotPositiveAbort, "vla_bound_not_positive"); | |
| 680 | ||
| 681 | exportHandler(&builtinUnreachable, "builtin_unreachable"); | |
| 682 | exportHandler(&missingReturn, "missing_return"); | |
| 683 | } | |
| 560 | 684 | |
| 561 | 685 | // these checks are nearly impossible to duplicate in zig, as they rely on nuances |
| 562 | 686 | // in the Itanium C++ ABI. |
src/Compilation.zig+23-33| ... | ... | @@ -1317,15 +1317,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1317 | 1317 | break :s .obj; |
| 1318 | 1318 | }; |
| 1319 | 1319 | |
| 1320 | const ubsan_rt_strat: RtStrat = s: { | |
| 1321 | const want_ubsan_rt = options.want_ubsan_rt orelse (any_sanitize_c and output_mode != .Obj); | |
| 1322 | if (!want_ubsan_rt) break :s .none; | |
| 1323 | if (options.skip_linker_dependencies) break :s .none; | |
| 1324 | if (have_zcu) break :s .zcu; | |
| 1325 | if (is_exe_or_dyn_lib) break :s .lib; | |
| 1326 | break :s .obj; | |
| 1327 | }; | |
| 1328 | ||
| 1329 | 1320 | if (compiler_rt_strat == .zcu) { |
| 1330 | 1321 | // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");` |
| 1331 | 1322 | // injected into the object. |
| ... | ... | @@ -1355,6 +1346,15 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1355 | 1346 | // unlike compiler_rt, we always want to go through the `_ = @import("ubsan-rt")` |
| 1356 | 1347 | // approach, since the ubsan runtime uses quite a lot of the standard library |
| 1357 | 1348 | // and this reduces unnecessary bloat. |
| 1349 | const ubsan_rt_strat: RtStrat = s: { | |
| 1350 | const want_ubsan_rt = options.want_ubsan_rt orelse (any_sanitize_c and output_mode != .Obj); | |
| 1351 | if (!want_ubsan_rt) break :s .none; | |
| 1352 | if (options.skip_linker_dependencies) break :s .none; | |
| 1353 | if (have_zcu) break :s .zcu; | |
| 1354 | if (is_exe_or_dyn_lib) break :s .lib; | |
| 1355 | break :s .obj; | |
| 1356 | }; | |
| 1357 | ||
| 1358 | 1358 | if (ubsan_rt_strat == .zcu) { |
| 1359 | 1359 | const ubsan_rt_mod = try Package.Module.create(arena, .{ |
| 1360 | 1360 | .global_cache_directory = options.global_cache_directory, |
| ... | ... | @@ -1362,7 +1362,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1362 | 1362 | .root = .{ |
| 1363 | 1363 | .root_dir = options.zig_lib_directory, |
| 1364 | 1364 | }, |
| 1365 | .root_src_path = "ubsan.zig", | |
| 1365 | .root_src_path = "ubsan_rt.zig", | |
| 1366 | 1366 | }, |
| 1367 | 1367 | .fully_qualified_name = "ubsan_rt", |
| 1368 | 1368 | .cc_argv = &.{}, |
| ... | ... | @@ -1925,25 +1925,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1925 | 1925 | comp.remaining_prelink_tasks += 1; |
| 1926 | 1926 | } |
| 1927 | 1927 | |
| 1928 | <<<<<<< HEAD | |
| 1929 | if (comp.include_compiler_rt and capable_of_building_compiler_rt) { | |
| 1930 | if (is_exe_or_dyn_lib) { | |
| 1931 | ======= | |
| 1932 | if (target.isMinGW() and comp.config.any_non_single_threaded) { | |
| 1933 | // LLD might drop some symbols as unused during LTO and GCing, therefore, | |
| 1934 | // we force mark them for resolution here. | |
| 1935 | ||
| 1936 | const tls_index_sym = switch (target.cpu.arch) { | |
| 1937 | .x86 => "__tls_index", | |
| 1938 | else => "_tls_index", | |
| 1939 | }; | |
| 1940 | ||
| 1941 | try comp.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); | |
| 1942 | } | |
| 1943 | ||
| 1944 | 1928 | if (capable_of_building_compiler_rt) { |
| 1945 | 1929 | if (comp.compiler_rt_strat == .lib) { |
| 1946 | >>>>>>> 050e3e69ac (Compilation: correct when to include ubsan) | |
| 1947 | 1930 | log.debug("queuing a job to build compiler_rt_lib", .{}); |
| 1948 | 1931 | comp.queued_jobs.compiler_rt_lib = true; |
| 1949 | 1932 | comp.remaining_prelink_tasks += 1; |
| ... | ... | @@ -1957,11 +1940,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1957 | 1940 | |
| 1958 | 1941 | if (comp.ubsan_rt_strat == .lib) { |
| 1959 | 1942 | log.debug("queuing a job to build ubsan_rt_lib", .{}); |
| 1960 | comp.job_queued_ubsan_rt_lib = true; | |
| 1943 | comp.queued_jobs.ubsan_rt_lib = true; | |
| 1961 | 1944 | comp.remaining_prelink_tasks += 1; |
| 1962 | 1945 | } else if (comp.ubsan_rt_strat == .obj) { |
| 1963 | 1946 | log.debug("queuing a job to build ubsan_rt_obj", .{}); |
| 1964 | comp.job_queued_ubsan_rt_obj = true; | |
| 1947 | comp.queued_jobs.ubsan_rt_obj = true; | |
| 1965 | 1948 | comp.remaining_prelink_tasks += 1; |
| 1966 | 1949 | } |
| 1967 | 1950 | |
| ... | ... | @@ -3782,11 +3765,11 @@ fn performAllTheWorkInner( |
| 3782 | 3765 | } |
| 3783 | 3766 | |
| 3784 | 3767 | if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) { |
| 3785 | comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "ubsan_rt.zig", .libubsan, .Lib, &comp.ubsan_rt_lib, main_progress_node }); | |
| 3768 | comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "ubsan_rt.zig", .libubsan, .Lib, false, &comp.ubsan_rt_lib, main_progress_node }); | |
| 3786 | 3769 | } |
| 3787 | 3770 | |
| 3788 | 3771 | if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) { |
| 3789 | comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "ubsan_rt.zig", .libubsan, .Obj, &comp.ubsan_rt_obj, main_progress_node }); | |
| 3772 | comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "ubsan_rt.zig", .libubsan, .Obj, false, &comp.ubsan_rt_obj, main_progress_node }); | |
| 3790 | 3773 | } |
| 3791 | 3774 | |
| 3792 | 3775 | if (comp.queued_jobs.glibc_shared_objects) { |
| ... | ... | @@ -6037,9 +6020,16 @@ pub fn addCCArgs( |
| 6037 | 6020 | try argv.append("-fno-sanitize=function"); |
| 6038 | 6021 | |
| 6039 | 6022 | // It's recommended to use the minimal runtime in production environments |
| 6040 | // due to the security implications of the full runtime. | |
| 6023 | // due to the security implications of the full runtime. The minimal runtime | |
| 6024 | // doesn't provide much benefit over simply trapping. | |
| 6041 | 6025 | if (mod.optimize_mode == .ReleaseSafe) { |
| 6042 | try argv.append("-fsanitize-minimal-runtime"); | |
| 6026 | try argv.append("-fsanitize-trap=undefined"); | |
| 6027 | } | |
| 6028 | ||
| 6029 | // This is necessary because, by default, Clang instructs LLVM to embed a COFF link | |
| 6030 | // dependency on `libclang_rt.ubsan_standalone.a` when the UBSan runtime is used. | |
| 6031 | if (target.os.tag == .windows) { | |
| 6032 | try argv.append("-fno-rtlib-defaultlib"); | |
| 6043 | 6033 | } |
| 6044 | 6034 | } |
| 6045 | 6035 | } |
test/link/elf.zig+4| ... | ... | @@ -2049,6 +2049,8 @@ fn testLargeBss(b: *Build, opts: Options) *Step { |
| 2049 | 2049 | \\} |
| 2050 | 2050 | , &.{}); |
| 2051 | 2051 | exe.linkLibC(); |
| 2052 | // Disabled to work around an ELF linker bug. | |
| 2053 | exe.root_module.sanitize_c = false; | |
| 2052 | 2054 | |
| 2053 | 2055 | const run = addRunArtifact(exe); |
| 2054 | 2056 | run.expectExitCode(0); |
| ... | ... | @@ -3552,6 +3554,8 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step { |
| 3552 | 3554 | \\} |
| 3553 | 3555 | , &.{}); |
| 3554 | 3556 | exe.linkLibC(); |
| 3557 | // Disabled to work around an ELF linker bug. | |
| 3558 | exe.root_module.sanitize_c = false; | |
| 3555 | 3559 | |
| 3556 | 3560 | const run = addRunArtifact(exe); |
| 3557 | 3561 | run.expectStdOutEqual("3 0 5 0 0 0\n"); |
test/link/glibc_compat/build.zig+6| ... | ... | @@ -22,6 +22,8 @@ pub fn build(b: *std.Build) void { |
| 22 | 22 | .link_libc = true, |
| 23 | 23 | }), |
| 24 | 24 | }); |
| 25 | exe.bundle_ubsan_rt = false; | |
| 26 | exe.root_module.sanitize_c = false; | |
| 25 | 27 | exe.root_module.addCSourceFile(.{ .file = b.path("main.c") }); |
| 26 | 28 | // TODO: actually test the output |
| 27 | 29 | _ = exe.getEmittedBin(); |
| ... | ... | @@ -62,6 +64,8 @@ pub fn build(b: *std.Build) void { |
| 62 | 64 | .link_libc = true, |
| 63 | 65 | }), |
| 64 | 66 | }); |
| 67 | exe.bundle_ubsan_rt = false; | |
| 68 | exe.root_module.sanitize_c = false; | |
| 65 | 69 | exe.root_module.addCSourceFile(.{ .file = b.path("glibc_runtime_check.c") }); |
| 66 | 70 | |
| 67 | 71 | // Only try running the test if the host glibc is known to be good enough. Ideally, the Zig |
| ... | ... | @@ -161,6 +165,8 @@ pub fn build(b: *std.Build) void { |
| 161 | 165 | .link_libc = true, |
| 162 | 166 | }), |
| 163 | 167 | }); |
| 168 | exe.bundle_ubsan_rt = false; | |
| 169 | exe.root_module.sanitize_c = false; | |
| 164 | 170 | |
| 165 | 171 | // Only try running the test if the host glibc is known to be good enough. Ideally, the Zig |
| 166 | 172 | // test runner would be able to check this, but see https://github.com/ziglang/zig/pull/17702#issuecomment-1831310453 |
test/link/wasm/export-data/build.zig+1| ... | ... | @@ -13,6 +13,7 @@ pub fn build(b: *std.Build) void { |
| 13 | 13 | }), |
| 14 | 14 | }); |
| 15 | 15 | lib.entry = .disabled; |
| 16 | lib.bundle_ubsan_rt = false; | |
| 16 | 17 | lib.use_lld = false; |
| 17 | 18 | lib.root_module.export_symbol_names = &.{ "foo", "bar" }; |
| 18 | 19 | // Object being linked has neither functions nor globals named "foo" or "bar" and |
test/link/wasm/export/build.zig+4| ... | ... | @@ -19,6 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 19 | 19 | no_export.entry = .disabled; |
| 20 | 20 | no_export.use_llvm = false; |
| 21 | 21 | no_export.use_lld = false; |
| 22 | no_export.bundle_ubsan_rt = false; | |
| 22 | 23 | |
| 23 | 24 | const dynamic_export = b.addExecutable(.{ |
| 24 | 25 | .name = "dynamic", |
| ... | ... | @@ -32,6 +33,8 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 32 | 33 | dynamic_export.rdynamic = true; |
| 33 | 34 | dynamic_export.use_llvm = false; |
| 34 | 35 | dynamic_export.use_lld = false; |
| 36 | // don't pull in ubsan, since we're just expecting a minimal executable | |
| 37 | dynamic_export.bundle_ubsan_rt = false; | |
| 35 | 38 | |
| 36 | 39 | const force_export = b.addExecutable(.{ |
| 37 | 40 | .name = "force", |
| ... | ... | @@ -45,6 +48,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 45 | 48 | force_export.root_module.export_symbol_names = &.{"foo"}; |
| 46 | 49 | force_export.use_llvm = false; |
| 47 | 50 | force_export.use_lld = false; |
| 51 | force_export.bundle_ubsan_rt = false; | |
| 48 | 52 | |
| 49 | 53 | const check_no_export = no_export.checkObject(); |
| 50 | 54 | check_no_export.checkInHeaders(); |
test/link/wasm/function-table/build.zig+2| ... | ... | @@ -21,6 +21,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 21 | 21 | export_table.use_lld = false; |
| 22 | 22 | export_table.export_table = true; |
| 23 | 23 | export_table.link_gc_sections = false; |
| 24 | export_table.bundle_ubsan_rt = false; | |
| 24 | 25 | |
| 25 | 26 | const regular_table = b.addExecutable(.{ |
| 26 | 27 | .name = "regular_table", |
| ... | ... | @@ -34,6 +35,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 34 | 35 | regular_table.use_llvm = false; |
| 35 | 36 | regular_table.use_lld = false; |
| 36 | 37 | regular_table.link_gc_sections = false; // Ensure function table is not empty |
| 38 | regular_table.bundle_ubsan_rt = false; | |
| 37 | 39 | |
| 38 | 40 | const check_export = export_table.checkObject(); |
| 39 | 41 | const check_regular = regular_table.checkObject(); |
test/link/wasm/shared-memory/build.zig+1| ... | ... | @@ -31,6 +31,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt |
| 31 | 31 | exe.shared_memory = true; |
| 32 | 32 | exe.max_memory = 67108864; |
| 33 | 33 | exe.root_module.export_symbol_names = &.{"foo"}; |
| 34 | exe.bundle_ubsan_rt = false; | |
| 34 | 35 | |
| 35 | 36 | const check_exe = exe.checkObject(); |
| 36 | 37 |
test/link/wasm/type/build.zig+1| ... | ... | @@ -21,6 +21,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 21 | 21 | exe.use_llvm = false; |
| 22 | 22 | exe.use_lld = false; |
| 23 | 23 | exe.root_module.export_symbol_names = &.{"foo"}; |
| 24 | exe.bundle_ubsan_rt = false; | |
| 24 | 25 | b.installArtifact(exe); |
| 25 | 26 | |
| 26 | 27 | const check_exe = exe.checkObject(); |
test/src/StackTrace.zig+1| ... | ... | @@ -81,6 +81,7 @@ fn addExpect( |
| 81 | 81 | }), |
| 82 | 82 | .use_llvm = use_llvm, |
| 83 | 83 | }); |
| 84 | exe.bundle_ubsan_rt = false; | |
| 84 | 85 | |
| 85 | 86 | const run = b.addRunArtifact(exe); |
| 86 | 87 | run.removeEnvironmentVariable("CLICOLOR_FORCE"); |
tools/incr-check.zig+1| ... | ... | @@ -108,6 +108,7 @@ pub fn main() !void { |
| 108 | 108 | "build-exe", |
| 109 | 109 | case.root_source_file, |
| 110 | 110 | "-fincremental", |
| 111 | "-fno-ubsan-rt", | |
| 111 | 112 | "-target", |
| 112 | 113 | target.query, |
| 113 | 114 | "--cache-dir", |