aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-07-26 20:05:54 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-07-26 20:05:54 -0700
commitea3db3274d890b7d00c907c037ffe203f41adbd3 (patch)
treeeb21fc1c8c8edbdedc37c4913f8d88f97f090310
parent0bc4726e00e794be9848b4b42dba43a0c7f4558e (diff)
downloadzig-ea3db3274d890b7d00c907c037ffe203f41adbd3.tar.gz
zig-ea3db3274d890b7d00c907c037ffe203f41adbd3.zip
link: avoid passing bad ptrs to pwritev
At least on Linux, the pwritev syscall checks the pointer and returns EFAULT before it checks if the length is nonzero. Perhaps this should be fixed in the standard library, however, these are still improvements since they make the kernel do less work within the syscall.
-rw-r--r--src/link/C.zig75
-rw-r--r--src/link/Dwarf.zig4
2 files changed, 48 insertions, 31 deletions
diff --git a/src/link/C.zig b/src/link/C.zig
index 4159a577d2..044f08c94d 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -263,11 +263,13 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
// Covers zig.h and err_typedef_item.
try f.all_buffers.ensureUnusedCapacity(gpa, 2);
- f.all_buffers.appendAssumeCapacity(.{
- .iov_base = zig_h,
- .iov_len = zig_h.len,
- });
- f.file_size += zig_h.len;
+ if (zig_h.len != 0) {
+ f.all_buffers.appendAssumeCapacity(.{
+ .iov_base = zig_h,
+ .iov_len = zig_h.len,
+ });
+ f.file_size += zig_h.len;
+ }
const err_typedef_writer = f.err_typedef_buf.writer(gpa);
const err_typedef_index = f.all_buffers.items.len;
@@ -301,11 +303,18 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
try flushDecl(self, &f, decl_index);
}
- f.all_buffers.items[err_typedef_index] = .{
- .iov_base = f.err_typedef_buf.items.ptr,
- .iov_len = f.err_typedef_buf.items.len,
- };
- f.file_size += f.err_typedef_buf.items.len;
+ if (f.err_typedef_buf.items.len == 0) {
+ f.all_buffers.items[err_typedef_index] = .{
+ .iov_base = "",
+ .iov_len = 0,
+ };
+ } else {
+ f.all_buffers.items[err_typedef_index] = .{
+ .iov_base = f.err_typedef_buf.items.ptr,
+ .iov_len = f.err_typedef_buf.items.len,
+ };
+ f.file_size += f.err_typedef_buf.items.len;
+ }
// Now the function bodies.
try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count);
@@ -391,21 +400,25 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
if (decl_block.fwd_decl.items.len != 0) {
const buf = decl_block.fwd_decl.items;
- try f.all_buffers.append(gpa, .{
- .iov_base = buf.ptr,
- .iov_len = buf.len,
- });
- f.file_size += buf.len;
+ if (buf.len != 0) {
+ try f.all_buffers.append(gpa, .{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ });
+ f.file_size += buf.len;
+ }
}
if (decl.getFunction() != null) {
f.fn_count += 1;
} else if (decl_block.code.items.len != 0) {
const buf = decl_block.code.items;
- try f.all_buffers.append(gpa, .{
- .iov_base = buf.ptr,
- .iov_len = buf.len,
- });
- f.file_size += buf.len;
+ if (buf.len != 0) {
+ try f.all_buffers.append(gpa, .{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ });
+ f.file_size += buf.len;
+ }
}
}
@@ -421,19 +434,23 @@ pub fn flushEmitH(module: *Module) !void {
defer all_buffers.deinit();
var file_size: u64 = zig_h.len;
- all_buffers.appendAssumeCapacity(.{
- .iov_base = zig_h,
- .iov_len = zig_h.len,
- });
+ if (zig_h.len != 0) {
+ all_buffers.appendAssumeCapacity(.{
+ .iov_base = zig_h,
+ .iov_len = zig_h.len,
+ });
+ }
for (emit_h.decl_table.keys()) |decl_index| {
const decl_emit_h = emit_h.declPtr(decl_index);
const buf = decl_emit_h.fwd_decl.items;
- all_buffers.appendAssumeCapacity(.{
- .iov_base = buf.ptr,
- .iov_len = buf.len,
- });
- file_size += buf.len;
+ if (buf.len != 0) {
+ all_buffers.appendAssumeCapacity(.{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ });
+ file_size += buf.len;
+ }
}
const directory = emit_h.loc.directory orelse module.comp.local_cache_directory;
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index efbd86bc7f..03ba53801b 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -1752,7 +1752,7 @@ fn pwriteDbgLineNops(
.iov_base = buf.ptr,
.iov_len = buf.len,
};
- vec_index += 1;
+ if (buf.len > 0) vec_index += 1;
{
var padding_left = next_padding_size;
@@ -1861,7 +1861,7 @@ fn pwriteDbgInfoNops(
.iov_base = buf.ptr,
.iov_len = buf.len,
};
- vec_index += 1;
+ if (buf.len > 0) vec_index += 1;
{
var padding_left = next_padding_size;