Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The readlink() function reads where a link points to. It makes no effort to NULLnull-terminate its second argument, buffer. Instead, it just returns the number of characters it has written.

...

If len is equal to sizeof(buf), the NULL null terminator will be written one byte past the end of buf.

...

An incorrect solution to this problem is to try to make buf large enough that it can always hold the result:.

Code Block
bgColor#ffcccc
long symlink_max;
size_t bufsize;
char *buf;
ssize_t len;
errno = 0;

symlink_max = pathconf("/usr/bin/", _PC_SYMLINK_MAX);
if (errno != 0) {
    /* handle error condition */
}
if (symlink_max == -1) {
    bufsize = 10000;
}
else {
    bufsize = symlink_max+1;
}

buf = (char *)malloc(bufsize);
if (buf == NULL) {
    /* handle error condition */
}

len = readlink("/usr/bin/perl", buf, bufsize);
buf[len] = '\0';

This modification incorrectly assumes that the symbolic link cannot be longer than the value of SYMLINK_MAX returned by pathconf(). However, the value returned by pathconf() is out-of-date by the time readlink() is called, and so the off-by-one buffer overflow risk is still present because in between the two calls, the location of /usr/bin/perl could change to a file system with a larger SYMLINK_MAX value. Also, if SYMLINK_MAX is indeterminate (that is, if pathconf() returned -1 without setting errno), the code uses an arbitrary large buffer size (10000) that it hopes will be sufficient, but there is a small chance that readlink() could return exactly this size.

...