Commit 4624c81899

Ryan Liptak <squeek502@hotmail.com>
2022-07-24 05:14:34
std.fs: Fix Walker closing the initial directory when not fully iterated
This is a fix for a regression caused by https://github.com/ziglang/zig/commit/61c5d8f8f19d4321a492cb8a1adc4d221024f7d9 Closes #12209
1 parent 934573f
Changed files (2)
lib
lib/std/fs/test.zig
@@ -1034,6 +1034,30 @@ test "walker" {
     try testing.expectEqual(expected_paths.kvs.len, num_walked);
 }
 
+test "walker without fully iterating" {
+    if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
+    if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
+
+    var tmp = tmpIterableDir(.{});
+    defer tmp.cleanup();
+
+    var walker = try tmp.iterable_dir.walk(testing.allocator);
+    defer walker.deinit();
+
+    // Create 2 directories inside the tmp directory, but then only iterate once before breaking.
+    // This ensures that walker doesn't try to close the initial directory when not fully iterating.
+
+    try tmp.iterable_dir.dir.makePath("a");
+    try tmp.iterable_dir.dir.makePath("b");
+
+    var num_walked: usize = 0;
+    while (try walker.next()) |_| {
+        num_walked += 1;
+        break;
+    }
+    try testing.expectEqual(@as(usize, 1), num_walked);
+}
+
 test ". and .. in fs.Dir functions" {
     if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
     if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
lib/std/fs.zig
@@ -889,8 +889,11 @@ pub const IterableDir = struct {
         }
 
         pub fn deinit(self: *Walker) void {
-            for (self.stack.items) |*item| {
-                item.iter.dir.close();
+            // Close any remaining directories except the initial one (which is always at index 0)
+            if (self.stack.items.len > 1) {
+                for (self.stack.items[1..]) |*item| {
+                    item.iter.dir.close();
+                }
             }
             self.stack.deinit();
             self.name_buffer.deinit();