authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-26 20:05:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-26 20:05:54-07:00
logea3db3274d890b7d00c907c037ffe203f41adbd3
treeeb21fc1c8c8edbdedc37c4913f8d88f97f090310
parent0bc4726e00e794be9848b4b42dba43a0c7f4558e

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.

2 files changed, 48 insertions(+), 31 deletions(-)

src/link/C.zig+46-29
...@@ -263,11 +263,13 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)...@@ -263,11 +263,13 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
263 // Covers zig.h and err_typedef_item.263 // Covers zig.h and err_typedef_item.
264 try f.all_buffers.ensureUnusedCapacity(gpa, 2);264 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
265265
266 f.all_buffers.appendAssumeCapacity(.{266 if (zig_h.len != 0) {
267 .iov_base = zig_h,267 f.all_buffers.appendAssumeCapacity(.{
268 .iov_len = zig_h.len,268 .iov_base = zig_h,
269 });269 .iov_len = zig_h.len,
270 f.file_size += zig_h.len;270 });
271 f.file_size += zig_h.len;
272 }
271273
272 const err_typedef_writer = f.err_typedef_buf.writer(gpa);274 const err_typedef_writer = f.err_typedef_buf.writer(gpa);
273 const err_typedef_index = f.all_buffers.items.len;275 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)...@@ -301,11 +303,18 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
301 try flushDecl(self, &f, decl_index);303 try flushDecl(self, &f, decl_index);
302 }304 }
303305
304 f.all_buffers.items[err_typedef_index] = .{306 if (f.err_typedef_buf.items.len == 0) {
305 .iov_base = f.err_typedef_buf.items.ptr,307 f.all_buffers.items[err_typedef_index] = .{
306 .iov_len = f.err_typedef_buf.items.len,308 .iov_base = "",
307 };309 .iov_len = 0,
308 f.file_size += f.err_typedef_buf.items.len;310 };
311 } else {
312 f.all_buffers.items[err_typedef_index] = .{
313 .iov_base = f.err_typedef_buf.items.ptr,
314 .iov_len = f.err_typedef_buf.items.len,
315 };
316 f.file_size += f.err_typedef_buf.items.len;
317 }
309318
310 // Now the function bodies.319 // Now the function bodies.
311 try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count);320 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!...@@ -391,21 +400,25 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
391400
392 if (decl_block.fwd_decl.items.len != 0) {401 if (decl_block.fwd_decl.items.len != 0) {
393 const buf = decl_block.fwd_decl.items;402 const buf = decl_block.fwd_decl.items;
394 try f.all_buffers.append(gpa, .{403 if (buf.len != 0) {
395 .iov_base = buf.ptr,404 try f.all_buffers.append(gpa, .{
396 .iov_len = buf.len,405 .iov_base = buf.ptr,
397 });406 .iov_len = buf.len,
398 f.file_size += buf.len;407 });
408 f.file_size += buf.len;
409 }
399 }410 }
400 if (decl.getFunction() != null) {411 if (decl.getFunction() != null) {
401 f.fn_count += 1;412 f.fn_count += 1;
402 } else if (decl_block.code.items.len != 0) {413 } else if (decl_block.code.items.len != 0) {
403 const buf = decl_block.code.items;414 const buf = decl_block.code.items;
404 try f.all_buffers.append(gpa, .{415 if (buf.len != 0) {
405 .iov_base = buf.ptr,416 try f.all_buffers.append(gpa, .{
406 .iov_len = buf.len,417 .iov_base = buf.ptr,
407 });418 .iov_len = buf.len,
408 f.file_size += buf.len;419 });
420 f.file_size += buf.len;
421 }
409 }422 }
410}423}
411424
...@@ -421,19 +434,23 @@ pub fn flushEmitH(module: *Module) !void {...@@ -421,19 +434,23 @@ pub fn flushEmitH(module: *Module) !void {
421 defer all_buffers.deinit();434 defer all_buffers.deinit();
422435
423 var file_size: u64 = zig_h.len;436 var file_size: u64 = zig_h.len;
424 all_buffers.appendAssumeCapacity(.{437 if (zig_h.len != 0) {
425 .iov_base = zig_h,438 all_buffers.appendAssumeCapacity(.{
426 .iov_len = zig_h.len,439 .iov_base = zig_h,
427 });440 .iov_len = zig_h.len,
441 });
442 }
428443
429 for (emit_h.decl_table.keys()) |decl_index| {444 for (emit_h.decl_table.keys()) |decl_index| {
430 const decl_emit_h = emit_h.declPtr(decl_index);445 const decl_emit_h = emit_h.declPtr(decl_index);
431 const buf = decl_emit_h.fwd_decl.items;446 const buf = decl_emit_h.fwd_decl.items;
432 all_buffers.appendAssumeCapacity(.{447 if (buf.len != 0) {
433 .iov_base = buf.ptr,448 all_buffers.appendAssumeCapacity(.{
434 .iov_len = buf.len,449 .iov_base = buf.ptr,
435 });450 .iov_len = buf.len,
436 file_size += buf.len;451 });
452 file_size += buf.len;
453 }
437 }454 }
438455
439 const directory = emit_h.loc.directory orelse module.comp.local_cache_directory;456 const directory = emit_h.loc.directory orelse module.comp.local_cache_directory;
src/link/Dwarf.zig+2-2
...@@ -1752,7 +1752,7 @@ fn pwriteDbgLineNops(...@@ -1752,7 +1752,7 @@ fn pwriteDbgLineNops(
1752 .iov_base = buf.ptr,1752 .iov_base = buf.ptr,
1753 .iov_len = buf.len,1753 .iov_len = buf.len,
1754 };1754 };
1755 vec_index += 1;1755 if (buf.len > 0) vec_index += 1;
17561756
1757 {1757 {
1758 var padding_left = next_padding_size;1758 var padding_left = next_padding_size;
...@@ -1861,7 +1861,7 @@ fn pwriteDbgInfoNops(...@@ -1861,7 +1861,7 @@ fn pwriteDbgInfoNops(
1861 .iov_base = buf.ptr,1861 .iov_base = buf.ptr,
1862 .iov_len = buf.len,1862 .iov_len = buf.len,
1863 };1863 };
1864 vec_index += 1;1864 if (buf.len > 0) vec_index += 1;
18651865
1866 {1866 {
1867 var padding_left = next_padding_size;1867 var padding_left = next_padding_size;