Skip to content

std.fs: improve error-handling for openDirW #14533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

yuyoyuppe
Copy link

@yuyoyuppe yuyoyuppe commented Feb 3, 2023

Scenario where the bug manifests itself in a real use-case.

While adding a cmake dependency to build.zig with:

b.addSystemCommand(&[_][]const u8{ "cmake", "-DCMAKE_BUILD_TYPE=Release", ".", "-B", "build" });

I've encountered unreachable which was caused by this line. It turns out my %PATH% had an incorrect entry: :\Program Files\7-Zip - notice no C at the start.

So what happens is that as part of spawnWindows Zig searches through each %PATH% entry to find an absolute path of cmake executable, and instead of skipping an invalid entry we panic on it.

You can repro the panic with this MRE:

var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();
var broken_dir = try std.unicode.utf8ToUtf16LeWithNull(allocator, ":\\Program Files\\7-Zip");
_ = try std.fs.cwd().openDirW(broken_dir, .{}, true);

There's no info in the original commit why it handles it as such, so I assume it's reasonable to treat the error as error.NotDir instead.

@squeek502
Copy link
Collaborator

squeek502 commented Feb 5, 2023

My understanding is the the unreachable here is intentional because it's assumed to be programmer error to pass invalid/malformed paths to fs functions. I'm not totally sold on that reasoning personally, but in keeping with this logic, the fix to the PATH searching problem might be to validate search paths instead of removing the unreachable here.

The relevant code for that would be within this loop:

while (it.next()) |search_path| {

I'm unsure what validation should be done in particular--is it required for search paths to be absolute? If so, then an isAbsolute check might be sufficient. If not, then it might need some special handling.

EDIT: Seems like relative paths do/can work in PATH, so some other validation would be necessary.

@yuyoyuppe
Copy link
Author

yuyoyuppe commented Feb 5, 2023

I've noticed a few places where OBJECT_NAME_INVALID was handled in a similar fashion, but it isn't always consistent. If there's an intent behind those unreachables, perhaps we could make those preconditions explicit with comments/asserts.

I couldn't find a function which reliably validates path, there's windowsParsePath but it accepts stuff like "::\\Program Files\\7-Zip".

@matu3ba
Copy link
Contributor

matu3ba commented Feb 5, 2023

I couldn't find a function which reliably validates path

Why does isAbsolute in lib/std/fs/path.zig or resolve not work? I do agree insofar as that a function isRelative would make things more consistent and isRelative should not need any allocation.

Do you want to make a PR or do you want me to create one?
https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats

Specifically the cases \Program Files and C:Projects sounds like they could have special handling, as they look very surprising for users to handle + its quite abit boilerplate to write for Windows.

@squeek502
Copy link
Collaborator

squeek502 commented Feb 5, 2023

Why does isAbsolute in lib/std/fs/path.zig or resolve not work?

Relative paths are allowed as search paths in PATH, so isAbsolute would fix this particular scenario but break others. std.fs.path.resolveWindows can only fail with error.OutOfMemory, so it can't be used to determine he validity of the path.

We'll likely need a function that actually validates paths (not sure if there's much precedence for this?), or abandon the OBJECT_NAME_INVALID => unreachable strategy.

@yuyoyuppe
Copy link
Author

If you decide to do the validation with isRelative approach, please go ahead @matu3ba.

@squeek502
Copy link
Collaborator

@andrewrk if it makes this easier to review, this PR is a very targeted change to fix one particular manifestation (bad path in %PATH% leading to unreachable when spawning a process on Windows) of what I think is a much larger problem that I've laid out here: #15607

My personal opinion about this particular PR:

@andrewrk
Copy link
Member

I solved this in f1a9344 and the path forward on #15607 is now clear.

@andrewrk andrewrk closed this Oct 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants