>Synopsis: rewinddir(3) does not invalidate buffer
>Category: library
>Environment:
System : OpenBSD 7.7
Details : OpenBSD 7.7 (GENERIC.MP) #2: Sun Jun 29 09:04:02 MDT 2025
[email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
Architecture: OpenBSD.amd64
Machine : amd64
>Description:
According to POSIX.1-2004:
> The rewinddir() function shall reset the position of the directory
> stream to which dirp refers to the beginning of the directory. It
> shall also cause the directory stream to refer to the current state of
> the corresponding directory, as a call to opendir() would have
> done.
However, OpenBSD rewinddir(3) does not invalidate the buffer
dirp->dd_buf, so the next call to readdir(3) will reuse stale data.
>How-To-Repeat:
Reproducer:
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
void main()
{
DIR *dir = opendir(".");
struct dirent *e;
e = readdir(dir);
puts(e->d_name);
close(open("new", O_RDWR | O_CREAT, 0666));
rewinddir(dir);
puts("");
while ((e = readdir(dir)))
puts(e->d_name);
}
Run this in a dir which has a few files, but no file "new". The file
"new" is being created, but the iteration after rewinddir does not
pick it up.
(I think this doesn't show up as a problem in practice since running
readdir until it returns 0 will do the right thing in rewinddir.)
>Fix:
I think it's enough to set dirp->dd_size = 0 in rewinddir, but I've
not tested this.
--
Leah Neukirchen <[email protected]> https://leahneukirchen.org/