www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Bug in import(...) on Windows?

reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
My code (test.d):
=======
void main()
{
     import std.path: buildPath;
     pragma(msg, import("file"));
     pragma(msg, import(buildPath(".", "file")));
}
=======

Content of file "file" is one line with "hello" text.

Running command: dmd -J. -run test.d

Result on Ubuntu:
=======
hello

hello

=======

Result on Windows:
=======
hello

test.d(46): Error: file ".\\file" cannot be found or not in a 
path specified with -J
test.d(46):        while evaluating pragma(msg, 
import(buildPath([".", "file"][])))
=======

Is this a bug in dmd?
Sep 02 2020
next sibling parent Andrey Zherikov <andrey.zherikov gmail.com> writes:
Adding some verbosity:
     pragma(msg, import("file"));
     pragma(msg, buildPath(".", "file"));
     pragma(msg, import(buildPath(".", "file")));


Result on Ubuntu:
=======
hello

./file
hello

=======

Result on Windows:
=======
hello

.\file
parser.d(47): Error: file ".\\file" cannot be found or not in a 
path specified with -J
parser.d(47):        while evaluating pragma(msg, 
import(buildPath([".", "file"][])))
=======
Sep 02 2020
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 2 September 2020 at 17:39:04 UTC, Andrey Zherikov 
wrote:
 Is this a bug in dmd?
I think it is an old bug filed (I can't find it though) about inconsistent platform behavior but it is allowed by spec for the compiler to reject any path components. import("") is supposed to just give a filename, no directory path. See: https://dlang.org/spec/expression.html#import_expressions "Implementations may restrict the file name in order to avoid directory traversal security vulnerabilities. A possible restriction might be to disallow any path components in the file name."
Sep 02 2020
next sibling parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Wednesday, 2 September 2020 at 17:47:47 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 2 September 2020 at 17:39:04 UTC, Andrey Zherikov 
 wrote:
 Is this a bug in dmd?
I think it is an old bug filed (I can't find it though) about inconsistent platform behavior but it is allowed by spec for the compiler to reject any path components. import("") is supposed to just give a filename, no directory path. See: https://dlang.org/spec/expression.html#import_expressions "Implementations may restrict the file name in order to avoid directory traversal security vulnerabilities. A possible restriction might be to disallow any path components in the file name."
If I provide -Jfoo to dmd, doesn't it mean my consent to use the contents of directory foo?
Sep 02 2020
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 2 September 2020 at 18:40:55 UTC, Andrey Zherikov 
wrote:
 If I provide -Jfoo to dmd, doesn't it mean my consent to use 
 the contents of directory foo?
Yeah, but dmd has been inconsistent on platforms about if it allows subdirectories. Right now I think it just strips all slashes out so your .\ path there just gets caught in the filter.
Sep 02 2020
parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Wednesday, 2 September 2020 at 19:13:47 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 2 September 2020 at 18:40:55 UTC, Andrey Zherikov 
 wrote:
 If I provide -Jfoo to dmd, doesn't it mean my consent to use 
 the contents of directory foo?
Yeah, but dmd has been inconsistent on platforms about if it allows subdirectories. Right now I think it just strips all slashes out so your .\ path there just gets caught in the filter.
I think the issue is here: https://github.com/dlang/dmd/blob/master/src/dmd/root/filename.d#L736-L748 Does it makes sense to allow paths in import(file) unless path points through parent directory, i.e. !buildNormalizedPath(file).startsWith("..")?
Sep 02 2020
parent Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Wednesday, 2 September 2020 at 20:55:34 UTC, Andrey Zherikov 
wrote:
 I think the issue is here: 
 https://github.com/dlang/dmd/blob/master/src/dmd/root/filename.d#L736-L748
Yes, issue is there. This change (removal of "c == '\\' || ") fixes it: diff --git a/src/dmd/root/filename.d b/src/dmd/root/filename.d index 09810df8e..673582d0e 100644 --- a/src/dmd/root/filename.d +++ b/src/dmd/root/filename.d -741,7 +741,7 nothrow: for (const(char)* p = name; *p; p++) { char c = *p; - if (c == '\\' || c == ':' || c == '%' || (c == '.' && p[1] == '.') || (c == '/' && p[1] == '/')) + if (c == ':' || c == '%' || (c == '.' && p[1] == '.') || (c == '/' && p[1] == '/')) { return null; }
Sep 02 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/2/20 1:47 PM, Adam D. Ruppe wrote:
 On Wednesday, 2 September 2020 at 17:39:04 UTC, Andrey Zherikov wrote:
 Is this a bug in dmd?
I think it is an old bug filed (I can't find it though) about inconsistent platform behavior but it is allowed by spec for the compiler to reject any path components. import("") is supposed to just give a filename, no directory path. See: https://dlang.org/spec/expression.html#import_expressions "Implementations may restrict the file name in order to avoid directory traversal security vulnerabilities. A possible restriction might be to disallow any path components in the file name."
Is this the problem though? It works on DMD Linux, which shares the same front end. What I'm wondering is if it needs to be ./file instead of .\file. Can you hard code that and see if it works? FYI, I know vibe diet templates DEPEND on this behavior, and I'd be surprised if it doesn't work at all on Windows. -Steve
Sep 02 2020
parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Wednesday, 2 September 2020 at 20:23:15 UTC, Steven 
Schveighoffer wrote:
 What I'm wondering is if it needs to be ./file instead of 
 .\file. Can you hard code that and see if it works?
This actually works: pragma(msg, import("file")); pragma(msg, buildPath(".", "file")); pragma(msg, import("./file")); Result on Ubuntu: ======= hello ./file hello ======= Result on Windows: ======= hello .\file hello ======= This seems weird that I can't use std.path functions or use valid "foo\bar" paths on Windows.
Sep 02 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/2/20 4:48 PM, Andrey Zherikov wrote:
 On Wednesday, 2 September 2020 at 20:23:15 UTC, Steven Schveighoffer wrote:
 What I'm wondering is if it needs to be ./file instead of .\file. Can 
 you hard code that and see if it works?
This actually works:     pragma(msg, import("file"));     pragma(msg, buildPath(".", "file"));     pragma(msg, import("./file")); Result on Ubuntu: ======= hello ../file hello ======= Result on Windows: ======= hello ..\file hello ======= This seems weird that I can't use std.path functions or use valid "foo\bar" paths on Windows.
I don't know why it wouldn't work with native paths on Windows. But I'm not a DMD maintainer, so I don't know where to look in the code to see why it doesn't work. It might be worth filing a bug. https://issues.dlang.org -Steve
Sep 02 2020