Skip to content

Commit 768b177

Browse files
authored
Merge pull request #19615 from ianic/tar_diagnostic
std.tar: add strip components error to diagnostics
2 parents efb00c2 + e035085 commit 768b177

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

lib/std/tar.zig

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ pub const Diagnostics = struct {
4646
file_name: []const u8,
4747
file_type: Header.Kind,
4848
},
49+
components_outside_stripped_prefix: struct {
50+
file_name: []const u8,
51+
},
4952
};
5053

5154
fn findRoot(d: *Diagnostics, path: []const u8) !void {
@@ -97,6 +100,9 @@ pub const Diagnostics = struct {
97100
.unsupported_file_type => |info| {
98101
d.allocator.free(info.file_name);
99102
},
103+
.components_outside_stripped_prefix => |info| {
104+
d.allocator.free(info.file_name);
105+
},
100106
}
101107
}
102108
d.errors.deinit(d.allocator);
@@ -623,18 +629,24 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: PipeOptions)
623629

624630
while (try iter.next()) |file| {
625631
const file_name = stripComponents(file.name, options.strip_components);
632+
if (file_name.len == 0 and file.kind != .directory) {
633+
const d = options.diagnostics orelse return error.TarComponentsOutsideStrippedPrefix;
634+
try d.errors.append(d.allocator, .{ .components_outside_stripped_prefix = .{
635+
.file_name = try d.allocator.dupe(u8, file.name),
636+
} });
637+
continue;
638+
}
626639
if (options.diagnostics) |d| {
627640
try d.findRoot(file_name);
628641
}
629642

630643
switch (file.kind) {
631644
.directory => {
632-
if (file_name.len != 0 and !options.exclude_empty_directories) {
645+
if (file_name.len > 0 and !options.exclude_empty_directories) {
633646
try dir.makePath(file_name);
634647
}
635648
},
636649
.file => {
637-
if (file_name.len == 0) return error.BadFileName;
638650
if (createDirAndFile(dir, file_name, fileMode(file.mode, options))) |fs_file| {
639651
defer fs_file.close();
640652
try file.writeAll(fs_file);
@@ -647,7 +659,6 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: PipeOptions)
647659
}
648660
},
649661
.sym_link => {
650-
if (file_name.len == 0) return error.BadFileName;
651662
const link_name = file.link_name;
652663
createDirAndSymlink(dir, link_name, file_name) catch |err| {
653664
const d = options.diagnostics orelse return error.UnableToCreateSymLink;
@@ -1096,6 +1107,30 @@ test "findRoot without explicit root dir" {
10961107
try testing.expectEqualStrings("root", diagnostics.root_dir);
10971108
}
10981109

1110+
test "pipeToFileSystem strip_components" {
1111+
const data = @embedFile("tar/testdata/example.tar");
1112+
var fbs = std.io.fixedBufferStream(data);
1113+
const reader = fbs.reader();
1114+
1115+
var tmp = testing.tmpDir(.{ .no_follow = true });
1116+
defer tmp.cleanup();
1117+
var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1118+
defer diagnostics.deinit();
1119+
1120+
pipeToFileSystem(tmp.dir, reader, .{
1121+
.strip_components = 3,
1122+
.diagnostics = &diagnostics,
1123+
}) catch |err| {
1124+
// Skip on platform which don't support symlinks
1125+
if (err == error.UnableToCreateSymLink) return error.SkipZigTest;
1126+
return err;
1127+
};
1128+
1129+
try testing.expectEqual(2, diagnostics.errors.items.len);
1130+
try testing.expectEqualStrings("example/b/symlink", diagnostics.errors.items[0].components_outside_stripped_prefix.file_name);
1131+
try testing.expectEqualStrings("example/a/file", diagnostics.errors.items[1].components_outside_stripped_prefix.file_name);
1132+
}
1133+
10991134
fn normalizePath(bytes: []u8) []u8 {
11001135
const canonical_sep = std.fs.path.sep_posix;
11011136
if (std.fs.path.sep == canonical_sep) return bytes;

src/Package/Fetch.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,7 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackRes
11891189
.unable_to_create_file => |i| res.unableToCreateFile(stripRoot(i.file_name, res.root_dir), i.code),
11901190
.unable_to_create_sym_link => |i| res.unableToCreateSymLink(stripRoot(i.file_name, res.root_dir), i.link_name, i.code),
11911191
.unsupported_file_type => |i| res.unsupportedFileType(stripRoot(i.file_name, res.root_dir), @intFromEnum(i.file_type)),
1192+
.components_outside_stripped_prefix => unreachable, // unreachable with strip_components = 0
11921193
}
11931194
}
11941195
}

0 commit comments

Comments
 (0)