@zigc/lib 0.16.0-dev.3091 → 0.16.0-dev.3128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/c/math.zig +121 -30
- package/compiler/build_runner.zig +1 -0
- package/compiler/test_runner.zig +191 -59
- package/compiler_rt/cos.zig +141 -52
- package/compiler_rt/long_double.zig +37 -0
- package/compiler_rt/rem_pio2l.zig +173 -0
- package/compiler_rt/sin.zig +140 -55
- package/compiler_rt/sincos.zig +279 -72
- package/compiler_rt/tan.zig +118 -47
- package/compiler_rt/trig.zig +256 -6
- package/fuzzer.zig +855 -307
- package/package.json +1 -1
- package/std/Build/Fuzz.zig +6 -19
- package/std/Build/Step/Run.zig +530 -68
- package/std/Build/abi.zig +39 -7
- package/std/Build.zig +3 -0
- package/std/compress/flate/Compress.zig +3 -3
- package/std/debug/Info.zig +4 -0
- package/std/heap/ArenaAllocator.zig +145 -154
- package/std/mem/Allocator.zig +4 -5
- package/std/mem.zig +48 -0
- package/std/priority_dequeue.zig +13 -12
- package/std/priority_queue.zig +5 -4
- package/std/zig/Client.zig +8 -3
- package/std/zig/Server.zig +26 -0
- package/libc/mingw/complex/cabs.c +0 -48
- package/libc/mingw/complex/cabsf.c +0 -48
- package/libc/mingw/complex/cacos.c +0 -50
- package/libc/mingw/complex/cacosf.c +0 -50
- package/libc/mingw/complex/carg.c +0 -48
- package/libc/mingw/complex/cargf.c +0 -48
- package/libc/mingw/complex/casin.c +0 -50
- package/libc/mingw/complex/casinf.c +0 -50
- package/libc/mingw/complex/catan.c +0 -50
- package/libc/mingw/complex/catanf.c +0 -50
- package/libc/mingw/complex/ccos.c +0 -50
- package/libc/mingw/complex/ccosf.c +0 -50
- package/libc/mingw/complex/cexp.c +0 -48
- package/libc/mingw/complex/cexpf.c +0 -48
- package/libc/mingw/complex/cimag.c +0 -48
- package/libc/mingw/complex/cimagf.c +0 -48
- package/libc/mingw/complex/clog.c +0 -48
- package/libc/mingw/complex/clog10.c +0 -49
- package/libc/mingw/complex/clog10f.c +0 -49
- package/libc/mingw/complex/clogf.c +0 -48
- package/libc/mingw/complex/conj.c +0 -48
- package/libc/mingw/complex/conjf.c +0 -48
- package/libc/mingw/complex/cpow.c +0 -48
- package/libc/mingw/complex/cpowf.c +0 -48
- package/libc/mingw/complex/cproj.c +0 -48
- package/libc/mingw/complex/cprojf.c +0 -48
- package/libc/mingw/complex/creal.c +0 -48
- package/libc/mingw/complex/crealf.c +0 -48
- package/libc/mingw/complex/csin.c +0 -50
- package/libc/mingw/complex/csinf.c +0 -50
- package/libc/mingw/complex/csqrt.c +0 -48
- package/libc/mingw/complex/csqrtf.c +0 -48
- package/libc/mingw/complex/ctan.c +0 -50
- package/libc/mingw/complex/ctanf.c +0 -50
- package/libc/mingw/math/arm/s_rint.c +0 -86
- package/libc/mingw/math/arm/s_rintf.c +0 -51
- package/libc/mingw/math/arm/sincos.S +0 -30
- package/libc/mingw/math/arm-common/sincosl.c +0 -13
- package/libc/mingw/math/arm64/rint.c +0 -12
- package/libc/mingw/math/arm64/rintf.c +0 -12
- package/libc/mingw/math/arm64/sincos.S +0 -32
- package/libc/mingw/math/bsd_private_base.h +0 -148
- package/libc/mingw/math/frexpf.c +0 -13
- package/libc/mingw/math/frexpl.c +0 -71
- package/libc/mingw/math/x86/acosf.c +0 -29
- package/libc/mingw/math/x86/atanf.c +0 -23
- package/libc/mingw/math/x86/atanl.c +0 -18
- package/libc/mingw/math/x86/cos.def.h +0 -65
- package/libc/mingw/math/x86/cosl.c +0 -46
- package/libc/mingw/math/x86/cosl_internal.S +0 -55
- package/libc/mingw/math/x86/ldexp.c +0 -23
- package/libc/mingw/math/x86/scalbn.S +0 -41
- package/libc/mingw/math/x86/scalbnf.S +0 -40
- package/libc/mingw/math/x86/sin.def.h +0 -65
- package/libc/mingw/math/x86/sinl.c +0 -46
- package/libc/mingw/math/x86/sinl_internal.S +0 -58
- package/libc/mingw/math/x86/tanl.S +0 -62
- package/libc/mingw/misc/btowc.c +0 -28
- package/libc/mingw/misc/wcstof.c +0 -66
- package/libc/mingw/misc/wcstoimax.c +0 -132
- package/libc/mingw/misc/wcstoumax.c +0 -126
- package/libc/mingw/misc/wctob.c +0 -29
- package/libc/mingw/misc/winbs_uint64.c +0 -6
- package/libc/mingw/misc/winbs_ulong.c +0 -6
- package/libc/mingw/misc/winbs_ushort.c +0 -6
- package/libc/mingw/stdio/_Exit.c +0 -10
- package/libc/mingw/stdio/_findfirst64i32.c +0 -21
- package/libc/mingw/stdio/_findnext64i32.c +0 -21
- package/libc/mingw/stdio/_fstat64i32.c +0 -37
- package/libc/mingw/stdio/_stat64i32.c +0 -37
- package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
- package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
- package/libc/mingw/stdio/_wstat64i32.c +0 -37
- package/libc/musl/src/legacy/valloc.c +0 -8
- package/libc/musl/src/math/__cosl.c +0 -96
- package/libc/musl/src/math/__sinl.c +0 -78
- package/libc/musl/src/math/__tanl.c +0 -143
- package/libc/musl/src/math/aarch64/lrint.c +0 -10
- package/libc/musl/src/math/aarch64/lrintf.c +0 -10
- package/libc/musl/src/math/aarch64/rintf.c +0 -7
- package/libc/musl/src/math/cosl.c +0 -39
- package/libc/musl/src/math/exp_data.c +0 -182
- package/libc/musl/src/math/exp_data.h +0 -26
- package/libc/musl/src/math/finite.c +0 -7
- package/libc/musl/src/math/finitef.c +0 -7
- package/libc/musl/src/math/frexp.c +0 -23
- package/libc/musl/src/math/frexpf.c +0 -23
- package/libc/musl/src/math/frexpl.c +0 -29
- package/libc/musl/src/math/i386/lrint.c +0 -8
- package/libc/musl/src/math/i386/lrintf.c +0 -8
- package/libc/musl/src/math/i386/rintf.c +0 -7
- package/libc/musl/src/math/lrint.c +0 -72
- package/libc/musl/src/math/lrintf.c +0 -8
- package/libc/musl/src/math/pow_data.c +0 -180
- package/libc/musl/src/math/pow_data.h +0 -22
- package/libc/musl/src/math/powerpc64/lrint.c +0 -16
- package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
- package/libc/musl/src/math/rintf.c +0 -30
- package/libc/musl/src/math/s390x/rintf.c +0 -15
- package/libc/musl/src/math/sincosl.c +0 -60
- package/libc/musl/src/math/sinl.c +0 -41
- package/libc/musl/src/math/tanl.c +0 -29
- package/libc/musl/src/math/x32/lrint.s +0 -5
- package/libc/musl/src/math/x32/lrintf.s +0 -5
- package/libc/musl/src/math/x86_64/lrint.c +0 -8
- package/libc/musl/src/math/x86_64/lrintf.c +0 -8
- package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
package/c/math.zig
CHANGED
|
@@ -35,33 +35,47 @@ comptime {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
if (builtin.target.isMinGW() or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
|
38
|
-
symbol(&
|
|
38
|
+
symbol(&frexpf, "frexpf");
|
|
39
|
+
symbol(&frexpl, "frexpl");
|
|
39
40
|
symbol(&hypotf, "hypotf");
|
|
40
41
|
symbol(&hypotl, "hypotl");
|
|
41
|
-
symbol(&modff, "modff");
|
|
42
42
|
symbol(&modfl, "modfl");
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if ((builtin.target.isMinGW() and @sizeOf(f64) != @sizeOf(c_longdouble)) or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
|
46
|
+
symbol(&atanl, "atanl");
|
|
47
|
+
symbol(©signl, "copysignl");
|
|
45
48
|
symbol(&nanl, "nanl");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if ((builtin.target.isMinGW() and builtin.cpu.arch == .x86) or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
|
52
|
+
symbol(&acosf, "acosf");
|
|
53
|
+
symbol(&atanf, "atanf");
|
|
54
|
+
symbol(&coshf, "coshf");
|
|
55
|
+
symbol(&modff, "modff");
|
|
46
56
|
symbol(&tanhf, "tanhf");
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
|
50
60
|
symbol(&acos, "acos");
|
|
51
|
-
symbol(&acosf, "acosf");
|
|
52
61
|
symbol(&acoshf, "acoshf");
|
|
53
62
|
symbol(&asin, "asin");
|
|
54
63
|
symbol(&atan, "atan");
|
|
55
|
-
symbol(&atanf, "atanf");
|
|
56
|
-
symbol(&atanl, "atanl");
|
|
57
64
|
symbol(&cbrt, "cbrt");
|
|
58
65
|
symbol(&cbrtf, "cbrtf");
|
|
59
66
|
symbol(&cosh, "cosh");
|
|
60
67
|
symbol(&exp10, "exp10");
|
|
61
68
|
symbol(&exp10f, "exp10f");
|
|
62
69
|
symbol(&fdim, "fdim");
|
|
70
|
+
symbol(&finite, "finite");
|
|
71
|
+
symbol(&finitef, "finitef");
|
|
72
|
+
symbol(&frexp, "frexp");
|
|
63
73
|
symbol(&hypot, "hypot");
|
|
74
|
+
symbol(&lrint, "lrint");
|
|
75
|
+
symbol(&lrintf, "lrintf");
|
|
64
76
|
symbol(&modf, "modf");
|
|
77
|
+
symbol(&nan, "nan");
|
|
78
|
+
symbol(&nanf, "nanf");
|
|
65
79
|
symbol(&pow, "pow");
|
|
66
80
|
symbol(&pow10, "pow10");
|
|
67
81
|
symbol(&pow10f, "pow10f");
|
|
@@ -72,9 +86,8 @@ comptime {
|
|
|
72
86
|
symbol(©sign, "copysign");
|
|
73
87
|
symbol(©signf, "copysignf");
|
|
74
88
|
symbol(&rint, "rint");
|
|
89
|
+
symbol(&rintf, "rintf");
|
|
75
90
|
}
|
|
76
|
-
|
|
77
|
-
symbol(©signl, "copysignl");
|
|
78
91
|
}
|
|
79
92
|
|
|
80
93
|
fn acos(x: f64) callconv(.c) f64 {
|
|
@@ -161,6 +174,45 @@ fn fdim(x: f64, y: f64) callconv(.c) f64 {
|
|
|
161
174
|
return 0;
|
|
162
175
|
}
|
|
163
176
|
|
|
177
|
+
fn finite(x: f64) callconv(.c) c_int {
|
|
178
|
+
return if (math.isFinite(x)) 1 else 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
fn finitef(x: f32) callconv(.c) c_int {
|
|
182
|
+
return if (math.isFinite(x)) 1 else 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fn frexpGeneric(comptime T: type, x: T, e: *c_int) T {
|
|
186
|
+
// libc expects `*e` to be unspecified in this case; an unspecified C value
|
|
187
|
+
// should be a valid value of the relevant type, yet Zig's std
|
|
188
|
+
// implementation sets it to `undefined` -- which can even be nonsense
|
|
189
|
+
// according to the type (int). Therefore, we're setting it to a valid
|
|
190
|
+
// int value in Zig -- a zero.
|
|
191
|
+
//
|
|
192
|
+
// This mirrors the handling of infinities, where libc also expects
|
|
193
|
+
// unspecified for the value of `*e` and Zig std sets it to a zero.
|
|
194
|
+
if (math.isNan(x)) {
|
|
195
|
+
e.* = 0;
|
|
196
|
+
return x;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const r = math.frexp(x);
|
|
200
|
+
e.* = r.exponent;
|
|
201
|
+
return r.significand;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
fn frexp(x: f64, e: *c_int) callconv(.c) f64 {
|
|
205
|
+
return frexpGeneric(f64, x, e);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
fn frexpf(x: f32, e: *c_int) callconv(.c) f32 {
|
|
209
|
+
return frexpGeneric(f32, x, e);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
fn frexpl(x: c_longdouble, e: *c_int) callconv(.c) c_longdouble {
|
|
213
|
+
return frexpGeneric(c_longdouble, x, e);
|
|
214
|
+
}
|
|
215
|
+
|
|
164
216
|
fn hypot(x: f64, y: f64) callconv(.c) f64 {
|
|
165
217
|
return math.hypot(x, y);
|
|
166
218
|
}
|
|
@@ -185,6 +237,14 @@ fn isnanl(x: c_longdouble) callconv(.c) c_int {
|
|
|
185
237
|
return if (math.isNan(x)) 1 else 0;
|
|
186
238
|
}
|
|
187
239
|
|
|
240
|
+
fn lrint(x: f64) callconv(.c) c_long {
|
|
241
|
+
return @intFromFloat(rint(x));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
fn lrintf(x: f32) callconv(.c) c_long {
|
|
245
|
+
return @intFromFloat(rintf(x));
|
|
246
|
+
}
|
|
247
|
+
|
|
188
248
|
fn modfGeneric(comptime T: type, x: T, iptr: *T) T {
|
|
189
249
|
if (math.isNegativeInf(x)) {
|
|
190
250
|
iptr.* = -math.inf(T);
|
|
@@ -299,7 +359,7 @@ fn pow10f(x: f32) callconv(.c) f32 {
|
|
|
299
359
|
}
|
|
300
360
|
|
|
301
361
|
fn rint(x: f64) callconv(.c) f64 {
|
|
302
|
-
const toint: f64 = 1.0 /
|
|
362
|
+
const toint: f64 = 1.0 / math.floatEps(f64);
|
|
303
363
|
const a: u64 = @bitCast(x);
|
|
304
364
|
const e = a >> 52 & 0x7ff;
|
|
305
365
|
const s = a >> 63;
|
|
@@ -319,39 +379,70 @@ fn rint(x: f64) callconv(.c) f64 {
|
|
|
319
379
|
return y;
|
|
320
380
|
}
|
|
321
381
|
|
|
322
|
-
|
|
382
|
+
fn rintf(x: f32) callconv(.c) f32 {
|
|
383
|
+
const toint: f32 = 1.0 / math.floatEps(f32);
|
|
384
|
+
const a: u32 = @bitCast(x);
|
|
385
|
+
const e = a >> 23 & 0xff;
|
|
386
|
+
const s = a >> 31;
|
|
387
|
+
var y: f32 = undefined;
|
|
388
|
+
|
|
389
|
+
if (e >= 0x7f + 23) {
|
|
390
|
+
return x;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (s == 1) {
|
|
394
|
+
y = x - toint + toint;
|
|
395
|
+
} else {
|
|
396
|
+
y = x + toint - toint;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (y == 0) {
|
|
400
|
+
return if (s == 1) -0.0 else 0;
|
|
401
|
+
}
|
|
402
|
+
return y;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
fn testRint(comptime T: type) !void {
|
|
406
|
+
const f = switch (T) {
|
|
407
|
+
f32 => rintf,
|
|
408
|
+
f64 => rint,
|
|
409
|
+
else => @compileError("rint not implemented for" ++ @typeName(T)),
|
|
410
|
+
};
|
|
411
|
+
|
|
323
412
|
// Positive numbers round correctly
|
|
324
|
-
try expectEqual(@as(
|
|
325
|
-
try expectEqual(@as(
|
|
413
|
+
try expectEqual(@as(T, 42.0), f(42.2));
|
|
414
|
+
try expectEqual(@as(T, 42.0), f(41.8));
|
|
326
415
|
|
|
327
416
|
// Negative numbers round correctly
|
|
328
|
-
try expectEqual(@as(
|
|
329
|
-
try expectEqual(@as(
|
|
417
|
+
try expectEqual(@as(T, -6.0), f(-5.9));
|
|
418
|
+
try expectEqual(@as(T, -6.0), f(-6.1));
|
|
330
419
|
|
|
331
420
|
// No rounding needed test
|
|
332
|
-
try expectEqual(@as(
|
|
333
|
-
try expectEqual(@as(
|
|
334
|
-
try expectEqual(@as(
|
|
421
|
+
try expectEqual(@as(T, 5.0), f(5.0));
|
|
422
|
+
try expectEqual(@as(T, -10.0), f(-10.0));
|
|
423
|
+
try expectEqual(@as(T, 0.0), f(0.0));
|
|
335
424
|
|
|
336
425
|
// Very large numbers return unchanged
|
|
337
|
-
const large:
|
|
338
|
-
try expectEqual(large,
|
|
339
|
-
try expectEqual(-large,
|
|
426
|
+
const large: T = 9007199254740992.0; // 2^53
|
|
427
|
+
try expectEqual(large, f(large));
|
|
428
|
+
try expectEqual(-large, f(-large));
|
|
340
429
|
|
|
341
430
|
// Small positive numbers round to zero
|
|
342
|
-
const pos_result =
|
|
343
|
-
try
|
|
344
|
-
try expect(@as(u64, @bitCast(pos_result)) == 0);
|
|
431
|
+
const pos_result = f(0.3);
|
|
432
|
+
try expect(math.isPositiveZero(pos_result));
|
|
345
433
|
|
|
346
434
|
// Small negative numbers round to negative zero
|
|
347
|
-
const neg_result =
|
|
348
|
-
try
|
|
349
|
-
const bits: u64 = @bitCast(neg_result);
|
|
350
|
-
try expect((bits >> 63) == 1);
|
|
435
|
+
const neg_result = f(-0.3);
|
|
436
|
+
try expect(math.isNegativeZero(neg_result));
|
|
351
437
|
|
|
352
438
|
// Exact half rounds to nearest even (banker's rounding)
|
|
353
|
-
try expectEqual(@as(
|
|
354
|
-
try expectEqual(@as(
|
|
439
|
+
try expectEqual(@as(T, 2.0), f(2.5));
|
|
440
|
+
try expectEqual(@as(T, 4.0), f(3.5));
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
test "rint" {
|
|
444
|
+
try testRint(f32);
|
|
445
|
+
try testRint(f64);
|
|
355
446
|
}
|
|
356
447
|
|
|
357
448
|
fn tanh(x: f64) callconv(.c) f64 {
|
|
@@ -424,6 +424,7 @@ pub fn main(init: process.Init.Minimal) !void {
|
|
|
424
424
|
fatal("unable to parse jobs count '{s}': {t}", .{ text, err });
|
|
425
425
|
if (n < 1) fatal("number of jobs must be at least 1", .{});
|
|
426
426
|
threaded.setAsyncLimit(.limited(n));
|
|
427
|
+
graph.max_jobs = n;
|
|
427
428
|
} else if (mem.eql(u8, arg, "--")) {
|
|
428
429
|
builder.args = argsRest(args, arg_idx);
|
|
429
430
|
break;
|
package/compiler/test_runner.zig
CHANGED
|
@@ -6,6 +6,7 @@ const Io = std.Io;
|
|
|
6
6
|
const fatal = std.process.fatal;
|
|
7
7
|
const testing = std.testing;
|
|
8
8
|
const assert = std.debug.assert;
|
|
9
|
+
const panic = std.debug.panic;
|
|
9
10
|
const fuzz_abi = std.Build.abi.fuzz;
|
|
10
11
|
|
|
11
12
|
pub const std_options: std.Options = .{
|
|
@@ -17,6 +18,8 @@ var fba: std.heap.FixedBufferAllocator = .init(&fba_buffer);
|
|
|
17
18
|
var fba_buffer: [8192]u8 = undefined;
|
|
18
19
|
var stdin_buffer: [4096]u8 = undefined;
|
|
19
20
|
var stdout_buffer: [4096]u8 = undefined;
|
|
21
|
+
var stdin_reader: Io.File.Reader = undefined;
|
|
22
|
+
var stdout_writer: Io.File.Writer = undefined;
|
|
20
23
|
const runner_threaded_io: Io = Io.Threaded.global_single_threaded.io();
|
|
21
24
|
|
|
22
25
|
/// Keep in sync with logic in `std.Build.addRunArtifact` which decides whether
|
|
@@ -38,10 +41,10 @@ pub fn main(init: std.process.Init.Minimal) void {
|
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
if (need_simple) {
|
|
41
|
-
return mainSimple() catch |err|
|
|
44
|
+
return mainSimple() catch |err| panic("test failure: {t}", .{err});
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
const args = init.args.toSlice(fba.allocator()) catch |err|
|
|
47
|
+
const args = init.args.toSlice(fba.allocator()) catch |err| panic("unable to parse command line args: {t}", .{err});
|
|
45
48
|
|
|
46
49
|
var listen = false;
|
|
47
50
|
var opt_cache_dir: ?[]const u8 = null;
|
|
@@ -55,7 +58,7 @@ pub fn main(init: std.process.Init.Minimal) void {
|
|
|
55
58
|
} else if (std.mem.startsWith(u8, arg, "--cache-dir")) {
|
|
56
59
|
opt_cache_dir = arg["--cache-dir=".len..];
|
|
57
60
|
} else {
|
|
58
|
-
|
|
61
|
+
panic("unrecognized command line argument: {s}", .{arg});
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -65,7 +68,7 @@ pub fn main(init: std.process.Init.Minimal) void {
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
if (listen) {
|
|
68
|
-
return mainServer(init) catch |err|
|
|
71
|
+
return mainServer(init) catch |err| panic("internal test runner failure: {t}", .{err});
|
|
69
72
|
} else {
|
|
70
73
|
return mainTerminal(init);
|
|
71
74
|
}
|
|
@@ -73,24 +76,14 @@ pub fn main(init: std.process.Init.Minimal) void {
|
|
|
73
76
|
|
|
74
77
|
fn mainServer(init: std.process.Init.Minimal) !void {
|
|
75
78
|
@disableInstrumentation();
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer);
|
|
80
|
+
stdout_writer = .initStreaming(.stdout(), runner_threaded_io, &stdout_buffer);
|
|
78
81
|
var server = try std.zig.Server.init(.{
|
|
79
82
|
.in = &stdin_reader.interface,
|
|
80
83
|
.out = &stdout_writer.interface,
|
|
81
84
|
.zig_version = builtin.zig_version_string,
|
|
82
85
|
});
|
|
83
86
|
|
|
84
|
-
if (builtin.fuzz) {
|
|
85
|
-
const coverage = fuzz_abi.fuzzer_coverage();
|
|
86
|
-
try server.serveCoverageIdMessage(
|
|
87
|
-
coverage.id,
|
|
88
|
-
coverage.runs,
|
|
89
|
-
coverage.unique,
|
|
90
|
-
coverage.seen,
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
87
|
while (true) {
|
|
95
88
|
const hdr = try server.receiveMessage();
|
|
96
89
|
switch (hdr.tag) {
|
|
@@ -180,48 +173,75 @@ fn mainServer(init: std.process.Init.Minimal) !void {
|
|
|
180
173
|
// since they are not present.
|
|
181
174
|
if (!builtin.fuzz) unreachable;
|
|
182
175
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
defer testing.allocator.free(name);
|
|
192
|
-
for (0.., builtin.test_functions) |i, test_fn| {
|
|
193
|
-
if (std.mem.eql(u8, name, test_fn.name)) {
|
|
194
|
-
break :index i;
|
|
195
|
-
}
|
|
196
|
-
} else {
|
|
197
|
-
std.debug.panic("fuzz test {s} no longer exists", .{name});
|
|
198
|
-
}
|
|
176
|
+
var gpa_instance: std.heap.DebugAllocator(.{}) = .init;
|
|
177
|
+
defer if (gpa_instance.deinit() == .leak) {
|
|
178
|
+
@panic("internal test runner memory leak");
|
|
179
|
+
};
|
|
180
|
+
const gpa = gpa_instance.allocator();
|
|
181
|
+
var io_instance: Io.Threaded = .init(gpa, .{
|
|
182
|
+
.argv0 = .init(init.args),
|
|
183
|
+
.environ = init.environ,
|
|
199
184
|
});
|
|
185
|
+
defer io_instance.deinit();
|
|
186
|
+
const io = io_instance.io();
|
|
187
|
+
|
|
200
188
|
const mode: fuzz_abi.LimitKind = @enumFromInt(try server.receiveBody_u8());
|
|
201
189
|
const amount_or_instance = try server.receiveBody_u64();
|
|
190
|
+
const main_instance = mode == .iterations or amount_or_instance == 0;
|
|
191
|
+
|
|
192
|
+
if (main_instance) {
|
|
193
|
+
const coverage = fuzz_abi.fuzzer_coverage();
|
|
194
|
+
try server.serveCoverageIdMessage(
|
|
195
|
+
coverage.id,
|
|
196
|
+
coverage.runs,
|
|
197
|
+
coverage.unique,
|
|
198
|
+
coverage.seen,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
202
201
|
|
|
203
|
-
const
|
|
204
|
-
const
|
|
202
|
+
const n_tests: u32 = try server.receiveBody_u32();
|
|
203
|
+
const test_indexes = try gpa.alloc(u32, n_tests);
|
|
204
|
+
defer gpa.free(test_indexes);
|
|
205
|
+
fuzz_runner = .{
|
|
206
|
+
.indexes = test_indexes,
|
|
207
|
+
.server = &server,
|
|
208
|
+
.gpa = gpa,
|
|
209
|
+
.io = io,
|
|
210
|
+
.input_poller = undefined,
|
|
211
|
+
};
|
|
205
212
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
213
|
+
{
|
|
214
|
+
var large_name_buf: std.ArrayList(u8) = .empty;
|
|
215
|
+
defer large_name_buf.deinit(gpa);
|
|
216
|
+
for (test_indexes) |*i| {
|
|
217
|
+
const name_len = try server.receiveBody_u32();
|
|
218
|
+
const name = if (name_len <= server.in.buffer.len)
|
|
219
|
+
try server.in.take(name_len)
|
|
220
|
+
else large_name: {
|
|
221
|
+
try large_name_buf.resize(gpa, name_len);
|
|
222
|
+
try server.in.readSliceAll(large_name_buf.items);
|
|
223
|
+
break :large_name large_name_buf.items;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
for (0.., builtin.test_functions) |test_i, test_fn| {
|
|
227
|
+
if (std.mem.eql(u8, name, test_fn.name)) {
|
|
228
|
+
i.* = @intCast(test_i);
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
panic("fuzz test {s} no longer exists", .{name});
|
|
233
|
+
}
|
|
212
234
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
std.debug.dumpStackTrace(trace);
|
|
235
|
+
if (main_instance) {
|
|
236
|
+
const relocated_entry_addr = @intFromPtr(builtin.test_functions[i.*].func);
|
|
237
|
+
const entry_addr = fuzz_abi.fuzzer_unslide_address(relocated_entry_addr);
|
|
238
|
+
try server.serveU64Message(.fuzz_start_addr, entry_addr);
|
|
218
239
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (log_err_count != 0) @panic("error logs detected");
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
fuzz_abi.fuzzer_main(n_tests, testing.random_seed, mode, amount_or_instance);
|
|
244
|
+
|
|
225
245
|
assert(mode != .forever);
|
|
226
246
|
std.process.exit(0);
|
|
227
247
|
},
|
|
@@ -382,16 +402,126 @@ pub fn mainSimple() anyerror!void {
|
|
|
382
402
|
passed += 1;
|
|
383
403
|
}
|
|
384
404
|
if (enable_print) {
|
|
385
|
-
var
|
|
386
|
-
|
|
405
|
+
var unbuffered_stdout_writer = stdout.writer(runner_threaded_io, &.{});
|
|
406
|
+
unbuffered_stdout_writer.interface.print(
|
|
407
|
+
"{} passed, {} skipped, {} failed\n",
|
|
408
|
+
.{ passed, skipped, failed },
|
|
409
|
+
) catch {};
|
|
387
410
|
}
|
|
388
411
|
if (failed != 0) std.process.exit(1);
|
|
389
412
|
}
|
|
390
413
|
|
|
391
414
|
var is_fuzz_test: bool = undefined;
|
|
392
|
-
var
|
|
393
|
-
|
|
394
|
-
|
|
415
|
+
var fuzz_runner: if (builtin.fuzz) struct {
|
|
416
|
+
indexes: []u32,
|
|
417
|
+
server: *std.zig.Server,
|
|
418
|
+
gpa: std.mem.Allocator,
|
|
419
|
+
io: Io,
|
|
420
|
+
input_poller: Io.Future(Io.Cancelable!void),
|
|
421
|
+
|
|
422
|
+
comptime {
|
|
423
|
+
assert(builtin.fuzz); // `fuzz_runner` was analyzed in non-fuzzing compilation
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export fn runner_test_run(i: u32) void {
|
|
427
|
+
@disableInstrumentation();
|
|
428
|
+
|
|
429
|
+
fuzz_runner.server.serveU32Message(.fuzz_test_change, i) catch |e| switch (e) {
|
|
430
|
+
error.WriteFailed => panic("failed to write to stdout: {t}", .{stdout_writer.err.?}),
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
testing.allocator_instance = .{};
|
|
434
|
+
defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1);
|
|
435
|
+
is_fuzz_test = false;
|
|
436
|
+
|
|
437
|
+
builtin.test_functions[fuzz_runner.indexes[i]].func() catch |err| switch (err) {
|
|
438
|
+
error.SkipZigTest => return,
|
|
439
|
+
else => {
|
|
440
|
+
if (@errorReturnTrace()) |trace| {
|
|
441
|
+
std.debug.dumpStackTrace(trace);
|
|
442
|
+
}
|
|
443
|
+
std.debug.print("failed with error.{t}\n", .{err});
|
|
444
|
+
std.process.exit(1);
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
if (!is_fuzz_test) @panic("missed call to std.testing.fuzz");
|
|
449
|
+
if (log_err_count != 0) @panic("error logs detected");
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export fn runner_test_name(i: u32) fuzz_abi.Slice {
|
|
453
|
+
@disableInstrumentation();
|
|
454
|
+
return .fromSlice(builtin.test_functions[fuzz_runner.indexes[i]].name);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export fn runner_broadcast_input(test_i: u32, bytes_slice: fuzz_abi.Slice) void {
|
|
458
|
+
@disableInstrumentation();
|
|
459
|
+
const bytes = bytes_slice.toSlice();
|
|
460
|
+
fuzz_runner.server.serveBroadcastFuzzInputMessage(test_i, bytes) catch |e| switch (e) {
|
|
461
|
+
error.WriteFailed => panic("failed to write to stdout: {t}", .{stdout_writer.err.?}),
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export fn runner_start_input_poller() void {
|
|
466
|
+
@disableInstrumentation();
|
|
467
|
+
const future = fuzz_runner.io.concurrent(inputPoller, .{}) catch |e| switch (e) {
|
|
468
|
+
error.ConcurrencyUnavailable => @panic("failed to spawn concurrent fuzz input poller"),
|
|
469
|
+
};
|
|
470
|
+
fuzz_runner.input_poller = future;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export fn runner_stop_input_poller() void {
|
|
474
|
+
@disableInstrumentation();
|
|
475
|
+
assert(fuzz_runner.input_poller.cancel(fuzz_runner.io) == error.Canceled);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export fn runner_futex_wait(ptr: *const u32, expected: u32) bool {
|
|
479
|
+
@disableInstrumentation();
|
|
480
|
+
return fuzz_runner.io.futexWait(u32, ptr, expected) == error.Canceled;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export fn runner_futex_wake(ptr: *const u32, waiters: u32) void {
|
|
484
|
+
@disableInstrumentation();
|
|
485
|
+
fuzz_runner.io.futexWake(u32, ptr, waiters);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
fn inputPoller() Io.Cancelable!void {
|
|
489
|
+
@disableInstrumentation();
|
|
490
|
+
switch (inputPollerInner()) {
|
|
491
|
+
error.Canceled => return error.Canceled,
|
|
492
|
+
error.ReadFailed => {
|
|
493
|
+
if (stdin_reader.err.? == error.Canceled) return error.Canceled;
|
|
494
|
+
panic("failed to read from stdin: {t}", .{stdin_reader.err.?});
|
|
495
|
+
},
|
|
496
|
+
error.EndOfStream => @panic("unexpected end of stdin"),
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
fn inputPollerInner() (Io.Cancelable || Io.Reader.Error) {
|
|
501
|
+
@disableInstrumentation();
|
|
502
|
+
const server = fuzz_runner.server;
|
|
503
|
+
var large_bytes_list: std.ArrayList(u8) = .empty;
|
|
504
|
+
defer large_bytes_list.deinit(fuzz_runner.gpa);
|
|
505
|
+
while (true) {
|
|
506
|
+
const hdr = try server.receiveMessage();
|
|
507
|
+
if (hdr.tag != .new_fuzz_input) {
|
|
508
|
+
panic("unexpected message: {x}\n", .{@intFromEnum(hdr.tag)});
|
|
509
|
+
}
|
|
510
|
+
const test_i = try server.receiveBody_u32();
|
|
511
|
+
const input_len = hdr.bytes_len - 4;
|
|
512
|
+
const bytes = if (input_len <= server.in.buffer.len)
|
|
513
|
+
try server.in.take(input_len)
|
|
514
|
+
else bytes: {
|
|
515
|
+
large_bytes_list.resize(fuzz_runner.gpa, @intCast(input_len)) catch @panic("OOM");
|
|
516
|
+
try server.in.readSliceAll(large_bytes_list.items);
|
|
517
|
+
break :bytes large_bytes_list.items;
|
|
518
|
+
};
|
|
519
|
+
if (fuzz_abi.fuzzer_receive_input(test_i, .fromSlice(bytes))) {
|
|
520
|
+
return error.Canceled;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
} else void = undefined;
|
|
395
525
|
|
|
396
526
|
pub fn fuzz(
|
|
397
527
|
context: anytype,
|
|
@@ -448,16 +578,18 @@ pub fn fuzz(
|
|
|
448
578
|
return false;
|
|
449
579
|
}
|
|
450
580
|
};
|
|
581
|
+
|
|
451
582
|
if (builtin.fuzz) {
|
|
583
|
+
// Preserve the calling test's allocator state
|
|
452
584
|
const prev_allocator_state = testing.allocator_instance;
|
|
453
585
|
testing.allocator_instance = .{};
|
|
454
586
|
defer testing.allocator_instance = prev_allocator_state;
|
|
455
|
-
global.ctx = context;
|
|
456
587
|
|
|
457
|
-
|
|
588
|
+
global.ctx = context;
|
|
589
|
+
fuzz_abi.fuzzer_set_test(&global.test_one);
|
|
458
590
|
for (options.corpus) |elem|
|
|
459
591
|
fuzz_abi.fuzzer_new_input(.fromSlice(elem));
|
|
460
|
-
fuzz_abi.
|
|
592
|
+
fuzz_abi.fuzzer_start_test();
|
|
461
593
|
return;
|
|
462
594
|
}
|
|
463
595
|
|