Thread overview | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 31 std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Some python code: #!/usr/bin/python def myfun (filename): open (filename, 'w') myfun ("a\0c") which when executed behaves in an exemplary manner: Traceback (most recent call last): File "./test.py", line 6, in <module> myfun ("a\0c") File "./test.py", line 4, in myfun open (filename, 'w') TypeError: file() argument 1 must be encoded string without null bytes, not str Other languages like D, perl or even Ada seem to let the embedded NUL character silently truncate the filename. This poses a considerable risk when the input to std.file functions is not controlled by the program author [1]. E.g. rmdirRecurse ("/\0/home/user/subdir"); [1] https://cwe.mitre.org/data/definitions/158.html |
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to kdevel | On Thursday, 31 July 2025 at 20:45:14 UTC, kdevel wrote:
> Some python code:
>
> #!/usr/bin/python
>
> def myfun (filename):
> open (filename, 'w')
>
> myfun ("a\0c")
>
> which when executed behaves in an exemplary manner:
>
> Traceback (most recent call last):
> File "./test.py", line 6, in <module>
> myfun ("a\0c")
> File "./test.py", line 4, in myfun
> open (filename, 'w')
> TypeError: file() argument 1 must be encoded string without null
> bytes, not str
>
> Other languages like D, perl or even Ada seem to let the embedded NUL
> character silently truncate the filename. This poses a considerable
> risk when the input to std.file functions is not controlled by the
> program author [1]. E.g.
>
> rmdirRecurse ("/\0/home/user/subdir");
>
> [1] https://cwe.mitre.org/data/definitions/158.html
Do you actually have a source or an example program that D actually does anything with the null terminator or are you talking out of your ass? D doesn't care about the null terminator and doesn't do anything with it.
Try this code on run.dlang.io and report back with your apology:
import std.stdio;
void main()
{
writeln("Hello\0World\0!");
}
|
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Doigt | On Thu, Jul 31, 2025 at 09:25:44PM +0000, Doigt via Digitalmars-d wrote: > On Thursday, 31 July 2025 at 20:45:14 UTC, kdevel wrote: [...] > > Other languages like D, perl or even Ada seem to let the embedded NUL character silently truncate the filename. This poses a considerable risk when the input to std.file functions is not controlled by the program author [1]. E.g. > > > > rmdirRecurse ("/\0/home/user/subdir"); > > > > [1] https://cwe.mitre.org/data/definitions/158.html > > Do you actually have a source or an example program that D actually does anything with the null terminator or are you talking out of your ass? D doesn't care about the null terminator and doesn't do anything with it. This tone is uncalled for. OP is specifically pointing the issue with passing NUL-containing strings to underlying OS calls. For example: ``` void main() { auto fp = File("/tmp/x\0reallynow", "w"); // What's the filename of the created file? } ``` T -- Last night, I dreamed about my pet rabbits all lined up like in a parade, and hopping backwards. Then I woke up and realized that it was my receding hare line! |
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Doigt | On Thursday, 31 July 2025 at 21:25:44 UTC, Doigt wrote:
> On Thursday, 31 July 2025 at 20:45:14 UTC, kdevel wrote:
>> Some python code:
>>
>> #!/usr/bin/python
>>
>> def myfun (filename):
>> open (filename, 'w')
>>
>> myfun ("a\0c")
>>
>> which when executed behaves in an exemplary manner:
>>
>> Traceback (most recent call last):
>> File "./test.py", line 6, in <module>
>> myfun ("a\0c")
>> File "./test.py", line 4, in myfun
>> open (filename, 'w')
>> TypeError: file() argument 1 must be encoded string without null
>> bytes, not str
>>
>> Other languages like D, perl or even Ada seem to let the embedded NUL
>> character silently truncate the filename. This poses a considerable
>> risk when the input to std.file functions is not controlled by the
>> program author [1]. E.g.
>>
>> rmdirRecurse ("/\0/home/user/subdir");
>>
>> [1] https://cwe.mitre.org/data/definitions/158.html
>
> Do you actually have a source or an example program that D actually does anything with the null terminator or are you talking out of your ass? D doesn't care about the null terminator and doesn't do anything with it.
>
> Try this code on run.dlang.io and report back with your apology:
> import std.stdio;
> void main()
> {
> writeln("Hello\0World\0!");
> }
D does nothing with the NULL terminator, but I think the argument here is that for many file operations, the filename string eventually gets converted to a C string before it is passed to an API (C stdlib? syscall?) where the null terminator is significant.
It is best NOT to be rude and nasty, but if you are, you should at least understand the technical argument
|
August 01 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to kdevel | This is quite a good example of why for PhobosV3 I want us to go through a FilePath abstraction, rather than accepting random strings for file names. This is indeed a security vulnerability, but it isn't on D's side. All system API's take in a null terminated string, when it should've been pointer + length. If someone has a problem with this currently, you can call ``isValidPath`` in ``std.path``, which will check for the null character. https://dlang.org/phobos/std_path.html#isValidPath |
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Doigt | On Thursday, 31 July 2025 at 21:25:44 UTC, Doigt wrote:
> [...]
> Do you actually have a source or an example program that D actually does anything with the null terminator
I did not argue that D "does" something "with the null terminator".
D like perl or Ada ignores the potential occurrence of NUL in the
string data when calling the underlying C functions for file system
operations.
import std;
void main ()
{
File ("abc", "w");
std.file.rename ("abc", "ab\0c");
}
Instead of throwing as the python code does this D program leaves
a file named "ab" in the filesystem.
|
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard (Rikki) Andrew Cattermole | On Thursday, 31 July 2025 at 21:47:24 UTC, Richard (Rikki) Andrew Cattermole wrote:
> This is quite a good example of why for PhobosV3 I want us to go through a FilePath abstraction, rather than accepting random strings for file names.
whats wrong with just changing toStringz? I dont understand the threat profile imagined by the infinitely wise cve org; but you could make toStringz:
a) shorten it to the first null char
b) replace null with something
c) (bad idea but youll love it) assert when detecting extra null
|
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to kdevel | On Thursday, 31 July 2025 at 20:45:14 UTC, kdevel wrote: > Some python code: > > #!/usr/bin/python > > def myfun (filename): > open (filename, 'w') > > myfun ("a\0c") > > which when executed behaves in an exemplary manner: > > Traceback (most recent call last): > File "./test.py", line 6, in <module> > myfun ("a\0c") > File "./test.py", line 4, in myfun > open (filename, 'w') > TypeError: file() argument 1 must be encoded string without null > bytes, not str > > Other languages like D, perl or even Ada seem to let the embedded NUL > character silently truncate the filename. This poses a considerable > risk when the input to std.file functions is not controlled by the > program author [1]. E.g. > > rmdirRecurse ("/\0/home/user/subdir"); > > [1] https://cwe.mitre.org/data/definitions/158.html https://github.com/dlang/phobos/blob/205256abb1f86faf986f8c789cb733ca4137246e/std/string.d#L368 are you sure? Im not entirely sure if this will always trigger but theres asserts here |
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard (Rikki) Andrew Cattermole | On Thursday, 31 July 2025 at 21:47:24 UTC, Richard (Rikki) Andrew Cattermole wrote: > This is indeed a security vulnerability, but it isn't on D's side. > All system API's take in a null terminated string, when it should've been pointer + length. The cause of the problem is the silent truncation when the conversion from D-string to C-const char * takes place. This is not a problem of the API which is in the case of POSIX is totally simple (compared to all the VMS/Windows APIs). There must be a reason why C++ uses const char* in its filesystem functions [1]. > If someone has a problem with this currently, you can call ``isValidPath`` in ``std.path``, which will check for the null character. Unfortunately isValidPath also flags perfectly legal filenames as invalid, e.g. such containing invalid UTF-8 sequences. [1] https://en.cppreference.com/w/cpp/header/iostream.html |
July 31 Re: std.file functions and embedded NUL characters [CWE-158] | ||||
---|---|---|---|---|
| ||||
Posted in reply to kdevel | On Thursday, 31 July 2025 at 22:38:41 UTC, kdevel wrote:
> Unfortunately isValidPath also flags perfectly legal filenames
> as invalid, e.g. such containing invalid UTF-8 sequences.
I stand corrected. This is probably not true:
ivp.d:
```
import std;
void main (string [] args)
{
auto input = "a\xfc";
writeln (input, ": ", isValidPath (input));
}
```
$ ./ivp [latin9 mode console]
aü: true
|
Copyright © 1999-2021 by the D Language Foundation