authorgravatar for 39384757+chwayne@users.noreply.github.comchwayne <39384757+chwayne@users.noreply.github.com> 2020-10-22 17:52:48-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-10-22 17:52:48-04:00
log1e13e8e8172c1409c5152e8b4e935c5a1d31704b
treeca4a50d7e30964118f0ddd6634ef13ec6933367e
parent2ee79f149b3a16aca152f6aa0c5a7a8df35c06de
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Make argsAlloc/ArgIterator return zero-sentinel strings (#6720)


1 files changed, 22 insertions(+), 21 deletions(-)

lib/std/process.zig+22-21
...@@ -194,7 +194,7 @@ pub const ArgIteratorPosix = struct {...@@ -194,7 +194,7 @@ pub const ArgIteratorPosix = struct {
194 };194 };
195 }195 }
196196
197 pub fn next(self: *ArgIteratorPosix) ?[]const u8 {197 pub fn next(self: *ArgIteratorPosix) ?[:0]const u8 {
198 if (self.index == self.count) return null;198 if (self.index == self.count) return null;
199199
200 const s = os.argv[self.index];200 const s = os.argv[self.index];
...@@ -213,7 +213,7 @@ pub const ArgIteratorPosix = struct {...@@ -213,7 +213,7 @@ pub const ArgIteratorPosix = struct {
213pub const ArgIteratorWasi = struct {213pub const ArgIteratorWasi = struct {
214 allocator: *mem.Allocator,214 allocator: *mem.Allocator,
215 index: usize,215 index: usize,
216 args: [][]u8,216 args: [][:0]u8,
217217
218 pub const InitError = error{OutOfMemory} || os.UnexpectedError;218 pub const InitError = error{OutOfMemory} || os.UnexpectedError;
219219
...@@ -228,7 +228,7 @@ pub const ArgIteratorWasi = struct {...@@ -228,7 +228,7 @@ pub const ArgIteratorWasi = struct {
228 };228 };
229 }229 }
230230
231 fn internalInit(allocator: *mem.Allocator) InitError![][]u8 {231 fn internalInit(allocator: *mem.Allocator) InitError![][:0]u8 {
232 const w = os.wasi;232 const w = os.wasi;
233 var count: usize = undefined;233 var count: usize = undefined;
234 var buf_size: usize = undefined;234 var buf_size: usize = undefined;
...@@ -248,7 +248,7 @@ pub const ArgIteratorWasi = struct {...@@ -248,7 +248,7 @@ pub const ArgIteratorWasi = struct {
248 else => |err| return os.unexpectedErrno(err),248 else => |err| return os.unexpectedErrno(err),
249 }249 }
250250
251 var result_args = try allocator.alloc([]u8, count);251 var result_args = try allocator.alloc([:0]u8, count);
252 var i: usize = 0;252 var i: usize = 0;
253 while (i < count) : (i += 1) {253 while (i < count) : (i += 1) {
254 result_args[i] = mem.spanZ(argv[i]);254 result_args[i] = mem.spanZ(argv[i]);
...@@ -257,7 +257,7 @@ pub const ArgIteratorWasi = struct {...@@ -257,7 +257,7 @@ pub const ArgIteratorWasi = struct {
257 return result_args;257 return result_args;
258 }258 }
259259
260 pub fn next(self: *ArgIteratorWasi) ?[]const u8 {260 pub fn next(self: *ArgIteratorWasi) ?[:0]const u8 {
261 if (self.index == self.args.len) return null;261 if (self.index == self.args.len) return null;
262262
263 const arg = self.args[self.index];263 const arg = self.args[self.index];
...@@ -301,7 +301,7 @@ pub const ArgIteratorWindows = struct {...@@ -301,7 +301,7 @@ pub const ArgIteratorWindows = struct {
301 }301 }
302302
303 /// You must free the returned memory when done.303 /// You must free the returned memory when done.
304 pub fn next(self: *ArgIteratorWindows, allocator: *Allocator) ?(NextError![]u8) {304 pub fn next(self: *ArgIteratorWindows, allocator: *Allocator) ?(NextError![:0]u8) {
305 // march forward over whitespace305 // march forward over whitespace
306 while (true) : (self.index += 1) {306 while (true) : (self.index += 1) {
307 const byte = self.cmd_line[self.index];307 const byte = self.cmd_line[self.index];
...@@ -355,8 +355,8 @@ pub const ArgIteratorWindows = struct {...@@ -355,8 +355,8 @@ pub const ArgIteratorWindows = struct {
355 }355 }
356 }356 }
357357
358 fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![]u8 {358 fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![:0]u8 {
359 var buf = std.ArrayList(u8).init(allocator);359 var buf = try std.ArrayListSentineled(u8, 0).init(allocator, "");
360 defer buf.deinit();360 defer buf.deinit();
361361
362 var backslash_count: usize = 0;362 var backslash_count: usize = 0;
...@@ -397,7 +397,7 @@ pub const ArgIteratorWindows = struct {...@@ -397,7 +397,7 @@ pub const ArgIteratorWindows = struct {
397 }397 }
398 }398 }
399399
400 fn emitBackslashes(self: *ArgIteratorWindows, buf: *std.ArrayList(u8), emit_count: usize) !void {400 fn emitBackslashes(self: *ArgIteratorWindows, buf: *std.ArrayListSentineled(u8, 0), emit_count: usize) !void {
401 var i: usize = 0;401 var i: usize = 0;
402 while (i < emit_count) : (i += 1) {402 while (i < emit_count) : (i += 1) {
403 try buf.append('\\');403 try buf.append('\\');
...@@ -437,21 +437,21 @@ pub const ArgIterator = struct {...@@ -437,21 +437,21 @@ pub const ArgIterator = struct {
437 pub const NextError = ArgIteratorWindows.NextError;437 pub const NextError = ArgIteratorWindows.NextError;
438438
439 /// You must free the returned memory when done.439 /// You must free the returned memory when done.
440 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) {440 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![:0]u8) {
441 if (builtin.os.tag == .windows) {441 if (builtin.os.tag == .windows) {
442 return self.inner.next(allocator);442 return self.inner.next(allocator);
443 } else {443 } else {
444 return allocator.dupe(u8, self.inner.next() orelse return null);444 return allocator.dupeZ(u8, self.inner.next() orelse return null);
445 }445 }
446 }446 }
447447
448 /// If you only are targeting posix you can call this and not need an allocator.448 /// If you only are targeting posix you can call this and not need an allocator.
449 pub fn nextPosix(self: *ArgIterator) ?[]const u8 {449 pub fn nextPosix(self: *ArgIterator) ?[:0]const u8 {
450 return self.inner.next();450 return self.inner.next();
451 }451 }
452452
453 /// If you only are targeting WASI, you can call this and not need an allocator.453 /// If you only are targeting WASI, you can call this and not need an allocator.
454 pub fn nextWasi(self: *ArgIterator) ?[]const u8 {454 pub fn nextWasi(self: *ArgIterator) ?[:0]const u8 {
455 return self.inner.next();455 return self.inner.next();
456 }456 }
457457
...@@ -501,7 +501,7 @@ test "args iterator" {...@@ -501,7 +501,7 @@ test "args iterator" {
501}501}
502502
503/// Caller must call argsFree on result.503/// Caller must call argsFree on result.
504pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {504pub fn argsAlloc(allocator: *mem.Allocator) ![][:0]u8 {
505 // TODO refactor to only make 1 allocation.505 // TODO refactor to only make 1 allocation.
506 var it = if (builtin.os.tag == .wasi) try argsWithAllocator(allocator) else args();506 var it = if (builtin.os.tag == .wasi) try argsWithAllocator(allocator) else args();
507 defer it.deinit();507 defer it.deinit();
...@@ -515,35 +515,36 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {...@@ -515,35 +515,36 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
515 while (it.next(allocator)) |arg_or_err| {515 while (it.next(allocator)) |arg_or_err| {
516 const arg = try arg_or_err;516 const arg = try arg_or_err;
517 defer allocator.free(arg);517 defer allocator.free(arg);
518 try contents.appendSlice(arg);518 try contents.appendSlice(arg[0 .. arg.len + 1]);
519 try slice_list.append(arg.len);519 try slice_list.append(arg.len);
520 }520 }
521521
522 const contents_slice = contents.span();522 const contents_slice = contents.span();
523 const slice_sizes = slice_list.span();523 const slice_sizes = slice_list.span();
524 const contents_size_bytes = try math.add(usize, contents_slice.len, slice_sizes.len);
524 const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len);525 const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len);
525 const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len);526 const total_bytes = try math.add(usize, slice_list_bytes, contents_size_bytes);
526 const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);527 const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);
527 errdefer allocator.free(buf);528 errdefer allocator.free(buf);
528529
529 const result_slice_list = mem.bytesAsSlice([]u8, buf[0..slice_list_bytes]);530 const result_slice_list = mem.bytesAsSlice([:0]u8, buf[0..slice_list_bytes]);
530 const result_contents = buf[slice_list_bytes..];531 const result_contents = buf[slice_list_bytes..];
531 mem.copy(u8, result_contents, contents_slice);532 mem.copy(u8, result_contents, contents_slice);
532533
533 var contents_index: usize = 0;534 var contents_index: usize = 0;
534 for (slice_sizes) |len, i| {535 for (slice_sizes) |len, i| {
535 const new_index = contents_index + len;536 const new_index = contents_index + len;
536 result_slice_list[i] = result_contents[contents_index..new_index];537 result_slice_list[i] = result_contents[contents_index..new_index :0];
537 contents_index = new_index;538 contents_index = new_index + 1;
538 }539 }
539540
540 return result_slice_list;541 return result_slice_list;
541}542}
542543
543pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {544pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const [:0]u8) void {
544 var total_bytes: usize = 0;545 var total_bytes: usize = 0;
545 for (args_alloc) |arg| {546 for (args_alloc) |arg| {
546 total_bytes += @sizeOf([]u8) + arg.len;547 total_bytes += @sizeOf([]u8) + arg.len + 1;
547 }548 }
548 const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes];549 const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes];
549 const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf);550 const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf);