readlink() function reads where a link points to. It makes no effort to null-terminate its second argument,
buffer. Instead, it just returns the number of characters it has written.
Noncompliant Code Example
len is equal to
sizeof(buf), the null terminator is written 1 byte past the end of
An incorrect solution to this problem is to try to make
buf large enough that it can always hold the result:
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, so the off-by-one buffer-overflow risk is still present because, between the two calls, the location of
/usr/bin/perl can change to a file system with a larger
SYMLINK_MAX value. Also, if
SYMLINK_MAX is indeterminate (that is, if
-1 without setting
errno), the code uses an arbitrary large buffer size (10,000) that it hopes will be sufficient, but there is a small chance that
readlink() can return exactly this size.
An additional issue is that
readlink() can return
-1 if it fails, causing an off-by-one underflow.
This compliant solution ensures there is no overflow by reading in only
sizeof(buf)-1 characters. It also properly checks to see if an error has occurred:
Failing to properly null-terminate the result of
readlink() can result in abnormal program termination and buffer-overflow vulnerabilities.
|Axivion Bauhaus Suite|
Avoid overflow due to reading a not zero terminated string
|CERT C: Rule POS30-C||Checks for misuse of readlink() (rule partially covered)|
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Key here (explains table format and definitions)
|CWE 2.11||CWE-170, Improper null termination||2017-06-13: CERT: Rule subset of CWE|
CERT-CWE Mapping Notes
Key here for mapping notes
CWE-170 and POS30-C
CWE-170 = Union( POS30-C, list) where list =
- Non-null terminated strings fed to functions other than POSIX readlink()