aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-02-15 18:05:50 -0500
committerAndrew Kelley <andrew@ziglang.org>2019-02-15 18:05:50 -0500
commit7293e012d7956b892380517e914108ffadc6941b (patch)
tree420049c2174484e2c536d2e36b5b1bb906b921b3 /std
parent567c9b688effdb64e3995df09af4b45105515c2c (diff)
downloadzig-7293e012d7956b892380517e914108ffadc6941b.tar.gz
zig-7293e012d7956b892380517e914108ffadc6941b.zip
breaking: fix @sizeOf to be alloc size rather than store size
* Fixes breaches of the guarantee that `@sizeOf(T) >= @alignOf(T)` * Fixes std.mem.secureZero for integers where this guarantee previously was breached * Fixes std.mem.Allocator for integers where this guarantee previously was breached Closes #1851 Closes #1864
Diffstat (limited to 'std')
-rw-r--r--std/io.zig13
-rw-r--r--std/mem.zig49
2 files changed, 25 insertions, 37 deletions
diff --git a/std/io.zig b/std/io.zig
index d7e8507f9b..6c70834b52 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -935,8 +935,6 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
};
}
-
-
pub const BufferedAtomicFile = struct {
atomic_file: os.AtomicFile,
file_stream: os.File.OutStream,
@@ -978,7 +976,6 @@ pub const BufferedAtomicFile = struct {
}
};
-
pub fn readLine(buf: *std.Buffer) ![]u8 {
var stdin = try getStdIn();
var stdin_stream = stdin.inStream();
@@ -1073,13 +1070,13 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E
else => in_stream,
} };
}
-
+
pub fn alignToByte(self: *Self) void {
- if(!is_packed) return;
+ if (!is_packed) return;
self.in_stream.alignToByte();
}
- //@BUG: inferred error issue. See: #1386
+ //@BUG: inferred error issue. See: #1386
fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
@@ -1088,7 +1085,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E
const U = @IntType(false, t_bit_count);
const Log2U = math.Log2Int(U);
- const int_size = @sizeOf(U);
+ const int_size = (U.bit_count + 7) / 8;
if (is_packed) {
const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
@@ -1301,7 +1298,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, com
const U = @IntType(false, t_bit_count);
const Log2U = math.Log2Int(U);
- const int_size = @sizeOf(U);
+ const int_size = (U.bit_count + 7) / 8;
const u_value = @bitCast(U, value);
diff --git a/std/mem.zig b/std/mem.zig
index 1c7523bf13..39b9701754 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -423,8 +423,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.
/// This function cannot fail and cannot cause undefined behavior.
/// Assumes the endianness of memory is native. This means the function can
/// simply pointer cast memory.
-pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
- comptime assert(T.bit_count % 8 == 0);
+pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
return @ptrCast(*align(1) const T, bytes).*;
}
@@ -432,7 +431,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
/// The bit count of T must be evenly divisible by 8.
/// This function cannot fail and cannot cause undefined behavior.
/// Assumes the endianness of memory is foreign, so it must byte-swap.
-pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
+pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
return @bswap(T, readIntNative(T, bytes));
}
@@ -446,22 +445,20 @@ pub const readIntBig = switch (builtin.endian) {
builtin.Endian.Big => readIntNative,
};
-/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
+/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
/// and ignores extra bytes.
-/// Note that @sizeOf(u24) is 3.
/// The bit count of T must be evenly divisible by 8.
/// Assumes the endianness of memory is native. This means the function can
/// simply pointer cast memory.
pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
- assert(@sizeOf(u24) == 3);
- assert(bytes.len >= @sizeOf(T));
+ const n = @divExact(T.bit_count, 8);
+ assert(bytes.len >= n);
// TODO https://github.com/ziglang/zig/issues/863
- return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr));
+ return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr));
}
-/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
+/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
/// and ignores extra bytes.
-/// Note that @sizeOf(u24) is 3.
/// The bit count of T must be evenly divisible by 8.
/// Assumes the endianness of memory is foreign, so it must byte-swap.
pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
@@ -481,7 +478,7 @@ pub const readIntSliceBig = switch (builtin.endian) {
/// Reads an integer from memory with bit count specified by T.
/// The bit count of T must be evenly divisible by 8.
/// This function cannot fail and cannot cause undefined behavior.
-pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T {
+pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T {
if (endian == builtin.endian) {
return readIntNative(T, bytes);
} else {
@@ -489,15 +486,14 @@ pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.E
}
}
-/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
+/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
/// and ignores extra bytes.
-/// Note that @sizeOf(u24) is 3.
/// The bit count of T must be evenly divisible by 8.
pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
- assert(@sizeOf(u24) == 3);
- assert(bytes.len >= @sizeOf(T));
+ const n = @divExact(T.bit_count, 8);
+ assert(bytes.len >= n);
// TODO https://github.com/ziglang/zig/issues/863
- return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian);
+ return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian);
}
test "comptime read/write int" {
@@ -540,7 +536,7 @@ test "readIntBig and readIntLittle" {
/// accepts any integer bit width.
/// This function stores in native endian, which means it is implemented as a simple
/// memory store.
-pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
+pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void {
@ptrCast(*align(1) T, buf).* = value;
}
@@ -548,7 +544,7 @@ pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
/// This function always succeeds, has defined behavior for all inputs, but
/// the integer bit width must be divisible by 8.
/// This function stores in foreign endian, which means it does a @bswap first.
-pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
+pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {
writeIntNative(T, buf, @bswap(T, value));
}
@@ -565,8 +561,7 @@ pub const writeIntBig = switch (builtin.endian) {
/// Writes an integer to memory, storing it in twos-complement.
/// This function always succeeds, has defined behavior for all inputs, but
/// the integer bit width must be divisible by 8.
-pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void {
- comptime assert(T.bit_count % 8 == 0);
+pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void {
if (endian == builtin.endian) {
return writeIntNative(T, buffer, value);
} else {
@@ -575,15 +570,13 @@ pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: bui
}
/// Writes a twos-complement little-endian integer to memory.
-/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
+/// Asserts that buf.len >= T.bit_count / 8.
/// The bit count of T must be divisible by 8.
/// Any extra bytes in buffer after writing the integer are set to zero. To
/// avoid the branch to check for extra buffer bytes, use writeIntLittle
/// instead.
pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
- comptime assert(@sizeOf(u24) == 3);
- comptime assert(T.bit_count % 8 == 0);
- assert(buffer.len >= @sizeOf(T));
+ assert(buffer.len >= @divExact(T.bit_count, 8));
// TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
const uint = @IntType(false, T.bit_count);
@@ -595,14 +588,12 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
}
/// Writes a twos-complement big-endian integer to memory.
-/// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
+/// Asserts that buffer.len >= T.bit_count / 8.
/// The bit count of T must be divisible by 8.
/// Any extra bytes in buffer before writing the integer are set to zero. To
/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
- comptime assert(@sizeOf(u24) == 3);
- comptime assert(T.bit_count % 8 == 0);
- assert(buffer.len >= @sizeOf(T));
+ assert(buffer.len >= @divExact(T.bit_count, 8));
// TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
const uint = @IntType(false, T.bit_count);
@@ -626,7 +617,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) {
};
/// Writes a twos-complement integer to memory, with the specified endianness.
-/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
+/// Asserts that buf.len >= T.bit_count / 8.
/// The bit count of T must be evenly divisible by 8.
/// Any extra bytes in buffer not part of the integer are set to zero, with
/// respect to endianness. To avoid the branch to check for extra buffer bytes,