Commit 7eb938c909

daurnimator <quae@daurnimator.com>
2020-03-12 14:52:28
Use length field as passed in stage2 libc_installation instead of relying on zero termination
1 parent e535057
src/cache_hash.cpp
@@ -27,11 +27,17 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) {
 void cache_mem(CacheHash *ch, const char *ptr, size_t len) {
     assert(ch->manifest_file_path == nullptr);
     assert(ptr != nullptr);
-    // + 1 to include the null byte
     blake2b_update(&ch->blake, ptr, len);
 }
 
+void cache_slice(CacheHash *ch, Slice<const char> slice) {
+    // mix the length into the hash so that two juxtaposed cached slices can't collide
+    cache_usize(ch, slice.len);
+    cache_mem(ch, slice.ptr, slice.len);
+}
+
 void cache_str(CacheHash *ch, const char *ptr) {
+    // + 1 to include the null byte
     cache_mem(ch, ptr, strlen(ptr) + 1);
 }
 
src/cache_hash.hpp
@@ -36,6 +36,7 @@ void cache_init(CacheHash *ch, Buf *manifest_dir);
 
 // Next, use the hash population functions to add the initial parameters.
 void cache_mem(CacheHash *ch, const char *ptr, size_t len);
+void cache_slice(CacheHash *ch, Slice<const char> slice);
 void cache_str(CacheHash *ch, const char *ptr);
 void cache_int(CacheHash *ch, int x);
 void cache_bool(CacheHash *ch, bool x);
src/codegen.cpp
@@ -9123,21 +9123,26 @@ static void detect_libc(CodeGen *g) {
         g->libc_include_dir_len = 0;
         g->libc_include_dir_list = heap::c_allocator.allocate<const char *>(dir_count);
 
-        g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->include_dir;
+        g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_create_from_mem(g->libc->include_dir, g->libc->include_dir_len));
         g->libc_include_dir_len += 1;
 
         if (want_sys_dir) {
-            g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->sys_include_dir;
+            g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_create_from_mem(g->libc->sys_include_dir, g->libc->sys_include_dir_len));
             g->libc_include_dir_len += 1;
         }
 
         if (want_um_and_shared_dirs != 0) {
-            g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf(
-                        "%s" OS_SEP ".." OS_SEP "um", g->libc->include_dir));
+            Buf *include_dir_parent = buf_alloc();
+            os_path_join(buf_create_from_mem(g->libc->include_dir, g->libc->include_dir_len), buf_create_from_str(".."), include_dir_parent);
+
+            Buf *buff1 = buf_alloc();
+            os_path_join(include_dir_parent, buf_create_from_str("um"), buff1);
+            g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buff1);
             g->libc_include_dir_len += 1;
 
-            g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf(
-                        "%s" OS_SEP ".." OS_SEP "shared", g->libc->include_dir));
+            Buf *buff2 = buf_alloc();
+            os_path_join(include_dir_parent, buf_create_from_str("shared"), buff2);
+            g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buff2);
             g->libc_include_dir_len += 1;
         }
         assert(g->libc_include_dir_len == dir_count);
@@ -10546,11 +10551,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
     cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
     cache_list_of_str(ch, g->framework_dirs.items, g->framework_dirs.length);
     if (g->libc) {
-        cache_str(ch, g->libc->include_dir);
-        cache_str(ch, g->libc->sys_include_dir);
-        cache_str(ch, g->libc->crt_dir);
-        cache_str(ch, g->libc->msvc_lib_dir);
-        cache_str(ch, g->libc->kernel32_lib_dir);
+        cache_slice(ch, Slice<const char>{g->libc->include_dir, g->libc->include_dir_len});
+        cache_slice(ch, Slice<const char>{g->libc->sys_include_dir, g->libc->sys_include_dir_len});
+        cache_slice(ch, Slice<const char>{g->libc->crt_dir, g->libc->crt_dir_len});
+        cache_slice(ch, Slice<const char>{g->libc->msvc_lib_dir, g->libc->msvc_lib_dir_len});
+        cache_slice(ch, Slice<const char>{g->libc->kernel32_lib_dir, g->libc->kernel32_lib_dir_len});
     }
     cache_buf_opt(ch, g->version_script_path);
     cache_buf_opt(ch, g->override_soname);
src/link.cpp
@@ -1595,7 +1595,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
     } else {
         assert(parent->libc != nullptr);
         Buf *out_buf = buf_alloc();
-        os_path_join(buf_create_from_str(parent->libc->crt_dir), buf_create_from_str(file), out_buf);
+        os_path_join(buf_create_from_mem(parent->libc->crt_dir, parent->libc->crt_dir_len), buf_create_from_str(file), out_buf);
         return buf_ptr(out_buf);
     }
 }
@@ -1860,7 +1860,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
     if (g->libc_link_lib != nullptr) {
         if (g->libc != nullptr) {
             lj->args.append("-L");
-            lj->args.append(g->libc->crt_dir);
+            lj->args.append(buf_ptr(buf_create_from_mem(g->libc->crt_dir, g->libc->crt_dir_len)));
         }
 
         if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) {
@@ -2381,14 +2381,26 @@ static void construct_linker_job_coff(LinkJob *lj) {
     lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path))));
 
     if (g->libc_link_lib != nullptr && g->libc != nullptr) {
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir)));
+        Buf *buff0 = buf_create_from_str("-LIBPATH:");
+        buf_append_mem(buff0, g->libc->crt_dir, g->libc->crt_dir_len);
+        lj->args.append(buf_ptr(buff0));
 
         if (target_abi_is_gnu(g->zig_target->abi)) {
-            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->sys_include_dir)));
-            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->include_dir)));
+            Buf *buff1 = buf_create_from_str("-LIBPATH:");
+            buf_append_mem(buff1, g->libc->sys_include_dir, g->libc->sys_include_dir_len);
+            lj->args.append(buf_ptr(buff1));
+
+            Buf *buff2 = buf_create_from_str("-LIBPATH:");
+            buf_append_mem(buff2, g->libc->include_dir, g->libc->include_dir_len);
+            lj->args.append(buf_ptr(buff2));
         } else {
-            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->msvc_lib_dir)));
-            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->kernel32_lib_dir)));
+            Buf *buff1 = buf_create_from_str("-LIBPATH:");
+            buf_append_mem(buff1, g->libc->msvc_lib_dir, g->libc->msvc_lib_dir_len);
+            lj->args.append(buf_ptr(buff1));
+
+            Buf *buff2 = buf_create_from_str("-LIBPATH:");
+            buf_append_mem(buff2, g->libc->kernel32_lib_dir, g->libc->kernel32_lib_dir_len);
+            lj->args.append(buf_ptr(buff2));
         }
     }
 
src-self-hosted/libc_installation.zig
@@ -14,11 +14,11 @@ usingnamespace @import("windows_sdk.zig");
 
 /// See the render function implementation for documentation of the fields.
 pub const LibCInstallation = struct {
-    include_dir: ?[:0]const u8 = null,
-    sys_include_dir: ?[:0]const u8 = null,
-    crt_dir: ?[:0]const u8 = null,
-    msvc_lib_dir: ?[:0]const u8 = null,
-    kernel32_lib_dir: ?[:0]const u8 = null,
+    include_dir: ?[]const u8 = null,
+    sys_include_dir: ?[]const u8 = null,
+    crt_dir: ?[]const u8 = null,
+    msvc_lib_dir: ?[]const u8 = null,
+    kernel32_lib_dir: ?[]const u8 = null,
 
     pub const FindError = error{
         OutOfMemory,
@@ -327,15 +327,20 @@ pub const LibCInstallation = struct {
         var search_buf: [2]Search = undefined;
         const searches = fillSearch(&search_buf, sdk);
 
-        var result_buf = try std.Buffer.initSize(allocator, 0);
-        defer result_buf.deinit();
-
         for (searches) |search| {
-            result_buf.shrink(0);
-            const stream = result_buf.outStream();
-            try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version });
-
-            var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) {
+            const dir_path = try fs.path.join(
+                allocator,
+                &[_][]const u8{
+                    search.path,
+                    "Include",
+                    search.version,
+                    "ucrt",
+                },
+            );
+            var found = false;
+            defer if (!found) allocator.free(dir_path);
+
+            var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) {
                 error.FileNotFound,
                 error.NotDir,
                 error.NoDevice,
@@ -350,7 +355,8 @@ pub const LibCInstallation = struct {
                 else => return error.FileSystem,
             };
 
-            self.include_dir = result_buf.toOwnedSlice();
+            found = true;
+            self.include_dir = dir_path;
             return;
         }
 
@@ -367,9 +373,6 @@ pub const LibCInstallation = struct {
         var search_buf: [2]Search = undefined;
         const searches = fillSearch(&search_buf, sdk);
 
-        var result_buf = try std.Buffer.initSize(allocator, 0);
-        defer result_buf.deinit();
-
         const arch_sub_dir = switch (builtin.arch) {
             .i386 => "x86",
             .x86_64 => "x64",
@@ -378,11 +381,20 @@ pub const LibCInstallation = struct {
         };
 
         for (searches) |search| {
-            result_buf.shrink(0);
-            const stream = result_buf.outStream();
-            try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir });
-
-            var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) {
+            const dir_path = try fs.path.join(
+                allocator,
+                &[_][]const u8{
+                    search.path,
+                    "Lib",
+                    search.version,
+                    "ucrt",
+                    arch_sub_dir,
+                },
+            );
+            var found = false;
+            defer if (!found) allocator.free(dir_path);
+
+            var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) {
                 error.FileNotFound,
                 error.NotDir,
                 error.NoDevice,
@@ -397,7 +409,8 @@ pub const LibCInstallation = struct {
                 else => return error.FileSystem,
             };
 
-            self.crt_dir = result_buf.toOwnedSlice();
+            found = true;
+            self.crt_dir = dir_path;
             return;
         }
         return error.LibCRuntimeNotFound;
@@ -421,10 +434,6 @@ pub const LibCInstallation = struct {
 
         var search_buf: [2]Search = undefined;
         const searches = fillSearch(&search_buf, sdk);
-
-        var result_buf = try std.Buffer.initSize(allocator, 0);
-        defer result_buf.deinit();
-
         const arch_sub_dir = switch (builtin.arch) {
             .i386 => "x86",
             .x86_64 => "x64",
@@ -433,11 +442,20 @@ pub const LibCInstallation = struct {
         };
 
         for (searches) |search| {
-            result_buf.shrink(0);
-            const stream = result_buf.outStream();
-            try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir });
-
-            var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) {
+            const dir_path = try fs.path.join(
+                allocator,
+                &[_][]const u8{
+                    search.path,
+                    "Lib",
+                    search.version,
+                    "um",
+                    arch_sub_dir,
+                },
+            );
+            var found = false;
+            defer if (!found) allocator.free(dir_path);
+
+            var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) {
                 error.FileNotFound,
                 error.NotDir,
                 error.NoDevice,
@@ -452,7 +470,8 @@ pub const LibCInstallation = struct {
                 else => return error.FileSystem,
             };
 
-            self.kernel32_lib_dir = result_buf.toOwnedSlice();
+            found = true;
+            self.kernel32_lib_dir = dir_path;
             return;
         }
         return error.LibCKernel32LibNotFound;
@@ -470,12 +489,16 @@ pub const LibCInstallation = struct {
         const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound;
         const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound;
 
-        var result_buf = try std.Buffer.init(allocator, up2);
-        defer result_buf.deinit();
-
-        try result_buf.append("\\include");
+        const dir_path = try fs.path.join(
+            allocator,
+            &[_][]const u8{
+                up2,
+                "include",
+            },
+        );
+        errdefer allocator.free(dir_path);
 
-        var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) {
+        var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) {
             error.FileNotFound,
             error.NotDir,
             error.NoDevice,
@@ -490,7 +513,7 @@ pub const LibCInstallation = struct {
             else => return error.FileSystem,
         };
 
-        self.sys_include_dir = result_buf.toOwnedSlice();
+        self.sys_include_dir = dir_path;
     }
 
     fn findNativeMsvcLibDir(
src-self-hosted/stage2.zig
@@ -741,15 +741,15 @@ fn stage2TargetParse(
 
 // ABI warning
 const Stage2LibCInstallation = extern struct {
-    include_dir: [*:0]const u8,
+    include_dir: [*]const u8,
     include_dir_len: usize,
-    sys_include_dir: [*:0]const u8,
+    sys_include_dir: [*]const u8,
     sys_include_dir_len: usize,
-    crt_dir: [*:0]const u8,
+    crt_dir: [*]const u8,
     crt_dir_len: usize,
-    msvc_lib_dir: [*:0]const u8,
+    msvc_lib_dir: [*]const u8,
     msvc_lib_dir_len: usize,
-    kernel32_lib_dir: [*:0]const u8,
+    kernel32_lib_dir: [*]const u8,
     kernel32_lib_dir_len: usize,
 
     fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void {
@@ -793,19 +793,19 @@ const Stage2LibCInstallation = extern struct {
     fn toStage2(self: Stage2LibCInstallation) LibCInstallation {
         var libc: LibCInstallation = .{};
         if (self.include_dir_len != 0) {
-            libc.include_dir = self.include_dir[0..self.include_dir_len :0];
+            libc.include_dir = self.include_dir[0..self.include_dir_len];
         }
         if (self.sys_include_dir_len != 0) {
-            libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0];
+            libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len];
         }
         if (self.crt_dir_len != 0) {
-            libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0];
+            libc.crt_dir = self.crt_dir[0..self.crt_dir_len];
         }
         if (self.msvc_lib_dir_len != 0) {
-            libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0];
+            libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len];
         }
         if (self.kernel32_lib_dir_len != 0) {
-            libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0];
+            libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len];
         }
         return libc;
     }