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)
263263 // Covers zig.h and err_typedef_item.
264264 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
265265
266 f.all_buffers.appendAssumeCapacity(.{
267 .iov_base = zig_h,
268 .iov_len = zig_h.len,
269 });
270 f.file_size += zig_h.len;
266 if (zig_h.len != 0) {
267 f.all_buffers.appendAssumeCapacity(.{
268 .iov_base = zig_h,
269 .iov_len = zig_h.len,
270 });
271 f.file_size += zig_h.len;
272 }
271273
272274 const err_typedef_writer = f.err_typedef_buf.writer(gpa);
273275 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)
301303 try flushDecl(self, &f, decl_index);
302304 }
303305
304 f.all_buffers.items[err_typedef_index] = .{
305 .iov_base = f.err_typedef_buf.items.ptr,
306 .iov_len = f.err_typedef_buf.items.len,
307 };
308 f.file_size += f.err_typedef_buf.items.len;
306 if (f.err_typedef_buf.items.len == 0) {
307 f.all_buffers.items[err_typedef_index] = .{
308 .iov_base = "",
309 .iov_len = 0,
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
310319 // Now the function bodies.
311320 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!
391400
392401 if (decl_block.fwd_decl.items.len != 0) {
393402 const buf = decl_block.fwd_decl.items;
394 try f.all_buffers.append(gpa, .{
395 .iov_base = buf.ptr,
396 .iov_len = buf.len,
397 });
398 f.file_size += buf.len;
403 if (buf.len != 0) {
404 try f.all_buffers.append(gpa, .{
405 .iov_base = buf.ptr,
406 .iov_len = buf.len,
407 });
408 f.file_size += buf.len;
409 }
399410 }
400411 if (decl.getFunction() != null) {
401412 f.fn_count += 1;
402413 } else if (decl_block.code.items.len != 0) {
403414 const buf = decl_block.code.items;
404 try f.all_buffers.append(gpa, .{
405 .iov_base = buf.ptr,
406 .iov_len = buf.len,
407 });
408 f.file_size += buf.len;
415 if (buf.len != 0) {
416 try f.all_buffers.append(gpa, .{
417 .iov_base = buf.ptr,
418 .iov_len = buf.len,
419 });
420 f.file_size += buf.len;
421 }
409422 }
410423}
411424
......@@ -421,19 +434,23 @@ pub fn flushEmitH(module: *Module) !void {
421434 defer all_buffers.deinit();
422435
423436 var file_size: u64 = zig_h.len;
424 all_buffers.appendAssumeCapacity(.{
425 .iov_base = zig_h,
426 .iov_len = zig_h.len,
427 });
437 if (zig_h.len != 0) {
438 all_buffers.appendAssumeCapacity(.{
439 .iov_base = zig_h,
440 .iov_len = zig_h.len,
441 });
442 }
428443
429444 for (emit_h.decl_table.keys()) |decl_index| {
430445 const decl_emit_h = emit_h.declPtr(decl_index);
431446 const buf = decl_emit_h.fwd_decl.items;
432 all_buffers.appendAssumeCapacity(.{
433 .iov_base = buf.ptr,
434 .iov_len = buf.len,
435 });
436 file_size += buf.len;
447 if (buf.len != 0) {
448 all_buffers.appendAssumeCapacity(.{
449 .iov_base = buf.ptr,
450 .iov_len = buf.len,
451 });
452 file_size += buf.len;
453 }
437454 }
438455
439456 const directory = emit_h.loc.directory orelse module.comp.local_cache_directory;
src/link/Dwarf.zig+2-2
......@@ -1752,7 +1752,7 @@ fn pwriteDbgLineNops(
17521752 .iov_base = buf.ptr,
17531753 .iov_len = buf.len,
17541754 };
1755 vec_index += 1;
1755 if (buf.len > 0) vec_index += 1;
17561756
17571757 {
17581758 var padding_left = next_padding_size;
......@@ -1861,7 +1861,7 @@ fn pwriteDbgInfoNops(
18611861 .iov_base = buf.ptr,
18621862 .iov_len = buf.len,
18631863 };
1864 vec_index += 1;
1864 if (buf.len > 0) vec_index += 1;
18651865
18661866 {
18671867 var padding_left = next_padding_size;