std.file functions and embedded NUL characters [CWE-158]
kdevel
kdevel at vogtner.de
Tue Aug 5 02:47:22 UTC 2025
On Sunday, 3 August 2025 at 21:01:05 UTC, Steven Schveighoffer
wrote:
> On Sunday, 3 August 2025 at 00:03:47 UTC, kdevel wrote:
>> On Friday, 1 August 2025 at 17:53:17 UTC, Steven Schveighoffer
>> wrote:
>>> [...]
>>> It's always a fight between correctness and performance here.
>>
>> Pardon?
>
> I mean in terms of where you apply the checks. You can say "I
> expect you to have validated this before sending it in", or you
> can say "I will always validate this, even if you already have,
> in the name of correctness."
>
> And I suppose a better word should have been "tradeoff" and not
> "fight".
I like the fragment "[...] it has to be correct before being
fast."
> [...]
> The issue is going to be fixed, not sure if you saw my issue
> report. It's quite an easy fix actually.
Thanks but sorry I could not yet take a look.
> But just so you know, C also allows passing in C strings with
> embedded null characters:
>
> ```c
> #include <unistd.h>
>
> int main() {
> rmdir("hello\0world");
> return 0;
> }
> ```
On the one hand there is no such thing as a C string with
embedded `NUL` (because the `NUL` terminates the string).
On the other hand the `rmdir` function takes `const char
*pathname`. Your code contains an array argument
(`"hello\0world"`). According to C's rules this array decays into
a pointer *before* `rmdir` is invoked. Thus one can hardly say
that a string with embedded `NUL` is passed to the function.
> And we do expose `core.stdc.posix.unistd`.
Yes. But in the D-function in question is `std.file.rmdir`. I
copied the relevant code:
```D
import std.stdio : writeln;
import std.range : isSomeFiniteCharInputRange;
import std.traits : isConvertibleToString;
void rmdir (R) (R pathname)
if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
{
writeln (__PRETTY_FUNCTION__);
writeln (typeid (pathname));
writeln (pathname.length);
writeln (pathname);
}
void rmdir(R)(auto ref R pathname)
if (isConvertibleToString!R)
{
writeln (__PRETTY_FUNCTION__);
writeln (typeid (pathname));
writeln (pathname.length);
writeln (pathname);
}
void main ()
{
rmdir ("a\0b");
}
```
which prints
```
void rmdir.rmdir!string.rmdir(string pathname)
immutable(char)[]
3
ab <--- there is a NUL between a and b
```
I.e. the function really takes the string with the embedded `NUL`.
More information about the Digitalmars-d
mailing list