Olivier Certner <o...@freebsd.org> writes:
> Only the latest POSIX release (Issue 8, 2024) amended the wording to
> unequivocally require that, even if previous versions could be
> considered to hint at that.  I did not survey some other open-source
> implementations, maybe in practice they all meet that requirement.
> But even if they do, we don't really know about proprietary systems.
> Also, readdir_r() has just been obsoleted in Issue 8, only a year ago,
> so again I don't understand the hurry in actually *removing* it unless
> there is a clear security issue or it is actively obstructing some
> other grand plan.

readdir_r() should never have existed.

* It writes a variable amount of data to a caller-provided buffer
  without knowing its size.  It's not the only function that does this,
  but usually the size of the buffer is well-defined.  That is not the
  case for readdir_r().  Callers have to check in advance by calling
  pathconf() or fpathconf() not just once at startup but _for every
  directory they open_.

* Because unionfs exists, it is possible for pathconf() to return the
  wrong value.  If you union-mount a directory with a small _PC_NAME_MAX
  on top of a directory with a large _PC_NAME_MAX, fpathconf() will
  return the smaller of the two values.  If you size your buffer
  accordingly and the lower directory has children with long names, you
  will suffer a buffer overrun.

* People have gotten used to reflexively choosing foo_r() over foo()
  when both exist.  In most cases that is the correct choice, but in
  this particular case readdir() is almost always completely safe to use
  (the only exception is if you have multiple threads calling readdir()
  with the same DIR *, which is a bad idea and easily avoided).  It is
  also faster than readdir_r().

* The fact that Rust uses readdir_r() on FreeBSD is evidence that it
  needs to die.  There was _never_ a reason to prefer readdir_r() over
  readdir() on FreeBSD, yet people who consider themselves experts in
  safe programming chose to use it, and continued using it for nearly a
  decade after being made aware that it was the wrong choice and that it
  was going to be deprecated in POSIX.  They should have switched across
  the board back in 2016, but they made the deliberate choice to only
  switch on Linux.  The deprecation notice in the manual page didn't
  bother them; annotating the prototype had no effect because they
  provide their own.  Rust is (hopefully) going to get fixed now, but
  the only way to avoid a repeat performance is to drop readdir_r().

DES
-- 
Dag-Erling Smørgrav - d...@freebsd.org

Reply via email to