From a59e4b64550dc5af29161b08a4819772aa1dfb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Fri, 22 Feb 2019 21:29:18 +0100 Subject: [PATCH] Make handling of corrupt Windows file system watcher events more robust. The reason for the intermittent corruptions still needs to be found. --- source/eventcore/drivers/winapi/watchers.d | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/source/eventcore/drivers/winapi/watchers.d b/source/eventcore/drivers/winapi/watchers.d index bb7c162..fb89444 100644 --- a/source/eventcore/drivers/winapi/watchers.d +++ b/source/eventcore/drivers/winapi/watchers.d @@ -135,10 +135,11 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { while (result.length) { assert(result.length >= FILE_NOTIFY_INFORMATION._FileName.offsetof); auto fni = () @trusted { return cast(FILE_NOTIFY_INFORMATION*)result.ptr; } (); - if (fni.NextEntryOffset > result.length) { + auto fulllen = () @trusted { try return cast(ubyte*)&fni.FileName[fni.FileNameLength/2] - result.ptr; catch (Exception e) return size_t.max; } (); + if (fni.NextEntryOffset > result.length || fulllen > (fni.NextEntryOffset ? fni.NextEntryOffset : result.length)) { import std.stdio : stderr; () @trusted { - try stderr.writeln("ERROR: Invalid directory watcher event received."); + try stderr.writefln("ERROR: Invalid directory watcher event received: %s", *fni); catch (Exception e) {} } (); break; @@ -156,7 +157,23 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { } ch.baseDirectory = slot.directory; - auto path = () @trusted { try return fni.FileName[0 .. fni.FileNameLength/2].map!(ch => dchar(ch)).to!string; catch (Exception e) assert(false, e.msg); } (); + string path; + try { + () @trusted { + path = fni.FileName[0 .. fni.FileNameLength/2].map!(ch => dchar(ch)).to!string; + } (); + } catch (Exception e) { + import std.stdio : stderr; + // NOTE: sometimes corrupted strings and invalid UTF-16 + // surrogate pairs occur here, until the cause of this is + // found, the best alternative is to ignore those changes + () @trusted { + try stderr.writefln("Invalid path in directory change: %(%02X %)", cast(ushort[])fni.FileName[0 .. fni.FileNameLength/2]); + catch (Exception e) assert(false, e.msg); + } (); + if (fni.NextEntryOffset > 0) continue; + else break; + } auto fullpath = buildPath(slot.directory, path); ch.directory = dirName(path); if (ch.directory == ".") ch.directory = "";