aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-24 10:44:41 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-24 10:44:41 -0700
commite86cee258cb0eefca14a94f6b3abb39e8a5f2ef9 (patch)
tree6d9aa3b21685b1581787246f953db94cdb486693 /lib/std
parent224fbb23c44628b215662c6199dff11cc2851f04 (diff)
parent8530b6b7242ebf43b5cb4ae3a2644593f4961a5e (diff)
downloadzig-e86cee258cb0eefca14a94f6b3abb39e8a5f2ef9.tar.gz
zig-e86cee258cb0eefca14a94f6b3abb39e8a5f2ef9.zip
Merge remote-tracking branch 'origin/master' into stage2-whole-file-astgen
In particular I wanted the change that makes `suspend;` illegal in the parser.
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/atomic/bool.zig2
-rw-r--r--lib/std/atomic/int.zig4
-rw-r--r--lib/std/build.zig5
-rw-r--r--lib/std/crypto.zig2
-rw-r--r--lib/std/crypto/25519/curve25519.zig20
-rw-r--r--lib/std/crypto/25519/ed25519.zig34
-rw-r--r--lib/std/crypto/25519/edwards25519.zig83
-rw-r--r--lib/std/crypto/25519/field.zig9
-rw-r--r--lib/std/crypto/25519/ristretto255.zig14
-rw-r--r--lib/std/crypto/25519/scalar.zig5
-rw-r--r--lib/std/crypto/25519/x25519.zig15
-rw-r--r--lib/std/crypto/aegis.zig6
-rw-r--r--lib/std/crypto/aes_gcm.zig4
-rw-r--r--lib/std/crypto/aes_ocb.zig4
-rw-r--r--lib/std/crypto/bcrypt.zig11
-rw-r--r--lib/std/crypto/chacha20.zig6
-rw-r--r--lib/std/crypto/error.zig34
-rw-r--r--lib/std/crypto/errors.zig35
-rw-r--r--lib/std/crypto/gimli.zig4
-rw-r--r--lib/std/crypto/isap.zig4
-rw-r--r--lib/std/crypto/pbkdf2.zig5
-rw-r--r--lib/std/crypto/salsa20.zig19
-rw-r--r--lib/std/event/rwlock.zig4
-rw-r--r--lib/std/math.zig9
-rw-r--r--lib/std/math/sqrt.zig20
-rw-r--r--lib/std/meta.zig18
-rw-r--r--lib/std/os/bits/linux/powerpc.zig10
-rw-r--r--lib/std/os/linux.zig50
-rw-r--r--lib/std/os/linux/bpf/btf.zig2
-rw-r--r--lib/std/os/windows/user32.zig2
-rw-r--r--lib/std/special/c.zig151
-rw-r--r--lib/std/special/compiler_rt.zig4
-rw-r--r--lib/std/special/compiler_rt/extendXfYf2.zig4
-rw-r--r--lib/std/special/compiler_rt/extendXfYf2_test.zig49
-rw-r--r--lib/std/special/compiler_rt/truncXfYf2.zig6
-rw-r--r--lib/std/special/compiler_rt/truncXfYf2_test.zig56
-rw-r--r--lib/std/target.zig11
-rw-r--r--lib/std/target/powerpc.zig7
-rw-r--r--lib/std/zig/parse.zig3
-rw-r--r--lib/std/zig/parser_test.zig57
-rw-r--r--lib/std/zig/render.zig11
41 files changed, 600 insertions, 199 deletions
diff --git a/lib/std/atomic/bool.zig b/lib/std/atomic/bool.zig
index c968b862b9..0cffb99d38 100644
--- a/lib/std/atomic/bool.zig
+++ b/lib/std/atomic/bool.zig
@@ -28,7 +28,7 @@ pub const Bool = extern struct {
return @atomicRmw(bool, &self.unprotected_value, .Xchg, operand, ordering);
}
- pub fn load(self: *Self, comptime ordering: std.builtin.AtomicOrder) bool {
+ pub fn load(self: *const Self, comptime ordering: std.builtin.AtomicOrder) bool {
switch (ordering) {
.Unordered, .Monotonic, .Acquire, .SeqCst => {},
else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),
diff --git a/lib/std/atomic/int.zig b/lib/std/atomic/int.zig
index 1a3bead2df..2d1c5f80e9 100644
--- a/lib/std/atomic/int.zig
+++ b/lib/std/atomic/int.zig
@@ -31,7 +31,7 @@ pub fn Int(comptime T: type) type {
return @atomicRmw(T, &self.unprotected_value, op, operand, ordering);
}
- pub fn load(self: *Self, comptime ordering: builtin.AtomicOrder) T {
+ pub fn load(self: *const Self, comptime ordering: builtin.AtomicOrder) T {
switch (ordering) {
.Unordered, .Monotonic, .Acquire, .SeqCst => {},
else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),
@@ -59,7 +59,7 @@ pub fn Int(comptime T: type) type {
return self.rmw(.Sub, 1, .SeqCst);
}
- pub fn get(self: *Self) T {
+ pub fn get(self: *const Self) T {
return self.load(.SeqCst);
}
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 22c22c1961..ff2a16d2b9 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -1386,6 +1386,8 @@ pub const LibExeObjStep = struct {
/// safely garbage-collected during the linking phase.
link_function_sections: bool = false,
+ linker_allow_shlib_undefined: ?bool = null,
+
/// Uses system Wine installation to run cross compiled Windows build artifacts.
enable_wine: bool = false,
@@ -2338,6 +2340,9 @@ pub const LibExeObjStep = struct {
if (self.link_function_sections) {
try zig_args.append("-ffunction-sections");
}
+ if (self.linker_allow_shlib_undefined) |x| {
+ try zig_args.append(if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");
+ }
if (self.single_threaded) {
try zig_args.append("--single-threaded");
}
diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig
index 457b9130d9..e4ec50f5b7 100644
--- a/lib/std/crypto.zig
+++ b/lib/std/crypto.zig
@@ -154,7 +154,7 @@ pub const random = &@import("crypto/tlcsprng.zig").interface;
const std = @import("std.zig");
-pub const Error = @import("crypto/error.zig").Error;
+pub const errors = @import("crypto/errors.zig");
test "crypto" {
const please_windows_dont_oom = std.Target.current.os.tag == .windows;
diff --git a/lib/std/crypto/25519/curve25519.zig b/lib/std/crypto/25519/curve25519.zig
index fd9d426bf8..65d709bcb3 100644
--- a/lib/std/crypto/25519/curve25519.zig
+++ b/lib/std/crypto/25519/curve25519.zig
@@ -4,7 +4,11 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
-const Error = std.crypto.Error;
+const crypto = std.crypto;
+
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// Group operations over Curve25519.
pub const Curve25519 = struct {
@@ -29,12 +33,12 @@ pub const Curve25519 = struct {
pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };
/// Check that the encoding of a Curve25519 point is canonical.
- pub fn rejectNonCanonical(s: [32]u8) Error!void {
+ pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
return Fe.rejectNonCanonical(s, false);
}
/// Reject the neutral element.
- pub fn rejectIdentity(p: Curve25519) Error!void {
+ pub fn rejectIdentity(p: Curve25519) IdentityElementError!void {
if (p.x.isZero()) {
return error.IdentityElement;
}
@@ -45,7 +49,7 @@ pub const Curve25519 = struct {
return p.dbl().dbl().dbl();
}
- fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) Error!Curve25519 {
+ fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) IdentityElementError!Curve25519 {
var x1 = p.x;
var x2 = Fe.one;
var z2 = Fe.zero;
@@ -86,7 +90,7 @@ pub const Curve25519 = struct {
/// way to use Curve25519 for a DH operation.
/// Return error.IdentityElement if the resulting point is
/// the identity element.
- pub fn clampedMul(p: Curve25519, s: [32]u8) Error!Curve25519 {
+ pub fn clampedMul(p: Curve25519, s: [32]u8) IdentityElementError!Curve25519 {
var t: [32]u8 = s;
scalar.clamp(&t);
return try ladder(p, t, 255);
@@ -96,16 +100,16 @@ pub const Curve25519 = struct {
/// Return error.IdentityElement if the resulting point is
/// the identity element or error.WeakPublicKey if the public
/// key is a low-order point.
- pub fn mul(p: Curve25519, s: [32]u8) Error!Curve25519 {
+ pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 {
const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;
_ = ladder(p, cofactor, 4) catch return error.WeakPublicKey;
return try ladder(p, s, 256);
}
/// Compute the Curve25519 equivalent to an Edwards25519 point.
- pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) Error!Curve25519 {
+ pub fn fromEdwards25519(p: crypto.ecc.Edwards25519) IdentityElementError!Curve25519 {
try p.clearCofactor().rejectIdentity();
- const one = std.crypto.ecc.Edwards25519.Fe.one;
+ const one = crypto.ecc.Edwards25519.Fe.one;
const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd)
return Curve25519{ .x = x };
}
diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig
index e385e34f12..b48cc24b4b 100644
--- a/lib/std/crypto/25519/ed25519.zig
+++ b/lib/std/crypto/25519/ed25519.zig
@@ -8,8 +8,15 @@ const crypto = std.crypto;
const debug = std.debug;
const fmt = std.fmt;
const mem = std.mem;
+
const Sha512 = crypto.hash.sha2.Sha512;
-const Error = crypto.Error;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const SignatureVerificationError = crypto.errors.SignatureVerificationError;
+const KeyMismatchError = crypto.errors.KeyMismatchError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// Ed25519 (EdDSA) signatures.
pub const Ed25519 = struct {
@@ -41,7 +48,7 @@ pub const Ed25519 = struct {
///
/// For this reason, an EdDSA secret key is commonly called a seed,
/// from which the actual secret is derived.
- pub fn create(seed: ?[seed_length]u8) Error!KeyPair {
+ pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
const ss = seed orelse ss: {
var random_seed: [seed_length]u8 = undefined;
crypto.random.bytes(&random_seed);
@@ -51,7 +58,7 @@ pub const Ed25519 = struct {
var h = Sha512.init(.{});
h.update(&ss);
h.final(&az);
- const p = try Curve.basePoint.clampedMul(az[0..32].*);
+ const p = Curve.basePoint.clampedMul(az[0..32].*) catch return error.IdentityElement;
var sk: [secret_length]u8 = undefined;
mem.copy(u8, &sk, &ss);
const pk = p.toBytes();
@@ -72,7 +79,7 @@ pub const Ed25519 = struct {
/// Sign a message using a key pair, and optional random noise.
/// Having noise creates non-standard, non-deterministic signatures,
/// but has been proven to increase resilience against fault attacks.
- pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) Error![signature_length]u8 {
+ pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) (IdentityElementError || WeakPublicKeyError || KeyMismatchError)![signature_length]u8 {
const seed = key_pair.secret_key[0..seed_length];
const public_key = key_pair.secret_key[seed_length..];
if (!mem.eql(u8, public_key, &key_pair.public_key)) {
@@ -113,7 +120,7 @@ pub const Ed25519 = struct {
/// Verify an Ed25519 signature given a message and a public key.
/// Returns error.SignatureVerificationFailed is the signature verification failed.
- pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) Error!void {
+ pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) (SignatureVerificationError || WeakPublicKeyError || EncodingError || NonCanonicalError || IdentityElementError)!void {
const r = sig[0..32];
const s = sig[32..64];
try Curve.scalar.rejectNonCanonical(s.*);
@@ -122,6 +129,7 @@ pub const Ed25519 = struct {
try a.rejectIdentity();
try Curve.rejectNonCanonical(r.*);
const expected_r = try Curve.fromBytes(r.*);
+ try expected_r.rejectIdentity();
var h = Sha512.init(.{});
h.update(r);
@@ -131,8 +139,7 @@ pub const Ed25519 = struct {
h.final(&hram64);
const hram = Curve.scalar.reduce64(hram64);
- const ah = try a.neg().mulPublic(hram);
- const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah);
+ const sb_ah = try Curve.basePoint.mulDoubleBasePublic(s.*, a.neg(), hram);
if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| {
return error.SignatureVerificationFailed;
} else |_| {}
@@ -146,7 +153,7 @@ pub const Ed25519 = struct {
};
/// Verify several signatures in a single operation, much faster than verifying signatures one-by-one
- pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) Error!void {
+ pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void {
var r_batch: [count][32]u8 = undefined;
var s_batch: [count][32]u8 = undefined;
var a_batch: [count]Curve = undefined;
@@ -161,6 +168,7 @@ pub const Ed25519 = struct {
try a.rejectIdentity();
try Curve.rejectNonCanonical(r.*);
const expected_r = try Curve.fromBytes(r.*);
+ try expected_r.rejectIdentity();
expected_r_batch[i] = expected_r;
r_batch[i] = r.*;
s_batch[i] = s.*;
@@ -180,7 +188,7 @@ pub const Ed25519 = struct {
var z_batch: [count]Curve.scalar.CompressedScalar = undefined;
for (z_batch) |*z| {
- std.crypto.random.bytes(z[0..16]);
+ crypto.random.bytes(z[0..16]);
mem.set(u8, z[16..], 0);
}
@@ -233,8 +241,8 @@ test "ed25519 batch verification" {
const key_pair = try Ed25519.KeyPair.create(null);
var msg1: [32]u8 = undefined;
var msg2: [32]u8 = undefined;
- std.crypto.random.bytes(&msg1);
- std.crypto.random.bytes(&msg2);
+ crypto.random.bytes(&msg1);
+ crypto.random.bytes(&msg2);
const sig1 = try Ed25519.sign(&msg1, key_pair, null);
const sig2 = try Ed25519.sign(&msg2, key_pair, null);
var signature_batch = [_]Ed25519.BatchElement{
@@ -317,13 +325,13 @@ test "ed25519 test vectors" {
.msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",
.public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",
.sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f",
- .expected = error.SignatureVerificationFailed, // 8 - non-canonical R
+ .expected = error.IdentityElement, // 8 - non-canonical R
},
Vec{
.msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",
.public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",
.sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908",
- .expected = null, // 9 - non-canonical R
+ .expected = error.IdentityElement, // 9 - non-canonical R
},
Vec{
.msg_hex = "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b",
diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig
index a7f385c365..13dacc77f9 100644
--- a/lib/std/crypto/25519/edwards25519.zig
+++ b/lib/std/crypto/25519/edwards25519.zig
@@ -4,10 +4,16 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
+const crypto = std.crypto;
const debug = std.debug;
const fmt = std.fmt;
const mem = std.mem;
-const Error = std.crypto.Error;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const NotSquareError = crypto.errors.NotSquareError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// Group operations over Edwards25519.
pub const Edwards25519 = struct {
@@ -26,7 +32,7 @@ pub const Edwards25519 = struct {
is_base: bool = false,
/// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.
- pub fn fromBytes(s: [encoded_length]u8) Error!Edwards25519 {
+ pub fn fromBytes(s: [encoded_length]u8) EncodingError!Edwards25519 {
const z = Fe.one;
const y = Fe.fromBytes(s);
var u = y.sq();
@@ -56,7 +62,7 @@ pub const Edwards25519 = struct {
}
/// Check that the encoding of a point is canonical.
- pub fn rejectNonCanonical(s: [32]u8) Error!void {
+ pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
return Fe.rejectNonCanonical(s, true);
}
@@ -81,7 +87,7 @@ pub const Edwards25519 = struct {
const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
/// Reject the neutral element.
- pub fn rejectIdentity(p: Edwards25519) Error!void {
+ pub fn rejectIdentity(p: Edwards25519) IdentityElementError!void {
if (p.x.isZero()) {
return error.IdentityElement;
}
@@ -177,7 +183,7 @@ pub const Edwards25519 = struct {
// Based on real-world benchmarks, we only use this for multi-scalar multiplication.
// NAF could be useful to half the size of precomputation tables, but we intentionally
// avoid these to keep the standard library lightweight.
- fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {
+ fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
std.debug.assert(vartime);
const e = nonAdjacentForm(s);
var q = Edwards25519.identityElement;
@@ -197,7 +203,7 @@ pub const Edwards25519 = struct {
}
// Scalar multiplication with a 4-bit window and the first 15 multiples.
- fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {
+ fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
var q = Edwards25519.identityElement;
var pos: usize = 252;
while (true) : (pos -= 4) {
@@ -232,10 +238,15 @@ pub const Edwards25519 = struct {
break :pc precompute(Edwards25519.basePoint, 15);
};
+ const basePointPc8 = comptime pc: {
+ @setEvalBranchQuota(10000);
+ break :pc precompute(Edwards25519.basePoint, 8);
+ };
+
/// Multiply an Edwards25519 point by a scalar without clamping it.
- /// Return error.WeakPublicKey if the resulting point is
- /// the identity element.
- pub fn mul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {
+ /// Return error.WeakPublicKey if the base generates a small-order group,
+ /// and error.IdentityElement if the result is the identity element.
+ pub fn mul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
const pc = if (p.is_base) basePointPc else pc: {
const xpc = precompute(p, 15);
xpc[4].rejectIdentity() catch return error.WeakPublicKey;
@@ -246,7 +257,7 @@ pub const Edwards25519 = struct {
/// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME*
/// This can be used for signature verification.
- pub fn mulPublic(p: Edwards25519, s: [32]u8) Error!Edwards25519 {
+ pub fn mulPublic(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
if (p.is_base) {
return pcMul16(basePointPc, s, true);
} else {
@@ -256,14 +267,50 @@ pub const Edwards25519 = struct {
}
}
+ /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
+ /// This can be used for signature verification.
+ pub fn mulDoubleBasePublic(p1: Edwards25519, s1: [32]u8, p2: Edwards25519, s2: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
+ const pc1 = if (p1.is_base) basePointPc8 else pc: {
+ const xpc = precompute(p1, 8);
+ xpc[4].rejectIdentity() catch return error.WeakPublicKey;
+ break :pc xpc;
+ };
+ const pc2 = if (p2.is_base) basePointPc8 else pc: {
+ const xpc = precompute(p2, 8);
+ xpc[4].rejectIdentity() catch return error.WeakPublicKey;
+ break :pc xpc;
+ };
+ const e1 = nonAdjacentForm(s1);
+ const e2 = nonAdjacentForm(s2);
+ var q = Edwards25519.identityElement;
+ var pos: usize = 2 * 32 - 1;
+ while (true) : (pos -= 1) {
+ const slot1 = e1[pos];
+ if (slot1 > 0) {
+ q = q.add(pc1[@intCast(usize, slot1)]);
+ } else if (slot1 < 0) {
+ q = q.sub(pc1[@intCast(usize, -slot1)]);
+ }
+ const slot2 = e2[pos];
+ if (slot2 > 0) {
+ q = q.add(pc2[@intCast(usize, slot2)]);
+ } else if (slot2 < 0) {
+ q = q.sub(pc2[@intCast(usize, -slot2)]);
+ }
+ if (pos == 0) break;
+ q = q.dbl().dbl().dbl().dbl();
+ }
+ try q.rejectIdentity();
+ return q;
+ }
+
/// Multiscalar multiplication *IN VARIABLE TIME* for public data
/// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually
- pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) Error!Edwards25519 {
+ pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
var pcs: [count][9]Edwards25519 = undefined;
for (ps) |p, i| {
if (p.is_base) {
- @setEvalBranchQuota(10000);
- pcs[i] = comptime precompute(Edwards25519.basePoint, 8);
+ pcs[i] = basePointPc8;
} else {
pcs[i] = precompute(p, 8);
pcs[i][4].rejectIdentity() catch return error.WeakPublicKey;
@@ -297,14 +344,14 @@ pub const Edwards25519 = struct {
/// This is strongly recommended for DH operations.
/// Return error.WeakPublicKey if the resulting point is
/// the identity element.
- pub fn clampedMul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {
+ pub fn clampedMul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
var t: [32]u8 = s;
scalar.clamp(&t);
return mul(p, t);
}
// montgomery -- recover y = sqrt(x^3 + A*x^2 + x)
- fn xmontToYmont(x: Fe) Error!Fe {
+ fn xmontToYmont(x: Fe) NotSquareError!Fe {
var x2 = x.sq();
const x3 = x.mul(x2);
x2 = x2.mul32(Fe.edwards25519a_32);
@@ -367,7 +414,7 @@ pub const Edwards25519 = struct {
fn stringToPoints(comptime n: usize, ctx: []const u8, s: []const u8) [n]Edwards25519 {
debug.assert(n <= 2);
- const H = std.crypto.hash.sha2.Sha512;
+ const H = crypto.hash.sha2.Sha512;
const h_l: usize = 48;
var xctx = ctx;
var hctx: [H.digest_length]u8 = undefined;
@@ -485,8 +532,8 @@ test "edwards25519 packing/unpacking" {
test "edwards25519 point addition/substraction" {
var s1: [32]u8 = undefined;
var s2: [32]u8 = undefined;
- std.crypto.random.bytes(&s1);
- std.crypto.random.bytes(&s2);
+ crypto.random.bytes(&s1);
+ crypto.random.bytes(&s2);
const p = try Edwards25519.basePoint.clampedMul(s1);
const q = try Edwards25519.basePoint.clampedMul(s2);
const r = p.add(q).add(q).sub(q).sub(q);
diff --git a/lib/std/crypto/25519/field.zig b/lib/std/crypto/25519/field.zig
index b570e2d06b..5ac184080c 100644
--- a/lib/std/crypto/25519/field.zig
+++ b/lib/std/crypto/25519/field.zig
@@ -4,9 +4,12 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
+const crypto = std.crypto;
const readIntLittle = std.mem.readIntLittle;
const writeIntLittle = std.mem.writeIntLittle;
-const Error = std.crypto.Error;
+
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const NotSquareError = crypto.errors.NotSquareError;
pub const Fe = struct {
limbs: [5]u64,
@@ -113,7 +116,7 @@ pub const Fe = struct {
}
/// Reject non-canonical encodings of an element, possibly ignoring the top bit
- pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) Error!void {
+ pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) NonCanonicalError!void {
var c: u16 = (s[31] & 0x7f) ^ 0x7f;
comptime var i = 30;
inline while (i > 0) : (i -= 1) {
@@ -413,7 +416,7 @@ pub const Fe = struct {
}
/// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square
- pub fn sqrt(x2: Fe) Error!Fe {
+ pub fn sqrt(x2: Fe) NotSquareError!Fe {
var x2_copy = x2;
const x = x2.uncheckedSqrt();
const check = x.sq().sub(x2_copy);
diff --git a/lib/std/crypto/25519/ristretto255.zig b/lib/std/crypto/25519/ristretto255.zig
index 4644b7622e..50f1580a80 100644
--- a/lib/std/crypto/25519/ristretto255.zig
+++ b/lib/std/crypto/25519/ristretto255.zig
@@ -5,7 +5,11 @@
// and substantial portions of the software.
const std = @import("std");
const fmt = std.fmt;
-const Error = std.crypto.Error;
+
+const EncodingError = std.crypto.errors.EncodingError;
+const IdentityElementError = std.crypto.errors.IdentityElementError;
+const NonCanonicalError = std.crypto.errors.NonCanonicalError;
+const WeakPublicKeyError = std.crypto.errors.WeakPublicKeyError;
/// Group operations over Edwards25519.
pub const Ristretto255 = struct {
@@ -35,7 +39,7 @@ pub const Ristretto255 = struct {
return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() };
}
- fn rejectNonCanonical(s: [encoded_length]u8) Error!void {
+ fn rejectNonCanonical(s: [encoded_length]u8) NonCanonicalError!void {
if ((s[0] & 1) != 0) {
return error.NonCanonical;
}
@@ -43,7 +47,7 @@ pub const Ristretto255 = struct {
}
/// Reject the neutral element.
- pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) Error!void {
+ pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) IdentityElementError!void {
return p.p.rejectIdentity();
}
@@ -51,7 +55,7 @@ pub const Ristretto255 = struct {
pub const basePoint = Ristretto255{ .p = Curve.basePoint };
/// Decode a Ristretto255 representative.
- pub fn fromBytes(s: [encoded_length]u8) Error!Ristretto255 {
+ pub fn fromBytes(s: [encoded_length]u8) (NonCanonicalError || EncodingError)!Ristretto255 {
try rejectNonCanonical(s);
const s_ = Fe.fromBytes(s);
const ss = s_.sq(); // s^2
@@ -154,7 +158,7 @@ pub const Ristretto255 = struct {
/// Multiply a Ristretto255 element with a scalar.
/// Return error.WeakPublicKey if the resulting element is
/// the identity element.
- pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) Error!Ristretto255 {
+ pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) (IdentityElementError || WeakPublicKeyError)!Ristretto255 {
return Ristretto255{ .p = try p.p.mul(s) };
}
diff --git a/lib/std/crypto/25519/scalar.zig b/lib/std/crypto/25519/scalar.zig
index a4bf5aafcf..21578486e8 100644
--- a/lib/std/crypto/25519/scalar.zig
+++ b/lib/std/crypto/25519/scalar.zig
@@ -5,7 +5,8 @@
// and substantial portions of the software.
const std = @import("std");
const mem = std.mem;
-const Error = std.crypto.Error;
+
+const NonCanonicalError = std.crypto.errors.NonCanonicalError;
/// 2^252 + 27742317777372353535851937790883648493
pub const field_size = [32]u8{
@@ -19,7 +20,7 @@ pub const CompressedScalar = [32]u8;
pub const zero = [_]u8{0} ** 32;
/// Reject a scalar whose encoding is not canonical.
-pub fn rejectNonCanonical(s: [32]u8) Error!void {
+pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
var c: u8 = 0;
var n: u8 = 1;
var i: usize = 31;
diff --git a/lib/std/crypto/25519/x25519.zig b/lib/std/crypto/25519/x25519.zig
index 2d53124056..07b1dc7a86 100644
--- a/lib/std/crypto/25519/x25519.zig
+++ b/lib/std/crypto/25519/x25519.zig
@@ -9,7 +9,10 @@ const mem = std.mem;
const fmt = std.fmt;
const Sha512 = crypto.hash.sha2.Sha512;
-const Error = crypto.Error;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// X25519 DH function.
pub const X25519 = struct {
@@ -32,7 +35,7 @@ pub const X25519 = struct {
secret_key: [secret_length]u8,
/// Create a new key pair using an optional seed.
- pub fn create(seed: ?[seed_length]u8) Error!KeyPair {
+ pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
const sk = seed orelse sk: {
var random_seed: [seed_length]u8 = undefined;
crypto.random.bytes(&random_seed);
@@ -45,7 +48,7 @@ pub const X25519 = struct {
}
/// Create a key pair from an Ed25519 key pair
- pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) Error!KeyPair {
+ pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) (IdentityElementError || EncodingError)!KeyPair {
const seed = ed25519_key_pair.secret_key[0..32];
var az: [Sha512.digest_length]u8 = undefined;
Sha512.hash(seed, &az, .{});
@@ -60,13 +63,13 @@ pub const X25519 = struct {
};
/// Compute the public key for a given private key.
- pub fn recoverPublicKey(secret_key: [secret_length]u8) Error![public_length]u8 {
+ pub fn recoverPublicKey(secret_key: [secret_length]u8) IdentityElementError![public_length]u8 {
const q = try Curve.basePoint.clampedMul(secret_key);
return q.toBytes();
}
/// Compute the X25519 equivalent to an Ed25519 public eky.
- pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) Error![public_length]u8 {
+ pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) (IdentityElementError || EncodingError)![public_length]u8 {
const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key);
const pk = try Curve.fromEdwards25519(pk_ed);
return pk.toBytes();
@@ -75,7 +78,7 @@ pub const X25519 = struct {
/// Compute the scalar product of a public key and a secret scalar.
/// Note that the output should not be used as a shared secret without
/// hashing it first.
- pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) Error![shared_length]u8 {
+ pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) IdentityElementError![shared_length]u8 {
const q = try Curve.fromBytes(public_key).clampedMul(secret_key);
return q.toBytes();
}
diff --git a/lib/std/crypto/aegis.zig b/lib/std/crypto/aegis.zig
index 3969d59e10..59dcf04dac 100644
--- a/lib/std/crypto/aegis.zig
+++ b/lib/std/crypto/aegis.zig
@@ -8,7 +8,7 @@ const std = @import("std");
const mem = std.mem;
const assert = std.debug.assert;
const AesBlock = std.crypto.core.aes.Block;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
const State128L = struct {
blocks: [8]AesBlock,
@@ -137,7 +137,7 @@ pub const Aegis128L = struct {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var state = State128L.init(key, npub);
var src: [32]u8 align(16) = undefined;
@@ -299,7 +299,7 @@ pub const Aegis256 = struct {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var state = State256.init(key, npub);
var src: [16]u8 align(16) = undefined;
diff --git a/lib/std/crypto/aes_gcm.zig b/lib/std/crypto/aes_gcm.zig
index bcb1b4c5fa..70746af073 100644
--- a/lib/std/crypto/aes_gcm.zig
+++ b/lib/std/crypto/aes_gcm.zig
@@ -12,7 +12,7 @@ const debug = std.debug;
const Ghash = std.crypto.onetimeauth.Ghash;
const mem = std.mem;
const modes = crypto.core.modes;
-const Error = crypto.Error;
+const AuthenticationError = crypto.errors.AuthenticationError;
pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128);
pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256);
@@ -60,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type {
}
}
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
const aes = Aes.initEnc(key);
diff --git a/lib/std/crypto/aes_ocb.zig b/lib/std/crypto/aes_ocb.zig
index 9eb0561d9f..658b3b97ce 100644
--- a/lib/std/crypto/aes_ocb.zig
+++ b/lib/std/crypto/aes_ocb.zig
@@ -10,7 +10,7 @@ const aes = crypto.core.aes;
const assert = std.debug.assert;
const math = std.math;
const mem = std.mem;
-const Error = crypto.Error;
+const AuthenticationError = crypto.errors.AuthenticationError;
pub const Aes128Ocb = AesOcb(aes.Aes128);
pub const Aes256Ocb = AesOcb(aes.Aes256);
@@ -179,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type {
/// ad: Associated Data
/// npub: public nonce
/// k: secret key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
const aes_enc_ctx = Aes.initEnc(key);
diff --git a/lib/std/crypto/bcrypt.zig b/lib/std/crypto/bcrypt.zig
index d00108b9c4..51fb144b2f 100644
--- a/lib/std/crypto/bcrypt.zig
+++ b/lib/std/crypto/bcrypt.zig
@@ -12,7 +12,8 @@ const mem = std.mem;
const debug = std.debug;
const testing = std.testing;
const utils = crypto.utils;
-const Error = crypto.Error;
+const EncodingError = crypto.errors.EncodingError;
+const PasswordVerificationError = crypto.errors.PasswordVerificationError;
const salt_length: usize = 16;
const salt_str_length: usize = 22;
@@ -179,7 +180,7 @@ const Codec = struct {
debug.assert(j == b64.len);
}
- fn decode(bin: []u8, b64: []const u8) Error!void {
+ fn decode(bin: []u8, b64: []const u8) EncodingError!void {
var i: usize = 0;
var j: usize = 0;
while (j < bin.len) {
@@ -204,7 +205,7 @@ const Codec = struct {
}
};
-fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) Error![hash_length]u8 {
+fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) ![hash_length]u8 {
var state = State{};
var password_buf: [73]u8 = undefined;
const trimmed_len = math.min(password.len, password_buf.len - 1);
@@ -252,14 +253,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8)
/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes.
/// If this is an issue for your application, hash the password first using a function such as SHA-512,
/// and then use the resulting hash as the password parameter for bcrypt.
-pub fn strHash(password: []const u8, rounds_log: u6) Error![hash_length]u8 {
+pub fn strHash(password: []const u8, rounds_log: u6) ![hash_length]u8 {
var salt: [salt_length]u8 = undefined;
crypto.random.bytes(&salt);
return strHashInternal(password, rounds_log, salt);
}
/// Verify that a previously computed hash is valid for a given password.
-pub fn strVerify(h: [hash_length]u8, password: []const u8) Error!void {
+pub fn strVerify(h: [hash_length]u8, password: []const u8) (EncodingError || PasswordVerificationError)!void {
if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding;
if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding;
const rounds_log_str = h[4..][0..2];
diff --git a/lib/std/crypto/chacha20.zig b/lib/std/crypto/chacha20.zig
index e1fe3e232d..ea9eafd356 100644
--- a/lib/std/crypto/chacha20.zig
+++ b/lib/std/crypto/chacha20.zig
@@ -13,7 +13,7 @@ const testing = std.testing;
const maxInt = math.maxInt;
const Vector = std.meta.Vector;
const Poly1305 = std.crypto.onetimeauth.Poly1305;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
/// IETF-variant of the ChaCha20 stream cipher, as designed for TLS.
pub const ChaCha20IETF = ChaChaIETF(20);
@@ -521,7 +521,7 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type {
/// npub: public nonce
/// k: private key
/// NOTE: the check of the authentication tag is currently not done in constant time
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var polyKey = [_]u8{0} ** 32;
@@ -583,7 +583,7 @@ fn XChaChaPoly1305(comptime rounds_nb: usize) type {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
const extended = extend(k, npub, rounds_nb);
return ChaChaPoly1305(rounds_nb).decrypt(m, c, tag, ad, extended.nonce, extended.key);
}
diff --git a/lib/std/crypto/error.zig b/lib/std/crypto/error.zig
deleted file mode 100644
index 4cb12bb8f7..0000000000
--- a/lib/std/crypto/error.zig
+++ /dev/null
@@ -1,34 +0,0 @@
-pub const Error = error{
- /// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
- AuthenticationFailed,
-
- /// The requested output length is too long for the chosen algorithm
- OutputTooLong,
-
- /// Finite field operation returned the identity element
- IdentityElement,
-
- /// Encoded input cannot be decoded
- InvalidEncoding,
-
- /// The signature does't verify for the given message and public key
- SignatureVerificationFailed,
-
- /// Both a public and secret key have been provided, but they are incompatible
- KeyMismatch,
-
- /// Encoded input is not in canonical form
- NonCanonical,
-
- /// Square root has no solutions
- NotSquare,
-
- /// Verification string doesn't match the provided password and parameters
- PasswordVerificationFailed,
-
- /// Parameters would be insecure to use
- WeakParameters,
-
- /// Public key would be insecure to use
- WeakPublicKey,
-};
diff --git a/lib/std/crypto/errors.zig b/lib/std/crypto/errors.zig
new file mode 100644
index 0000000000..4d79055919
--- /dev/null
+++ b/lib/std/crypto/errors.zig
@@ -0,0 +1,35 @@
+/// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
+pub const AuthenticationError = error{AuthenticationFailed};
+
+/// The requested output length is too long for the chosen algorithm
+pub const OutputTooLongError = error{OutputTooLong};
+
+/// Finite field operation returned the identity element
+pub const IdentityElementError = error{IdentityElement};
+
+/// Encoded input cannot be decoded
+pub const EncodingError = error{InvalidEncoding};
+
+/// The signature does't verify for the given message and public key
+pub const SignatureVerificationError = error{SignatureVerificationFailed};
+
+/// Both a public and secret key have been provided, but they are incompatible
+pub const KeyMismatchError = error{KeyMismatch};
+
+/// Encoded input is not in canonical form
+pub const NonCanonicalError = error{NonCanonical};
+
+/// Square root has no solutions
+pub const NotSquareError = error{NotSquare};
+
+/// Verification string doesn't match the provided password and parameters
+pub const PasswordVerificationError = error{PasswordVerificationFailed};
+
+/// Parameters would be insecure to use
+pub const WeakParametersError = error{WeakParameters};
+
+/// Public key would be insecure to use
+pub const WeakPublicKeyError = error{WeakPublicKey};
+
+/// Any error related to cryptography operations
+pub const Error = AuthenticationError || OutputTooLongError || IdentityElementError || EncodingError || SignatureVerificationError || KeyMismatchError || NonCanonicalError || NotSquareError || PasswordVerificationError || WeakParametersError || WeakPublicKeyError;
diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig
index 111e0c5274..fb67c25343 100644
--- a/lib/std/crypto/gimli.zig
+++ b/lib/std/crypto/gimli.zig
@@ -20,7 +20,7 @@ const assert = std.debug.assert;
const testing = std.testing;
const htest = @import("test.zig");
const Vector = std.meta.Vector;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
pub const State = struct {
pub const BLOCKBYTES = 48;
@@ -393,7 +393,7 @@ pub const Aead = struct {
/// npub: public nonce
/// k: private key
/// NOTE: the check of the authentication tag is currently not done in constant time
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var state = Aead.init(ad, npub, k);
diff --git a/lib/std/crypto/isap.zig b/lib/std/crypto/isap.zig
index 5219742d85..6deb4977bb 100644
--- a/lib/std/crypto/isap.zig
+++ b/lib/std/crypto/isap.zig
@@ -3,7 +3,7 @@ const debug = std.debug;
const mem = std.mem;
const math = std.math;
const testing = std.testing;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
/// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks.
/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf
@@ -218,7 +218,7 @@ pub const IsapA128A = struct {
tag.* = mac(c, ad, npub, key);
}
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
var computed_tag = mac(c, ad, npub, key);
var acc: u8 = 0;
for (computed_tag) |_, j| {
diff --git a/lib/std/crypto/pbkdf2.zig b/lib/std/crypto/pbkdf2.zig
index 575fb83006..f93a5235af 100644
--- a/lib/std/crypto/pbkdf2.zig
+++ b/lib/std/crypto/pbkdf2.zig
@@ -7,7 +7,8 @@
const std = @import("std");
const mem = std.mem;
const maxInt = std.math.maxInt;
-const Error = std.crypto.Error;
+const OutputTooLongError = std.crypto.errors.OutputTooLongError;
+const WeakParametersError = std.crypto.errors.WeakParametersError;
// RFC 2898 Section 5.2
//
@@ -55,7 +56,7 @@ const Error = std.crypto.Error;
/// the dk. It is common to tune this parameter to achieve approximately 100ms.
///
/// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`.
-pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Error!void {
+pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) (WeakParametersError || OutputTooLongError)!void {
if (rounds < 1) return error.WeakParameters;
const dk_len = dk.len;
diff --git a/lib/std/crypto/salsa20.zig b/lib/std/crypto/salsa20.zig
index 006767c93f..2a06944adc 100644
--- a/lib/std/crypto/salsa20.zig
+++ b/lib/std/crypto/salsa20.zig
@@ -15,7 +15,10 @@ const Vector = std.meta.Vector;
const Poly1305 = crypto.onetimeauth.Poly1305;
const Blake2b = crypto.hash.blake2.Blake2b;
const X25519 = crypto.dh.X25519;
-const Error = crypto.Error;
+
+const AuthenticationError = crypto.errors.AuthenticationError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
const Salsa20VecImpl = struct {
const Lane = Vector(4, u32);
@@ -399,7 +402,7 @@ pub const XSalsa20Poly1305 = struct {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
debug.assert(c.len == m.len);
const extended = extend(k, npub);
var block0 = [_]u8{0} ** 64;
@@ -447,7 +450,7 @@ pub const SecretBox = struct {
/// Verify and decrypt `c` using a nonce `npub` and a key `k`.
/// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message.
- pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
if (c.len < tag_length) {
return error.AuthenticationFailed;
}
@@ -482,20 +485,20 @@ pub const Box = struct {
pub const KeyPair = X25519.KeyPair;
/// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key.
- pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) Error![shared_length]u8 {
+ pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)![shared_length]u8 {
const p = try X25519.scalarmult(secret_key, public_key);
const zero = [_]u8{0} ** 16;
return Salsa20Impl.hsalsa20(zero, p);
}
/// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`.
- pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {
+ pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)!void {
const shared_key = try createSharedSecret(public_key, secret_key);
return SecretBox.seal(c, m, npub, shared_key);
}
/// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`.
- pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {
+ pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
const shared_key = try createSharedSecret(public_key, secret_key);
return SecretBox.open(m, c, npub, shared_key);
}
@@ -528,7 +531,7 @@ pub const SealedBox = struct {
/// Encrypt a message `m` for a recipient whose public key is `public_key`.
/// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added.
- pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) Error!void {
+ pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void {
debug.assert(c.len == m.len + seal_length);
var ekp = try KeyPair.create(null);
const nonce = createNonce(ekp.public_key, public_key);
@@ -539,7 +542,7 @@ pub const SealedBox = struct {
/// Decrypt a message using a key pair.
/// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata.
- pub fn open(m: []u8, c: []const u8, keypair: KeyPair) Error!void {
+ pub fn open(m: []u8, c: []const u8, keypair: KeyPair) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
if (c.len < seal_length) {
return error.AuthenticationFailed;
}
diff --git a/lib/std/event/rwlock.zig b/lib/std/event/rwlock.zig
index d981956c77..5cdb0a92df 100644
--- a/lib/std/event/rwlock.zig
+++ b/lib/std/event/rwlock.zig
@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;
var shared_test_index: usize = 0;
var shared_count: usize = 0;
fn writeRunner(lock: *RwLock) callconv(.Async) void {
- suspend; // resumed by onNextTick
+ suspend {} // resumed by onNextTick
var i: usize = 0;
while (i < shared_test_data.len) : (i += 1) {
@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {
}
}
fn readRunner(lock: *RwLock) callconv(.Async) void {
- suspend; // resumed by onNextTick
+ suspend {} // resumed by onNextTick
std.time.sleep(1);
var i: usize = 0;
diff --git a/lib/std/math.zig b/lib/std/math.zig
index cb6f3cec1f..f6dfc6ec78 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -1349,15 +1349,6 @@ pub fn boolMask(comptime MaskInt: type, value: bool) callconv(.Inline) MaskInt {
return @bitCast(i1, @as(u1, @boolToInt(value)));
}
- // At comptime, -% is disallowed on unsigned values.
- // So we need to jump through some hoops in that case.
- // This is a workaround for #7951
- if (@typeInfo(@TypeOf(.{value})).Struct.fields[0].is_comptime) {
- // Since it's comptime, we don't need this to generate nice code.
- // We can just do a branch here.
- return if (value) ~@as(MaskInt, 0) else 0;
- }
-
return -%@intCast(MaskInt, @boolToInt(value));
}
diff --git a/lib/std/math/sqrt.zig b/lib/std/math/sqrt.zig
index c9e999e1d1..2cca9bf836 100644
--- a/lib/std/math/sqrt.zig
+++ b/lib/std/math/sqrt.zig
@@ -38,7 +38,13 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {
}
}
-fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int.bits / 2) {
+fn sqrt_int(comptime T: type, value: T) Sqrt(T) {
+ switch (T) {
+ u0 => return 0,
+ u1 => return value,
+ else => {},
+ }
+
var op = value;
var res: T = 0;
var one: T = 1 << (@typeInfo(T).Int.bits - 2);
@@ -57,11 +63,13 @@ fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int
one >>= 2;
}
- const ResultType = std.meta.Int(.unsigned, @typeInfo(T).Int.bits / 2);
+ const ResultType = Sqrt(T);
return @intCast(ResultType, res);
}
test "math.sqrt_int" {
+ expect(sqrt_int(u0, 0) == 0);
+ expect(sqrt_int(u1, 1) == 1);
expect(sqrt_int(u32, 3) == 1);
expect(sqrt_int(u32, 4) == 2);
expect(sqrt_int(u32, 5) == 2);
@@ -73,7 +81,13 @@ test "math.sqrt_int" {
/// Returns the return type `sqrt` will return given an operand of type `T`.
pub fn Sqrt(comptime T: type) type {
return switch (@typeInfo(T)) {
- .Int => |int| std.meta.Int(.unsigned, int.bits / 2),
+ .Int => |int| {
+ return switch (int.bits) {
+ 0 => u0,
+ 1 => u1,
+ else => std.meta.Int(.unsigned, int.bits / 2),
+ };
+ },
else => T,
};
}
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index a67e04431a..83ef3f83e0 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -884,7 +884,7 @@ pub fn Vector(comptime len: u32, comptime child: type) type {
/// Given a type and value, cast the value to the type as c would.
/// This is for translate-c and is not intended for general use.
pub fn cast(comptime DestType: type, target: anytype) DestType {
- // this function should behave like transCCast in translate-c, except it's for macros
+ // this function should behave like transCCast in translate-c, except it's for macros and enums
const SourceType = @TypeOf(target);
switch (@typeInfo(DestType)) {
.Pointer => {
@@ -921,9 +921,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
}
}
},
- .Enum => {
+ .Enum => |enum_type| {
if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) {
- return @intToEnum(DestType, target);
+ const intermediate = cast(enum_type.tag_type, target);
+ return @intToEnum(DestType, intermediate);
}
},
.Int => {
@@ -1011,6 +1012,17 @@ test "std.meta.cast" {
testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*volatile u8, 2)));
testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));
+
+ const C_ENUM = extern enum(c_int) {
+ A = 0,
+ B,
+ C,
+ _,
+ };
+ testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1));
+ testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);
+ testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);
+ testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));
}
/// Given a value returns its size as C's sizeof operator would.
diff --git a/lib/std/os/bits/linux/powerpc.zig b/lib/std/os/bits/linux/powerpc.zig
index 67be4146c4..2f86fb892a 100644
--- a/lib/std/os/bits/linux/powerpc.zig
+++ b/lib/std/os/bits/linux/powerpc.zig
@@ -557,18 +557,10 @@ pub const kernel_stat = extern struct {
size: off_t,
blksize: blksize_t,
blocks: blkcnt_t,
- __atim32: timespec32,
- __mtim32: timespec32,
- __ctim32: timespec32,
- __unused: [2]u32,
atim: timespec,
mtim: timespec,
ctim: timespec,
-
- const timespec32 = extern struct {
- tv_sec: i32,
- tv_nsec: i32,
- };
+ __unused: [2]u32,
pub fn atime(self: @This()) timespec {
return self.atim;
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 555a67cd55..d34e7d16af 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -53,6 +53,7 @@ pub fn getauxval(index: usize) usize {
// Some architectures (and some syscalls) require 64bit parameters to be passed
// in a even-aligned register pair.
const require_aligned_register_pair =
+ std.Target.current.cpu.arch.isPPC() or
std.Target.current.cpu.arch.isMIPS() or
std.Target.current.cpu.arch.isARM() or
std.Target.current.cpu.arch.isThumb();
@@ -633,7 +634,7 @@ pub fn tkill(tid: pid_t, sig: i32) usize {
}
pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize {
- return syscall2(.tgkill, @bitCast(usize, @as(isize, tgid)), @bitCast(usize, @as(isize, tid)), @bitCast(usize, @as(isize, sig)));
+ return syscall3(.tgkill, @bitCast(usize, @as(isize, tgid)), @bitCast(usize, @as(isize, tid)), @bitCast(usize, @as(isize, sig)));
}
pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {
@@ -1386,6 +1387,53 @@ pub fn madvise(address: [*]u8, len: usize, advice: u32) usize {
return syscall3(.madvise, @ptrToInt(address), len, advice);
}
+pub fn pidfd_open(pid: pid_t, flags: u32) usize {
+ return syscall2(.pidfd_open, @bitCast(usize, @as(isize, pid)), flags);
+}
+
+pub fn pidfd_getfd(pidfd: fd_t, targetfd: fd_t, flags: u32) usize {
+ return syscall3(
+ .pidfd_getfd,
+ @bitCast(usize, @as(isize, pidfd)),
+ @bitCast(usize, @as(isize, targetfd)),
+ flags,
+ );
+}
+
+pub fn pidfd_send_signal(pidfd: fd_t, sig: i32, info: ?*siginfo_t, flags: u32) usize {
+ return syscall4(
+ .pidfd_send_signal,
+ @bitCast(usize, @as(isize, pidfd)),
+ @bitCast(usize, @as(isize, sig)),
+ @ptrToInt(info),
+ flags,
+ );
+}
+
+pub fn process_vm_readv(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
+ return syscall6(
+ .process_vm_readv,
+ @bitCast(usize, @as(isize, pid)),
+ @ptrToInt(local),
+ local_count,
+ @ptrToInt(remote),
+ remote_count,
+ flags,
+ );
+}
+
+pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
+ return syscall6(
+ .process_vm_writev,
+ @bitCast(usize, @as(isize, pid)),
+ @ptrToInt(local),
+ local_count,
+ @ptrToInt(remote),
+ remote_count,
+ flags,
+ );
+}
+
test {
if (std.Target.current.os.tag == .linux) {
_ = @import("linux/test.zig");
diff --git a/lib/std/os/linux/bpf/btf.zig b/lib/std/os/linux/bpf/btf.zig
index b28f65945a..9ba3a0f942 100644
--- a/lib/std/os/linux/bpf/btf.zig
+++ b/lib/std/os/linux/bpf/btf.zig
@@ -6,7 +6,7 @@
const magic = 0xeb9f;
const version = 1;
-pub const ext = @import("ext.zig");
+pub const ext = @import("btf_ext.zig");
/// All offsets are in bytes relative to the end of this header
pub const Header = packed struct {
diff --git a/lib/std/os/windows/user32.zig b/lib/std/os/windows/user32.zig
index c03ba939ba..4694be6ece 100644
--- a/lib/std/os/windows/user32.zig
+++ b/lib/std/os/windows/user32.zig
@@ -663,7 +663,7 @@ pub fn messageBoxA(hWnd: ?HWND, lpText: [*:0]const u8, lpCaption: [*:0]const u8,
pub extern "user32" fn MessageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: ?[*:0]const u16, uType: UINT) callconv(WINAPI) i32;
pub var pfnMessageBoxW: @TypeOf(MessageBoxW) = undefined;
pub fn messageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: [*:0]const u16, uType: u32) !i32 {
- const function = selectSymbol(pfnMessageBoxW, MessageBoxW, .win2k);
+ const function = selectSymbol(MessageBoxW, pfnMessageBoxW, .win2k);
const value = function(hWnd, lpText, lpCaption, uType);
if (value != 0) return value;
switch (GetLastError()) {
diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig
index fac9d4b827..8627e976d7 100644
--- a/lib/std/special/c.zig
+++ b/lib/std/special/c.zig
@@ -88,7 +88,7 @@ test "strncpy" {
var s1: [9:0]u8 = undefined;
s1[0] = 0;
- _ = strncpy(&s1, "foobarbaz", 9);
+ _ = strncpy(&s1, "foobarbaz", @sizeOf(@TypeOf(s1)));
std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.spanZ(&s1));
}
@@ -242,7 +242,7 @@ export fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) isiz
return 0;
}
-test "test_memcmp" {
+test "memcmp" {
const base_arr = &[_]u8{ 1, 1, 1 };
const arr1 = &[_]u8{ 1, 1, 1 };
const arr2 = &[_]u8{ 1, 0, 1 };
@@ -266,7 +266,7 @@ export fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) c
return 0;
}
-test "test_bcmp" {
+test "bcmp" {
const base_arr = &[_]u8{ 1, 1, 1 };
const arr1 = &[_]u8{ 1, 1, 1 };
const arr2 = &[_]u8{ 1, 0, 1 };
@@ -862,6 +862,85 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
return @bitCast(T, ux);
}
+test "fmod, fmodf" {
+ inline for ([_]type{ f32, f64 }) |T| {
+ const nan_val = math.nan(T);
+ const inf_val = math.inf(T);
+
+ std.testing.expect(isNan(generic_fmod(T, nan_val, 1.0)));
+ std.testing.expect(isNan(generic_fmod(T, 1.0, nan_val)));
+ std.testing.expect(isNan(generic_fmod(T, inf_val, 1.0)));
+ std.testing.expect(isNan(generic_fmod(T, 0.0, 0.0)));
+ std.testing.expect(isNan(generic_fmod(T, 1.0, 0.0)));
+
+ std.testing.expectEqual(@as(T, 0.0), generic_fmod(T, 0.0, 2.0));
+ std.testing.expectEqual(@as(T, -0.0), generic_fmod(T, -0.0, 2.0));
+
+ std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, 10.0));
+ std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, -10.0));
+ std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, 10.0));
+ std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, -10.0));
+ }
+}
+
+fn generic_fmin(comptime T: type, x: T, y: T) T {
+ if (isNan(x))
+ return y;
+ if (isNan(y))
+ return x;
+ return if (x < y) x else y;
+}
+
+export fn fminf(x: f32, y: f32) callconv(.C) f32 {
+ return generic_fmin(f32, x, y);
+}
+
+export fn fmin(x: f64, y: f64) callconv(.C) f64 {
+ return generic_fmin(f64, x, y);
+}
+
+test "fmin, fminf" {
+ inline for ([_]type{ f32, f64 }) |T| {
+ const nan_val = math.nan(T);
+
+ std.testing.expect(isNan(generic_fmin(T, nan_val, nan_val)));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, nan_val, 1.0));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, nan_val));
+
+ std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, 10.0));
+ std.testing.expectEqual(@as(T, -1.0), generic_fmin(T, 1.0, -1.0));
+ }
+}
+
+fn generic_fmax(comptime T: type, x: T, y: T) T {
+ if (isNan(x))
+ return y;
+ if (isNan(y))
+ return x;
+ return if (x < y) y else x;
+}
+
+export fn fmaxf(x: f32, y: f32) callconv(.C) f32 {
+ return generic_fmax(f32, x, y);
+}
+
+export fn fmax(x: f64, y: f64) callconv(.C) f64 {
+ return generic_fmax(f64, x, y);
+}
+
+test "fmax, fmaxf" {
+ inline for ([_]type{ f32, f64 }) |T| {
+ const nan_val = math.nan(T);
+
+ std.testing.expect(isNan(generic_fmax(T, nan_val, nan_val)));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, nan_val, 1.0));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, nan_val));
+
+ std.testing.expectEqual(@as(T, 10.0), generic_fmax(T, 1.0, 10.0));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, -1.0));
+ }
+}
+
// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are
// potentially some edge cases remaining that are not handled in the same way.
@@ -996,25 +1075,32 @@ export fn sqrt(x: f64) f64 {
}
test "sqrt" {
- const epsilon = 0.000001;
-
- std.testing.expect(sqrt(0.0) == 0.0);
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(2.0), 1.414214, epsilon));
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(3.6), 1.897367, epsilon));
- std.testing.expect(sqrt(4.0) == 2.0);
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(7.539840), 2.745877, epsilon));
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(19.230934), 4.385309, epsilon));
- std.testing.expect(sqrt(64.0) == 8.0);
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(64.1), 8.006248, epsilon));
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(8942.230469), 94.563367, epsilon));
+ const V = [_]f64{
+ 0.0,
+ 4.089288054930154,
+ 7.538757127071935,
+ 8.97780793672623,
+ 5.304443821913729,
+ 5.682408965311888,
+ 0.5846878579110049,
+ 3.650338664297043,
+ 0.3178091951800732,
+ 7.1505232436382835,
+ 3.6589165881946464,
+ };
+
+ // Note that @sqrt will either generate the sqrt opcode (if supported by the
+ // target ISA) or a call to `sqrtf` otherwise.
+ for (V) |val|
+ std.testing.expectEqual(@sqrt(val), sqrt(val));
}
test "sqrt special" {
std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64))));
std.testing.expect(sqrt(0.0) == 0.0);
std.testing.expect(sqrt(-0.0) == -0.0);
- std.testing.expect(std.math.isNan(sqrt(-1.0)));
- std.testing.expect(std.math.isNan(sqrt(std.math.nan(f64))));
+ std.testing.expect(isNan(sqrt(-1.0)));
+ std.testing.expect(isNan(sqrt(std.math.nan(f64))));
}
export fn sqrtf(x: f32) f32 {
@@ -1094,23 +1180,30 @@ export fn sqrtf(x: f32) f32 {
}
test "sqrtf" {
- const epsilon = 0.000001;
-
- std.testing.expect(sqrtf(0.0) == 0.0);
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(2.0), 1.414214, epsilon));
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(3.6), 1.897367, epsilon));
- std.testing.expect(sqrtf(4.0) == 2.0);
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(7.539840), 2.745877, epsilon));
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(19.230934), 4.385309, epsilon));
- std.testing.expect(sqrtf(64.0) == 8.0);
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(64.1), 8.006248, epsilon));
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(8942.230469), 94.563370, epsilon));
+ const V = [_]f32{
+ 0.0,
+ 4.089288054930154,
+ 7.538757127071935,
+ 8.97780793672623,
+ 5.304443821913729,
+ 5.682408965311888,
+ 0.5846878579110049,
+ 3.650338664297043,
+ 0.3178091951800732,
+ 7.1505232436382835,
+ 3.6589165881946464,
+ };
+
+ // Note that @sqrt will either generate the sqrt opcode (if supported by the
+ // target ISA) or a call to `sqrtf` otherwise.
+ for (V) |val|
+ std.testing.expectEqual(@sqrt(val), sqrtf(val));
}
test "sqrtf special" {
std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32))));
std.testing.expect(sqrtf(0.0) == 0.0);
std.testing.expect(sqrtf(-0.0) == -0.0);
- std.testing.expect(std.math.isNan(sqrtf(-1.0)));
- std.testing.expect(std.math.isNan(sqrtf(std.math.nan(f32))));
+ std.testing.expect(isNan(sqrtf(-1.0)));
+ std.testing.expect(isNan(sqrtf(std.math.nan(f32))));
}
diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig
index 90db855fde..a13097765e 100644
--- a/lib/std/special/compiler_rt.zig
+++ b/lib/std/special/compiler_rt.zig
@@ -116,9 +116,11 @@ comptime {
@export(@import("compiler_rt/extendXfYf2.zig").__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
@export(@import("compiler_rt/extendXfYf2.zig").__extendsftf2, .{ .name = "__extendsftf2", .linkage = linkage });
@export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = linkage });
+ @export(@import("compiler_rt/extendXfYf2.zig").__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
+ @export(@import("compiler_rt/truncXfYf2.zig").__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
@@ -299,7 +301,7 @@ comptime {
@export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });
}
- if (arch == .powerpc or arch.isPPC64()) {
+ if ((arch == .powerpc or arch.isPPC64()) and !is_test) {
@export(@import("compiler_rt/addXf3.zig").__addtf3, .{ .name = "__addkf3", .linkage = linkage });
@export(@import("compiler_rt/addXf3.zig").__subtf3, .{ .name = "__subkf3", .linkage = linkage });
@export(@import("compiler_rt/mulXf3.zig").__multf3, .{ .name = "__mulkf3", .linkage = linkage });
diff --git a/lib/std/special/compiler_rt/extendXfYf2.zig b/lib/std/special/compiler_rt/extendXfYf2.zig
index c5b93fa51e..59be8441fa 100644
--- a/lib/std/special/compiler_rt/extendXfYf2.zig
+++ b/lib/std/special/compiler_rt/extendXfYf2.zig
@@ -23,6 +23,10 @@ pub fn __extendhfsf2(a: u16) callconv(.C) f32 {
return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, a });
}
+pub fn __extendhftf2(a: u16) callconv(.C) f128 {
+ return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f16, a });
+}
+
pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 {
@setRuntimeSafety(false);
return @call(.{ .modifier = .always_inline }, __extendhfsf2, .{arg});
diff --git a/lib/std/special/compiler_rt/extendXfYf2_test.zig b/lib/std/special/compiler_rt/extendXfYf2_test.zig
index 6a3f69d8e9..f05d33eac3 100644
--- a/lib/std/special/compiler_rt/extendXfYf2_test.zig
+++ b/lib/std/special/compiler_rt/extendXfYf2_test.zig
@@ -4,9 +4,10 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const builtin = @import("builtin");
-const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
+const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2;
const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
+const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {
const x = __extenddftf2(a);
@@ -161,3 +162,49 @@ fn makeNaN32(rand: u32) f32 {
fn makeInf32() f32 {
return @bitCast(f32, @as(u32, 0x7f800000));
}
+
+fn test__extendhftf2(a: u16, expectedHi: u64, expectedLo: u64) void {
+ const x = __extendhftf2(a);
+
+ const rep = @bitCast(u128, x);
+ const hi = @intCast(u64, rep >> 64);
+ const lo = @truncate(u64, rep);
+
+ if (hi == expectedHi and lo == expectedLo)
+ return;
+
+ // test other possible NaN representation(signal NaN)
+ if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) {
+ if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
+ ((hi & 0xffffffffffff) > 0 or lo > 0))
+ {
+ return;
+ }
+ }
+
+ @panic("__extendhftf2 test failure");
+}
+
+test "extendhftf2" {
+ // qNaN
+ test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0);
+ // NaN
+ test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0);
+ // inf
+ test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0);
+ test__extendhftf2(0xfc00, 0xffff000000000000, 0x0);
+ // zero
+ test__extendhftf2(0x0000, 0x0000000000000000, 0x0);
+ test__extendhftf2(0x8000, 0x8000000000000000, 0x0);
+ // denormal
+ test__extendhftf2(0x0010, 0x3feb000000000000, 0x0);
+ test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0);
+ test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0);
+
+ // pi
+ test__extendhftf2(0x4248, 0x4000920000000000, 0x0);
+ test__extendhftf2(0xc248, 0xc000920000000000, 0x0);
+
+ test__extendhftf2(0x508c, 0x4004230000000000, 0x0);
+ test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0);
+}
diff --git a/lib/std/special/compiler_rt/truncXfYf2.zig b/lib/std/special/compiler_rt/truncXfYf2.zig
index 470ac17c2c..e85aa363db 100644
--- a/lib/std/special/compiler_rt/truncXfYf2.zig
+++ b/lib/std/special/compiler_rt/truncXfYf2.zig
@@ -13,6 +13,10 @@ pub fn __truncdfhf2(a: f64) callconv(.C) u16 {
return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a }));
}
+pub fn __trunctfhf2(a: f128) callconv(.C) u16 {
+ return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a }));
+}
+
pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f128, a });
}
@@ -122,7 +126,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
if (shift > srcSigBits) {
absResult = 0;
} else {
- const sticky: src_rep_t = significand << @intCast(SrcShift, srcBits - shift);
+ const sticky: src_rep_t = @boolToInt(significand << @intCast(SrcShift, srcBits - shift) != 0);
const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky;
absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits));
const roundBits: src_rep_t = denormalizedSignificand & roundMask;
diff --git a/lib/std/special/compiler_rt/truncXfYf2_test.zig b/lib/std/special/compiler_rt/truncXfYf2_test.zig
index 6426614b07..4fae5d1fc0 100644
--- a/lib/std/special/compiler_rt/truncXfYf2_test.zig
+++ b/lib/std/special/compiler_rt/truncXfYf2_test.zig
@@ -242,3 +242,59 @@ test "truncdfsf2" {
// huge number becomes inf
test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
}
+
+const __trunctfhf2 = @import("truncXfYf2.zig").__trunctfhf2;
+
+fn test__trunctfhf2(a: f128, expected: u16) void {
+ const x = __trunctfhf2(a);
+
+ const rep = @bitCast(u16, x);
+ if (rep == expected) {
+ return;
+ }
+
+ @import("std").debug.warn("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
+
+ @panic("__trunctfhf2 test failure");
+}
+
+test "trunctfhf2" {
+ // qNaN
+ test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
+ // NaN
+ test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
+ // inf
+ test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
+ test__trunctfhf2(-@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0xfc00);
+ // zero
+ test__trunctfhf2(0.0, 0x0);
+ test__trunctfhf2(-0.0, 0x8000);
+
+ test__trunctfhf2(3.1415926535, 0x4248);
+ test__trunctfhf2(-3.1415926535, 0xc248);
+ test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);
+ test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);
+ test__trunctfhf2(0x1.0p+0, 0x3c00);
+ test__trunctfhf2(0x1.0p-14, 0x0400);
+ // denormal
+ test__trunctfhf2(0x1.0p-20, 0x0010);
+ test__trunctfhf2(0x1.0p-24, 0x0001);
+ test__trunctfhf2(-0x1.0p-24, 0x8001);
+ test__trunctfhf2(0x1.5p-25, 0x0001);
+ // and back to zero
+ test__trunctfhf2(0x1.0p-25, 0x0000);
+ test__trunctfhf2(-0x1.0p-25, 0x8000);
+ // max (precise)
+ test__trunctfhf2(65504.0, 0x7bff);
+ // max (rounded)
+ test__trunctfhf2(65519.0, 0x7bff);
+ // max (to +inf)
+ test__trunctfhf2(65520.0, 0x7c00);
+ test__trunctfhf2(65536.0, 0x7c00);
+ test__trunctfhf2(-65520.0, 0xfc00);
+
+ test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
+ test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
+ test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
+ test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
+}
diff --git a/lib/std/target.zig b/lib/std/target.zig
index 5d246465e2..3e8159aae9 100644
--- a/lib/std/target.zig
+++ b/lib/std/target.zig
@@ -800,6 +800,13 @@ pub const Target = struct {
};
}
+ pub fn isPPC(arch: Arch) bool {
+ return switch (arch) {
+ .powerpc, .powerpcle => true,
+ else => false,
+ };
+ }
+
pub fn isPPC64(arch: Arch) bool {
return switch (arch) {
.powerpc64, .powerpc64le => true,
@@ -1184,8 +1191,8 @@ pub const Target = struct {
.mips, .mipsel => &mips.cpu.mips32,
.mips64, .mips64el => &mips.cpu.mips64,
.msp430 => &msp430.cpu.generic,
- .powerpc => &powerpc.cpu.ppc32,
- .powerpcle => &powerpc.cpu.ppc32,
+ .powerpc => &powerpc.cpu.ppc,
+ .powerpcle => &powerpc.cpu.ppc,
.powerpc64 => &powerpc.cpu.ppc64,
.powerpc64le => &powerpc.cpu.ppc64le,
.amdgcn => &amdgpu.cpu.generic,
diff --git a/lib/std/target/powerpc.zig b/lib/std/target/powerpc.zig
index 4e2200a47f..db4d5dccdc 100644
--- a/lib/std/target/powerpc.zig
+++ b/lib/std/target/powerpc.zig
@@ -751,13 +751,6 @@ pub const cpu = struct {
.hard_float,
}),
};
- pub const ppc32 = CpuModel{
- .name = "ppc32",
- .llvm_name = "ppc32",
- .features = featureSet(&[_]Feature{
- .hard_float,
- }),
- };
pub const ppc64 = CpuModel{
.name = "ppc64",
.llvm_name = "ppc64",
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
index 029d8ede50..d6880ad273 100644
--- a/lib/std/zig/parse.zig
+++ b/lib/std/zig/parse.zig
@@ -852,7 +852,7 @@ const Parser = struct {
/// <- KEYWORD_comptime? VarDecl
/// / KEYWORD_comptime BlockExprStatement
/// / KEYWORD_nosuspend BlockExprStatement
- /// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
+ /// / KEYWORD_suspend BlockExprStatement
/// / KEYWORD_defer BlockExprStatement
/// / KEYWORD_errdefer Payload? BlockExprStatement
/// / IfStatement
@@ -892,6 +892,7 @@ const Parser = struct {
},
.keyword_suspend => {
const token = p.nextToken();
+ // TODO remove this special case when 0.9.0 is released.
const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)
0
else
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
index 1bed86f42d..2fa8baa185 100644
--- a/lib/std/zig/parser_test.zig
+++ b/lib/std/zig/parser_test.zig
@@ -40,6 +40,21 @@ test "zig fmt: rewrite inline functions as callconv(.Inline)" {
);
}
+// TODO Remove this after zig 0.9.0 is released.
+test "zig fmt: rewrite suspend without block expression" {
+ try testTransform(
+ \\fn foo() void {
+ \\ suspend;
+ \\}
+ \\
+ ,
+ \\fn foo() void {
+ \\ suspend {}
+ \\}
+ \\
+ );
+}
+
test "zig fmt: simple top level comptime block" {
try testCanonical(
\\// line comment
@@ -1315,6 +1330,27 @@ test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
);
}
+test "zig fmt: 'zig fmt: on' indentation is unchanged" {
+ try testCanonical(
+ \\fn initOptionsAndLayouts(output: *Output, context: *Context) !void {
+ \\ // zig fmt: off
+ \\ try output.main_amount.init(output, "main_amount"); errdefer optput.main_amount.deinit();
+ \\ try output.main_factor.init(output, "main_factor"); errdefer optput.main_factor.deinit();
+ \\ try output.view_padding.init(output, "view_padding"); errdefer optput.view_padding.deinit();
+ \\ try output.outer_padding.init(output, "outer_padding"); errdefer optput.outer_padding.deinit();
+ \\ // zig fmt: on
+ \\
+ \\ // zig fmt: off
+ \\ try output.top.init(output, .top); errdefer optput.top.deinit();
+ \\ try output.right.init(output, .right); errdefer optput.right.deinit();
+ \\ try output.bottom.init(output, .bottom); errdefer optput.bottom.deinit();
+ \\ try output.left.init(output, .left); errdefer optput.left.deinit();
+ \\ // zig fmt: on
+ \\}
+ \\
+ );
+}
+
test "zig fmt: pointer of unknown length" {
try testCanonical(
\\fn foo(ptr: [*]u8) void {}
@@ -3644,9 +3680,9 @@ test "zig fmt: async functions" {
\\fn simpleAsyncFn() void {
\\ const a = async a.b();
\\ x += 1;
- \\ suspend;
+ \\ suspend {}
\\ x += 1;
- \\ suspend;
+ \\ suspend {}
\\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
\\ await p;
\\}
@@ -5001,6 +5037,21 @@ test "recovery: invalid comptime" {
});
}
+test "recovery: missing block after suspend" {
+ // TODO Enable this after zig 0.9.0 is released.
+ if (true) return error.SkipZigTest;
+
+ try testError(
+ \\fn foo() void {
+ \\ suspend;
+ \\ nosuspend;
+ \\}
+ , &[_]Error{
+ .expected_block_or_expr,
+ .expected_block_or_expr,
+ });
+}
+
test "recovery: missing block after for/while loops" {
try testError(
\\test "" { while (foo) }
@@ -5144,7 +5195,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
var tree = try std.zig.parse(std.testing.allocator, source);
defer tree.deinit(std.testing.allocator);
- std.testing.expect(tree.errors.len == expected_errors.len);
+ std.testing.expectEqual(expected_errors.len, tree.errors.len);
for (expected_errors) |expected, i| {
std.testing.expectEqual(expected, tree.errors[i].tag);
}
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index ae12fc043f..237ecf777d 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -269,7 +269,12 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I
try renderToken(ais, tree, suspend_token, .space);
return renderExpression(gpa, ais, tree, body, space);
} else {
- return renderToken(ais, tree, suspend_token, space);
+ // TODO remove this special case when 0.9.0 is released.
+ assert(space == .semicolon);
+ try renderToken(ais, tree, suspend_token, .space);
+ try ais.writer().writeAll("{}");
+ try ais.insertNewline();
+ return;
}
},
@@ -2310,9 +2315,9 @@ fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!boo
// to the underlying writer, fixing up invaild whitespace.
const disabled_source = tree.source[ais.disabled_offset.?..comment_start];
try writeFixingWhitespace(ais.underlying_writer, disabled_source);
- ais.disabled_offset = null;
// Write with the canonical single space.
- try ais.writer().writeAll("// zig fmt: on\n");
+ try ais.underlying_writer.writeAll("// zig fmt: on\n");
+ ais.disabled_offset = null;
} else if (ais.disabled_offset == null and mem.eql(u8, comment_content, "zig fmt: off")) {
// Write with the canonical single space.
try ais.writer().writeAll("// zig fmt: off\n");