╭ ssp.zig ──────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
.. aarch64_outline_atomics.zig absv.zig absvdi2.zig absvdi2_test.zig absvsi2.zig absvsi2_test.zig absvti2.zig absvti2_test.zig addf3.zig addf3_test.zig addvdi3.zig addvsi3.zig arm.zig atomics.zig aulldiv.zig aullrem.zig bitreverse.zig bitreversedi2_test.zig bitreversesi2_test.zig bitreverseti2_test.zig bswap.zig bswapdi2_test.zig bswapsi2_test.zig bswapti2_test.zig clear_cache.zig clzdi2_test.zig clzsi2_test.zig clzti2_test.zig cmp.zig cmpdi2_test.zig cmpsi2_test.zig cmpti2_test.zig comparedf2_test.zig comparef.zig comparesf2_test.zig cos.zig count0bits.zig ctzdi2_test.zig ctzsi2_test.zig ctzti2_test.zig divc3.zig divc3_test.zig divdf3.zig divdf3_test.zig divmodei4.zig divsf3.zig divsf3_test.zig divtf3.zig divtf3_test.zig divti3_test.zig divxf3.zig divxf3_test.zig emutls.zig exp.zig exp2.zig exp_f128.zig extendf.zig extendf_test.zig fabs.zig ffsdi2_test.zig ffssi2_test.zig ffsti2_test.zig float_from_int.zig float_from_int_test.zig floor_ceil.zig fma.zig fmax.zig fmin.zig fmod.zig fmodq_test.zig fmodx_test.zig hexagon.zig int.zig int_from_float.zig int_from_float_test.zig limb64.zig log.zig log10.zig log2.zig log_f128.zig memcpy.zig memmove.zig modti3_test.zig mulXi3.zig mulXi3_test.zig mulc3.zig mulc3_test.zig mulf3.zig mulf3_test.zig mulo.zig mulodi4_test.zig mulosi4_test.zig muloti4_test.zig mulvsi3.zig negdi2_test.zig negsi2_test.zig negti2_test.zig negv.zig negvdi2_test.zig negvsi2_test.zig negvti2_test.zig os_version_check.zig parity.zig paritydi2_test.zig paritysi2_test.zig parityti2_test.zig popcount.zig popcountdi2_test.zig popcountsi2_test.zig popcountti2_test.zig powiXf2.zig powiXf2_test.zig rem_pio2.zig rem_pio2_large.zig rem_pio2f.zig rem_pio2l.zig round.zig shift.zig shift_test.zig sin.zig sincos.zig sqrt.zig ╭─────────────────────────────────╮ │ssp.zig │ ╰─────────────────────────────────╯ stack_probe.zig subvdi3.zig subvsi3.zig tan.zig trig.zig trunc.zig truncf.zig truncf_test.zig ucmpdi2_test.zig ucmpsi2_test.zig ucmpti2_test.zig udivmod.zig udivmoddi4_test.zig udivmodei4.zig udivmodsi4_test.zig udivmodti4_test.zig
1 //! 2 //! Small Zig reimplementation of gcc's libssp. 3 //! 4 //! This library implements most of the builtins required by the stack smashing 5 //! protection as implemented by gcc&clang. 6 //! Missing exports: 7 //! - __gets_chk 8 //! - __mempcpy_chk 9 //! - __snprintf_chk 10 //! - __sprintf_chk 11 //! - __stpcpy_chk 12 //! - __vsnprintf_chk 13 //! - __vsprintf_chk 14 15 const std = @import("std"); 16 const compiler_rt = @import("../compiler_rt.zig"); 17 const symbol = compiler_rt.symbol; 18 const builtin = @import("builtin"); 19 20 extern fn memset(dest: ?[*]u8, c: c_int, n: usize) callconv(.c) ?[*]u8; 21 extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; 22 extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; 23 24 comptime { 25 @export(&__stack_chk_fail, .{ .name = if (builtin.os.tag == .openbsd) "__stack_smash_handler" else "__stack_chk_fail", .linkage = compiler_rt.linkage, .visibility = compiler_rt.visibility }); 26 symbol(&__chk_fail, "__chk_fail"); 27 symbol(&__stack_chk_guard, if (builtin.os.tag == .openbsd) "__guard_local" else "__stack_chk_guard"); 28 symbol(&__strcpy_chk, "__strcpy_chk"); 29 symbol(&__strncpy_chk, "__strncpy_chk"); 30 symbol(&__strcat_chk, "__strcat_chk"); 31 symbol(&__strncat_chk, "__strncat_chk"); 32 symbol(&__memcpy_chk, "__memcpy_chk"); 33 symbol(&__memmove_chk, "__memmove_chk"); 34 symbol(&__memset_chk, "__memset_chk"); 35 } 36 37 fn __stack_chk_fail() callconv(.c) noreturn { 38 @panic("stack smashing detected"); 39 } 40 41 fn __chk_fail() callconv(.c) noreturn { 42 @panic("buffer overflow detected"); 43 } 44 45 // TODO: Initialize the canary with random data 46 var __stack_chk_guard: usize = blk: { 47 var buf: [@sizeOf(usize)]u8 = @splat(0); 48 buf[@sizeOf(usize) - 1] = 255; 49 buf[@sizeOf(usize) - 2] = '\n'; 50 break :blk @bitCast(buf); 51 }; 52 53 fn __strcpy_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.c) [*:0]u8 { 54 @setRuntimeSafety(false); 55 56 var i: usize = 0; 57 while (i < dest_n and src[i] != 0) : (i += 1) { 58 dest[i] = src[i]; 59 } 60 61 if (i == dest_n) __chk_fail(); 62 63 dest[i] = 0; 64 65 return dest; 66 } 67 68 fn __strncpy_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.c) [*:0]u8 { 69 @setRuntimeSafety(false); 70 if (dest_n < n) __chk_fail(); 71 var i: usize = 0; 72 while (i < n and src[i] != 0) : (i += 1) { 73 dest[i] = src[i]; 74 } 75 while (i < n) : (i += 1) { 76 dest[i] = 0; 77 } 78 return dest; 79 } 80 81 fn __strcat_chk(dest: [*:0]u8, src: [*:0]const u8, dest_n: usize) callconv(.c) [*:0]u8 { 82 @setRuntimeSafety(false); 83 84 var avail = dest_n; 85 86 var dest_end: usize = 0; 87 while (avail > 0 and dest[dest_end] != 0) : (dest_end += 1) { 88 avail -= 1; 89 } 90 91 if (avail < 1) __chk_fail(); 92 93 var i: usize = 0; 94 while (avail > 0 and src[i] != 0) : (i += 1) { 95 dest[dest_end + i] = src[i]; 96 avail -= 1; 97 } 98 99 if (avail < 1) __chk_fail(); 100 101 dest[dest_end + i] = 0; 102 103 return dest; 104 } 105 106 fn __strncat_chk(dest: [*:0]u8, src: [*:0]const u8, n: usize, dest_n: usize) callconv(.c) [*:0]u8 { 107 @setRuntimeSafety(false); 108 109 var avail = dest_n; 110 111 var dest_end: usize = 0; 112 while (avail > 0 and dest[dest_end] != 0) : (dest_end += 1) { 113 avail -= 1; 114 } 115 116 if (avail < 1) __chk_fail(); 117 118 var i: usize = 0; 119 while (avail > 0 and i < n and src[i] != 0) : (i += 1) { 120 dest[dest_end + i] = src[i]; 121 avail -= 1; 122 } 123 124 if (avail < 1) __chk_fail(); 125 126 dest[dest_end + i] = 0; 127 128 return dest; 129 } 130 131 fn __memcpy_chk(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { 132 if (dest_n < n) __chk_fail(); 133 return memcpy(dest, src, n); 134 } 135 136 fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { 137 if (dest_n < n) __chk_fail(); 138 return memmove(dest, src, n); 139 } 140 141 fn __memset_chk(dest: ?[*]u8, c: c_int, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { 142 if (dest_n < n) __chk_fail(); 143 return memset(dest, c, n); 144 } 145