diff options
author | bde <bde@FreeBSD.org> | 1994-12-12 01:29:13 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1994-12-12 01:29:13 +0000 |
commit | 0184c7ba037026b52ee3c41d7cec30fdea92f4fa (patch) | |
tree | e6d548dac258fa48a11d88dd63144e7aef4c9372 | |
parent | f9bd31e5430250e2089d716355836256f2f2bf1d (diff) | |
download | FreeBSD-src-0184c7ba037026b52ee3c41d7cec30fdea92f4fa.zip FreeBSD-src-0184c7ba037026b52ee3c41d7cec30fdea92f4fa.tar.gz |
Obtained from: 1.1.5
getcwd() has two off-by-one bugs in FreeBSD-2.0:
1. getcwd(buf, size) fails when the size is just large enough.
2. getcwd(buf + 1, 1) incorrectly succeeds when the current directory
is "/". buf[0] and buf[2] are clobbered.
(I modified Bruce's original patch to return the proper error code
[ERANGE] in the case of #2, but otherwise... -DG)
This program demonstrates the bug:
---
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char buf[5];
int errors;
errors = 0;
if (chdir("/tmp") != 0) {
perror("chdir");
abort();
}
if (getcwd(buf, 5) == NULL) {
perror("oops, getcwd failed for buffer size = size required");
++errors;
}
if (chdir("/") != 0) {
perror("chdir");
abort();
}
buf[0] = 0;
buf[2] = 1;
if (getcwd(buf + 1, 1) != NULL) {
fprintf(stderr,
"oops, getcwd succeeded for buffer size = one too small\n");
++errors;
}
if (buf[0] != 0) {
fprintf(stderr,
"oops, getcwd scribbled on memory before start of buffer\n");
++errors;
}
if (buf[2] != 1) {
fprintf(stderr,
"oops, getcwd scribbled on memory after end of buffer\n");
++errors;
}
exit(errors == 0 ? 0 : 1);
}
-rw-r--r-- | lib/libc/gen/getcwd.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/lib/libc/gen/getcwd.c b/lib/libc/gen/getcwd.c index 4797f7c..2757d3b 100644 --- a/lib/libc/gen/getcwd.c +++ b/lib/libc/gen/getcwd.c @@ -78,6 +78,10 @@ getcwd(pt, size) errno = EINVAL; return (NULL); } + if (size == 1) { + errno = ERANGE; + return (NULL); + } ept = pt + size; } else { if ((pt = malloc(ptsize = 1024 - 4)) == NULL) @@ -187,7 +191,7 @@ getcwd(pt, size) * Check for length of the current name, preceding slash, * leading slash. */ - if (bpt - pt <= dp->d_namlen + (first ? 1 : 2)) { + if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) { size_t len, off; if (!ptsize) { |