mirror of https://github.com/mkerrisk/man-pages
readlink.2: Fix an off-by-one error in example code
An off-by-one error could trigger a buffer overflow in some cases in the old code. See https://bugzilla.kernel.org/show_bug.cgi?id=196483 Also some other cosmetic changes to the code (more comments, better variable names). Reported-by: Jason Noakes <jjnoakes@gmail.com> Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
parent
928cf4522f
commit
f06a3f30fa
|
@ -282,8 +282,8 @@ falling back to a buffer of size
|
|||
in cases where
|
||||
.BR lstat (2)
|
||||
reports a size of zero.
|
||||
.PP
|
||||
.nf
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
|
@ -295,8 +295,8 @@ int
|
|||
main(int argc, char *argv[])
|
||||
{
|
||||
struct stat sb;
|
||||
char *linkname;
|
||||
ssize_t r, bufsiz;
|
||||
char *buf;
|
||||
ssize_t nbytes, bufsiz;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <pathname>\\n", argv[0]);
|
||||
|
@ -308,37 +308,42 @@ main(int argc, char *argv[])
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Add one to the link size, so that we can determine whether
|
||||
the buffer returned by readlink() was truncated. */
|
||||
|
||||
bufsiz = sb.st_size + 1;
|
||||
|
||||
/* Some magic symlinks under (for example) /proc and /sys
|
||||
report \(aqst_size\(aq as zero. In that case, take PATH_MAX as
|
||||
a "good enough" estimate */
|
||||
a "good enough" estimate. */
|
||||
|
||||
if (sb.st_size == 0)
|
||||
bufsiz = PATH_MAX;
|
||||
|
||||
printf("%zd\\n", bufsiz);
|
||||
|
||||
linkname = malloc(bufsiz);
|
||||
if (linkname == NULL) {
|
||||
buf = malloc(bufsiz);
|
||||
if (buf == NULL) {
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = readlink(argv[1], linkname, bufsiz);
|
||||
if (r == \-1) {
|
||||
nbytes = readlink(argv[1], buf, bufsiz);
|
||||
if (nbytes == \-1) {
|
||||
perror("readlink");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
linkname[r] = \(aq\\0\(aq;
|
||||
printf("\(aq%s\(aq points to \(aq%.*s\(aq\\n", argv[1], (int) nbytes, buf);
|
||||
|
||||
printf("\(aq%s\(aq points to \(aq%s\(aq\\n", argv[1], linkname);
|
||||
/* If the return value was equal to the buffer size, then the
|
||||
the link target was larger than expected (perhaps because the
|
||||
target was changed between the call to lstat() and the call to
|
||||
readlink()). Warn the user that the returned target may have
|
||||
been truncated. */
|
||||
|
||||
if (r == bufsiz)
|
||||
if (nbytes == bufsiz)
|
||||
printf("(Returned buffer may have been truncated)\\n");
|
||||
|
||||
free(linkname);
|
||||
free(buf);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
.fi
|
||||
|
|
Loading…
Reference in New Issue