authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-23 03:58:32+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-24 18:28:16+00:00
logaf0668d6c2c7696e695cf0553c1ae2d593e9effe
tree8738e4432c42dddcb8005a8e3ab58135424f0fa4
parent879ea2710f1e1bafab1d3e212cbba37aaf6b818d

Build.Cache: fix UAF during `unhit`


1 files changed, 19 insertions(+), 11 deletions(-)

lib/std/Build/Cache.zig+19-11
...@@ -526,7 +526,7 @@ pub const Manifest = struct {...@@ -526,7 +526,7 @@ pub const Manifest = struct {
526 break :f file;526 break :f file;
527 }527 }
528 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});528 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});
529 errdefer assert(self.files.popOrNull() != null);529 errdefer _ = self.files.pop();
530 if (!gop.found_existing) {530 if (!gop.found_existing) {
531 gop.key_ptr.* = .{531 gop.key_ptr.* = .{
532 .prefixed_path = .{532 .prefixed_path = .{
...@@ -633,10 +633,10 @@ pub const Manifest = struct {...@@ -633,10 +633,10 @@ pub const Manifest = struct {
633 self.hash.hasher.update(&bin_digest);633 self.hash.hasher.update(&bin_digest);
634634
635 // Remove files not in the initial hash.635 // Remove files not in the initial hash.
636 for (self.files.keys()[input_file_count..]) |*file| {636 while (self.files.count() != input_file_count) {
637 file.deinit(self.cache.gpa);637 var file = self.files.pop();
638 file.key.deinit(self.cache.gpa);
638 }639 }
639 self.files.shrinkRetainingCapacity(input_file_count);
640640
641 for (self.files.keys()) |file| {641 for (self.files.keys()) |file| {
642 self.hash.hasher.update(&file.bin_digest);642 self.hash.hasher.update(&file.bin_digest);
...@@ -736,19 +736,27 @@ pub const Manifest = struct {...@@ -736,19 +736,27 @@ pub const Manifest = struct {
736 const prefixed_path = try self.cache.findPrefix(file_path);736 const prefixed_path = try self.cache.findPrefix(file_path);
737 errdefer gpa.free(prefixed_path.sub_path);737 errdefer gpa.free(prefixed_path.sub_path);
738738
739 const new_ch_file = try self.files.addOne(gpa);739 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});
740 new_ch_file.* = .{740 errdefer _ = self.files.pop();
741
742 if (gop.found_existing) {
743 gpa.free(prefixed_path.sub_path);
744 return gop.key_ptr.contents.?;
745 }
746
747 gop.key_ptr.* = .{
741 .prefixed_path = prefixed_path,748 .prefixed_path = prefixed_path,
742 .max_file_size = max_file_size,749 .max_file_size = max_file_size,
743 .stat = undefined,750 .stat = undefined,
744 .bin_digest = undefined,751 .bin_digest = undefined,
745 .contents = null,752 .contents = null,
746 };753 };
747 errdefer self.files.shrinkRetainingCapacity(self.files.entries.len - 1);
748754
749 try self.populateFileHash(new_ch_file);755 self.files.lockPointers();
756 defer self.files.unlockPointers();
750757
751 return new_ch_file.contents.?;758 try self.populateFileHash(gop.key_ptr);
759 return gop.key_ptr.contents.?;
752 }760 }
753761
754 /// Add a file as a dependency of process being cached, after the initial hash has been762 /// Add a file as a dependency of process being cached, after the initial hash has been
...@@ -765,7 +773,7 @@ pub const Manifest = struct {...@@ -765,7 +773,7 @@ pub const Manifest = struct {
765 errdefer gpa.free(prefixed_path.sub_path);773 errdefer gpa.free(prefixed_path.sub_path);
766774
767 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});775 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});
768 errdefer assert(self.files.popOrNull() != null);776 errdefer _ = self.files.pop();
769777
770 if (gop.found_existing) {778 if (gop.found_existing) {
771 gpa.free(prefixed_path.sub_path);779 gpa.free(prefixed_path.sub_path);
...@@ -801,7 +809,7 @@ pub const Manifest = struct {...@@ -801,7 +809,7 @@ pub const Manifest = struct {
801 errdefer gpa.free(prefixed_path.sub_path);809 errdefer gpa.free(prefixed_path.sub_path);
802810
803 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});811 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});
804 errdefer assert(self.files.popOrNull() != null);812 errdefer _ = self.files.pop();
805813
806 if (gop.found_existing) {814 if (gop.found_existing) {
807 gpa.free(prefixed_path.sub_path);815 gpa.free(prefixed_path.sub_path);