From 47789cbeb341a2cf0673989df888086e7b88e287 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Tue, 27 Jan 2026 09:19:25 +0000 Subject: [PATCH] fix(watcher): handle unknown file action codes in Windows watcher Use std.meta.intToEnum instead of @enumFromInt to safely convert FILE_NOTIFY_INFORMATION.Action values. This prevents a panic if the Windows ReadDirectoryChangesW API returns an unexpected action code. Unknown action codes are now logged and skipped rather than causing a runtime panic. Fixes #26496 Co-Authored-By: Claude Opus 4.5 --- src/watcher/WindowsWatcher.zig | 37 ++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/watcher/WindowsWatcher.zig b/src/watcher/WindowsWatcher.zig index a883f91c49..28d901831a 100644 --- a/src/watcher/WindowsWatcher.zig +++ b/src/watcher/WindowsWatcher.zig @@ -59,24 +59,31 @@ const EventIterator = struct { hasNext: bool = true, pub fn next(this: *EventIterator) ?FileEvent { - if (!this.hasNext) return null; - const info_size = @sizeOf(w.FILE_NOTIFY_INFORMATION); - const info: *w.FILE_NOTIFY_INFORMATION = @ptrCast(@alignCast(this.watcher.buf[this.offset..].ptr)); - const name_ptr: [*]u16 = @ptrCast(@alignCast(this.watcher.buf[this.offset + info_size ..])); - const filename: []u16 = name_ptr[0 .. info.FileNameLength / @sizeOf(u16)]; + while (this.hasNext) { + const info_size = @sizeOf(w.FILE_NOTIFY_INFORMATION); + const info: *w.FILE_NOTIFY_INFORMATION = @ptrCast(@alignCast(this.watcher.buf[this.offset..].ptr)); + const name_ptr: [*]u16 = @ptrCast(@alignCast(this.watcher.buf[this.offset + info_size ..])); + const filename: []u16 = name_ptr[0 .. info.FileNameLength / @sizeOf(u16)]; - const action: Action = @enumFromInt(info.Action); + if (info.NextEntryOffset == 0) { + this.hasNext = false; + } else { + this.offset += @as(usize, info.NextEntryOffset); + } - if (info.NextEntryOffset == 0) { - this.hasNext = false; - } else { - this.offset += @as(usize, info.NextEntryOffset); + // Use intToEnum to safely convert the action value, skipping unknown action types. + // The Windows API may return undocumented action codes in some edge cases. + const action: Action = std.meta.intToEnum(Action, info.Action) catch { + log("skipping unknown file action: {d}", .{info.Action}); + continue; + }; + + return FileEvent{ + .action = action, + .filename = filename, + }; } - - return FileEvent{ - .action = action, - .filename = filename, - }; + return null; } };