Skip to content

Commit 29e438f

Browse files
committed
more sentinel-terminated pointers std lib integration
See #3767
1 parent 15d415e commit 29e438f

14 files changed

+98
-94
lines changed

doc/langref.html.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -4865,7 +4865,7 @@ const mem = std.mem;
48654865
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
48664866
const window_name = [1][*]const u8{"window name"};
48674867
const x: [*]const ?[*]const u8 = &window_name;
4868-
assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
4868+
assert(mem.eql(u8, std.mem.toSliceConst(u8, @ptrCast([*:0]const u8, x[0].?)), "window name"));
48694869
}
48704870
{#code_end#}
48714871
{#header_close#}

lib/std/c.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub extern "c" fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [
102102
pub extern "c" fn dup(fd: fd_t) c_int;
103103
pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int;
104104
pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
105-
pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
105+
pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;
106106
pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
107107
pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
108108
pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;

lib/std/debug.zig

+8-8
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
401401
const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
402402
const vaddr_end = vaddr_start + proc_sym.CodeSize;
403403
if (relative_address >= vaddr_start and relative_address < vaddr_end) {
404-
break mem.toSliceConst(u8, @ptrCast([*]u8, proc_sym) + @sizeOf(pdb.ProcSym));
404+
break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym));
405405
}
406406
},
407407
else => {},
@@ -703,9 +703,9 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
703703
return;
704704
};
705705

706-
const symbol_name = mem.toSliceConst(u8, di.strings.ptr + symbol.nlist.n_strx);
706+
const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
707707
const compile_unit_name = if (symbol.ofile) |ofile| blk: {
708-
const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
708+
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
709709
break :blk fs.path.basename(ofile_path);
710710
} else "???";
711711
if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
@@ -915,7 +915,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
915915
for (present) |_| {
916916
const name_offset = try pdb_stream.stream.readIntLittle(u32);
917917
const name_index = try pdb_stream.stream.readIntLittle(u32);
918-
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
918+
const name = mem.toSlice(u8, @ptrCast([*:0]u8, name_bytes.ptr + name_offset));
919919
if (mem.eql(u8, name, "/names")) {
920920
break :str_tab_index name_index;
921921
}
@@ -1708,7 +1708,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17081708
const gop = try di.ofiles.getOrPut(ofile);
17091709
const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: {
17101710
errdefer _ = di.ofiles.remove(ofile);
1711-
const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
1711+
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
17121712

17131713
gop.kv.value = MachOFile{
17141714
.bytes = try std.fs.Dir.cwd().readFileAllocAligned(
@@ -1741,7 +1741,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17411741
if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
17421742
(sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)
17431743
{
1744-
const sect_name = mem.toSliceConst(u8, &sect.sectname);
1744+
const sect_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &sect.sectname));
17451745
if (mem.eql(u8, sect_name, "__debug_line")) {
17461746
gop.kv.value.sect_debug_line = sect;
17471747
} else if (mem.eql(u8, sect_name, "__debug_info")) {
@@ -2323,8 +2323,8 @@ fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
23232323
}
23242324
}
23252325

2326-
fn readStringMem(ptr: *[*]const u8) []const u8 {
2327-
const result = mem.toSliceConst(u8, ptr.*);
2326+
fn readStringMem(ptr: *[*]const u8) [:0]const u8 {
2327+
const result = mem.toSliceConst(u8, @ptrCast([*:0]const u8, ptr.*));
23282328
ptr.* += result.len + 1;
23292329
return result;
23302330
}

lib/std/dynamic_library.zig

+4-4
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub const LinuxDynLib = struct {
140140
};
141141

142142
pub const ElfLib = struct {
143-
strings: [*]u8,
143+
strings: [*:0]u8,
144144
syms: [*]elf.Sym,
145145
hashtab: [*]os.Elf_Symndx,
146146
versym: ?[*]u16,
@@ -175,7 +175,7 @@ pub const ElfLib = struct {
175175
const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;
176176
if (base == maxInt(usize)) return error.BaseNotFound;
177177

178-
var maybe_strings: ?[*]u8 = null;
178+
var maybe_strings: ?[*:0]u8 = null;
179179
var maybe_syms: ?[*]elf.Sym = null;
180180
var maybe_hashtab: ?[*]os.Elf_Symndx = null;
181181
var maybe_versym: ?[*]u16 = null;
@@ -186,7 +186,7 @@ pub const ElfLib = struct {
186186
while (dynv[i] != 0) : (i += 2) {
187187
const p = base + dynv[i + 1];
188188
switch (dynv[i]) {
189-
elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
189+
elf.DT_STRTAB => maybe_strings = @intToPtr([*:0]u8, p),
190190
elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
191191
elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
192192
elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
@@ -230,7 +230,7 @@ pub const ElfLib = struct {
230230
}
231231
};
232232

233-
fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*]u8) bool {
233+
fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*:0]u8) bool {
234234
var def = def_arg;
235235
const vsym = @bitCast(u32, vsym_arg) & 0x7fff;
236236
while (true) {

lib/std/event/fs.zig

+2-4
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ pub const Request = struct {
5858
};
5959

6060
pub const Open = struct {
61-
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
62-
path: []const u8,
61+
path: [:0]const u8,
6362
flags: u32,
6463
mode: File.Mode,
6564
result: Error!fd_t,
@@ -68,8 +67,7 @@ pub const Request = struct {
6867
};
6968

7069
pub const WriteFile = struct {
71-
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
72-
path: []const u8,
70+
path: [:0]const u8,
7371
contents: []const u8,
7472
mode: File.Mode,
7573
result: Error!void,

lib/std/fs.zig

+23-21
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
2828
/// This represents the maximum size of a UTF-8 encoded file path.
2929
/// All file system operations which return a path are guaranteed to
3030
/// fit into a UTF-8 encoded array of this length.
31+
/// The byte count includes room for a null sentinel byte.
3132
pub const MAX_PATH_BYTES = switch (builtin.os) {
3233
.linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,
3334
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
@@ -227,7 +228,7 @@ pub const AtomicFile = struct {
227228
try crypto.randomBytes(rand_buf[0..]);
228229
b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
229230

230-
const file = File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
231+
const file = File.openWriteNoClobberC(@ptrCast([*:0]u8, &tmp_path_buf), mode) catch |err| switch (err) {
231232
error.PathAlreadyExists => continue,
232233
// TODO zig should figure out that this error set does not include PathAlreadyExists since
233234
// it is handled in the above switch
@@ -247,7 +248,7 @@ pub const AtomicFile = struct {
247248
pub fn deinit(self: *AtomicFile) void {
248249
if (!self.finished) {
249250
self.file.close();
250-
deleteFileC(&self.tmp_path_buf) catch {};
251+
deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
251252
self.finished = true;
252253
}
253254
}
@@ -258,11 +259,11 @@ pub const AtomicFile = struct {
258259
self.finished = true;
259260
if (builtin.os == .windows) {
260261
const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
261-
const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
262+
const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));
262263
return os.renameW(&tmp_path_w, &dest_path_w);
263264
}
264265
const dest_path_c = try os.toPosixPath(self.dest_path);
265-
return os.renameC(&self.tmp_path_buf, &dest_path_c);
266+
return os.renameC(@ptrCast([*:0]u8, &self.tmp_path_buf), &dest_path_c);
266267
}
267268
};
268269

@@ -274,12 +275,12 @@ pub fn makeDir(dir_path: []const u8) !void {
274275
}
275276

276277
/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
277-
pub fn makeDirC(dir_path: [*]const u8) !void {
278+
pub fn makeDirC(dir_path: [*:0]const u8) !void {
278279
return os.mkdirC(dir_path, default_new_dir_mode);
279280
}
280281

281282
/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
282-
pub fn makeDirW(dir_path: [*]const u16) !void {
283+
pub fn makeDirW(dir_path: [*:0]const u16) !void {
283284
return os.mkdirW(dir_path, default_new_dir_mode);
284285
}
285286

@@ -327,12 +328,12 @@ pub fn deleteDir(dir_path: []const u8) !void {
327328
}
328329

329330
/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
330-
pub fn deleteDirC(dir_path: [*]const u8) !void {
331+
pub fn deleteDirC(dir_path: [*:0]const u8) !void {
331332
return os.rmdirC(dir_path);
332333
}
333334

334335
/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
335-
pub fn deleteDirW(dir_path: [*]const u16) !void {
336+
pub fn deleteDirW(dir_path: [*:0]const u16) !void {
336337
return os.rmdirW(dir_path);
337338
}
338339

@@ -688,7 +689,7 @@ pub const Dir = struct {
688689
}
689690

690691
/// Same as `open` except the parameter is null-terminated.
691-
pub fn openC(dir_path_c: [*]const u8) OpenError!Dir {
692+
pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir {
692693
return cwd().openDirC(dir_path_c);
693694
}
694695

@@ -708,7 +709,7 @@ pub const Dir = struct {
708709
}
709710

710711
/// Call `File.close` on the result when done.
711-
pub fn openReadC(self: Dir, sub_path: [*]const u8) File.OpenError!File {
712+
pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {
712713
if (builtin.os == .windows) {
713714
const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
714715
return self.openReadW(&path_w);
@@ -719,7 +720,7 @@ pub const Dir = struct {
719720
return File.openHandle(fd);
720721
}
721722

722-
pub fn openReadW(self: Dir, sub_path_w: [*]const u16) File.OpenError!File {
723+
pub fn openReadW(self: Dir, sub_path_w: [*:0]const u16) File.OpenError!File {
723724
const w = os.windows;
724725

725726
var result = File{ .handle = undefined };
@@ -786,7 +787,7 @@ pub const Dir = struct {
786787
}
787788

788789
/// Same as `openDir` except the parameter is null-terminated.
789-
pub fn openDirC(self: Dir, sub_path_c: [*]const u8) OpenError!Dir {
790+
pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
790791
if (builtin.os == .windows) {
791792
const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
792793
return self.openDirW(&sub_path_w);
@@ -805,7 +806,7 @@ pub const Dir = struct {
805806

806807
/// Same as `openDir` except the path parameter is UTF16LE, NT-prefixed.
807808
/// This function is Windows-only.
808-
pub fn openDirW(self: Dir, sub_path_w: [*]const u16) OpenError!Dir {
809+
pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
809810
const w = os.windows;
810811

811812
var result = Dir{
@@ -868,7 +869,7 @@ pub const Dir = struct {
868869
}
869870

870871
/// Same as `deleteFile` except the parameter is null-terminated.
871-
pub fn deleteFileC(self: Dir, sub_path_c: [*]const u8) DeleteFileError!void {
872+
pub fn deleteFileC(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
872873
os.unlinkatC(self.fd, sub_path_c, 0) catch |err| switch (err) {
873874
error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
874875
else => |e| return e,
@@ -903,7 +904,7 @@ pub const Dir = struct {
903904
}
904905

905906
/// Same as `deleteDir` except the parameter is null-terminated.
906-
pub fn deleteDirC(self: Dir, sub_path_c: [*]const u8) DeleteDirError!void {
907+
pub fn deleteDirC(self: Dir, sub_path_c: [*:0]const u8) DeleteDirError!void {
907908
os.unlinkatC(self.fd, sub_path_c, os.AT_REMOVEDIR) catch |err| switch (err) {
908909
error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
909910
else => |e| return e,
@@ -912,7 +913,7 @@ pub const Dir = struct {
912913

913914
/// Same as `deleteDir` except the parameter is UTF16LE, NT prefixed.
914915
/// This function is Windows-only.
915-
pub fn deleteDirW(self: Dir, sub_path_w: [*]const u16) DeleteDirError!void {
916+
pub fn deleteDirW(self: Dir, sub_path_w: [*:0]const u16) DeleteDirError!void {
916917
os.unlinkatW(self.fd, sub_path_w, os.AT_REMOVEDIR) catch |err| switch (err) {
917918
error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
918919
else => |e| return e,
@@ -927,7 +928,7 @@ pub const Dir = struct {
927928
}
928929

929930
/// Same as `readLink`, except the `pathname` parameter is null-terminated.
930-
pub fn readLinkC(self: Dir, sub_path_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
931+
pub fn readLinkC(self: Dir, sub_path_c: [*:0]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
931932
return os.readlinkatC(self.fd, sub_path_c, buffer);
932933
}
933934

@@ -1250,7 +1251,8 @@ pub fn openSelfExe() OpenSelfExeError!File {
12501251
var buf: [MAX_PATH_BYTES]u8 = undefined;
12511252
const self_exe_path = try selfExePath(&buf);
12521253
buf[self_exe_path.len] = 0;
1253-
return File.openReadC(self_exe_path.ptr);
1254+
// TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
1255+
return File.openReadC(@ptrCast([*:0]u8, self_exe_path.ptr));
12541256
}
12551257

12561258
test "openSelfExe" {
@@ -1277,7 +1279,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
12771279
var u32_len: u32 = out_buffer.len;
12781280
const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
12791281
if (rc != 0) return error.NameTooLong;
1280-
return mem.toSlice(u8, out_buffer);
1282+
return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
12811283
}
12821284
switch (builtin.os) {
12831285
.linux => return os.readlinkC("/proc/self/exe", out_buffer),
@@ -1306,9 +1308,9 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
13061308
}
13071309

13081310
/// The result is UTF16LE-encoded.
1309-
pub fn selfExePathW() []const u16 {
1311+
pub fn selfExePathW() [:0]const u16 {
13101312
const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;
1311-
return mem.toSliceConst(u16, image_path_name.Buffer);
1313+
return mem.toSliceConst(u16, @ptrCast([*:0]const u16, image_path_name.Buffer));
13121314
}
13131315

13141316
/// `selfExeDirPath` except allocates the result on the heap.

lib/std/fs/file.zig

+7-7
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub const File = struct {
3131
}
3232

3333
/// Deprecated; call `std.fs.Dir.openReadC` directly.
34-
pub fn openReadC(path_c: [*]const u8) OpenError!File {
34+
pub fn openReadC(path_c: [*:0]const u8) OpenError!File {
3535
return std.fs.Dir.cwd().openReadC(path_c);
3636
}
3737

@@ -61,7 +61,7 @@ pub const File = struct {
6161

6262
/// Same as `openWriteMode` except `path` is null-terminated.
6363
/// TODO: deprecate this and move it to `std.fs.Dir`.
64-
pub fn openWriteModeC(path: [*]const u8, file_mode: Mode) OpenError!File {
64+
pub fn openWriteModeC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
6565
if (builtin.os == .windows) {
6666
const path_w = try windows.cStrToPrefixedFileW(path);
6767
return openWriteModeW(&path_w, file_mode);
@@ -74,7 +74,7 @@ pub const File = struct {
7474

7575
/// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded
7676
/// TODO: deprecate this and move it to `std.fs.Dir`.
77-
pub fn openWriteModeW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
77+
pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
7878
const handle = try windows.CreateFileW(
7979
path_w,
8080
windows.GENERIC_WRITE,
@@ -101,7 +101,7 @@ pub const File = struct {
101101
}
102102

103103
/// TODO: deprecate this and move it to `std.fs.Dir`.
104-
pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File {
104+
pub fn openWriteNoClobberC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
105105
if (builtin.os == .windows) {
106106
const path_w = try windows.cStrToPrefixedFileW(path);
107107
return openWriteNoClobberW(&path_w, file_mode);
@@ -113,7 +113,7 @@ pub const File = struct {
113113
}
114114

115115
/// TODO: deprecate this and move it to `std.fs.Dir`.
116-
pub fn openWriteNoClobberW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
116+
pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
117117
const handle = try windows.CreateFileW(
118118
path_w,
119119
windows.GENERIC_WRITE,
@@ -142,13 +142,13 @@ pub const File = struct {
142142

143143
/// Same as `access` except the parameter is null-terminated.
144144
/// TODO: deprecate this and move it to `std.fs.Dir`.
145-
pub fn accessC(path: [*]const u8) !void {
145+
pub fn accessC(path: [*:0]const u8) !void {
146146
return os.accessC(path, os.F_OK);
147147
}
148148

149149
/// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
150150
/// TODO: deprecate this and move it to `std.fs.Dir`.
151-
pub fn accessW(path: [*]const u16) !void {
151+
pub fn accessW(path: [*:0]const u16) !void {
152152
return os.accessW(path, os.F_OK);
153153
}
154154

0 commit comments

Comments
 (0)