*BSD News Article 10271


Return to BSD News archive

Received: by minnie.vk1xwt.ampr.org with NNTP
	id AA7615 ; Mon, 25 Jan 93 12:18:51 EST
Newsgroups: comp.unix.bsd
Path: sserve!manuel.anu.edu.au!munnari.oz.au!metro!ipso!runxtsa!bde
From: bde@runx.oz.au (Bruce Evans)
Subject: [386BSD] Bug + fix: getcwd off by one
Message-ID: <1993Jan22.185211.5564@runx.oz.au>
Organization: RUNX Un*x Timeshare.  Sydney, Australia.
Date: Fri, 22 Jan 93 18:52:11 GMT
Lines: 87

getcwd() has two off-by-one bugs in 386BSD-0.1:

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.

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);
}
---

This might be a fix:

---
*** /usr/src/lib/libc/gen/getcwd.c~	Wed May  1 10:35:50 1991
--- /usr/src/lib/libc/gen/getcwd.c	Tue Jan 19 22:22:38 1993
***************
*** 74,78 ****
  	if (pt) {
  		ptsize = 0;
! 		if (!size) {
  			errno = EINVAL;
  			return((char *)NULL);
--- 74,78 ----
  	if (pt) {
  		ptsize = 0;
! 		if (size < 2) {
  			errno = EINVAL;
  			return((char *)NULL);
***************
*** 186,190 ****
  		 * leading slash.
  		 */
! 		if (bpt - pt <= dp->d_namlen + (first ? 1 : 2)) {
  			size_t len, off;
  
--- 186,190 ----
  		 * leading slash.
  		 */
! 		if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
  			size_t len, off;
  
---
-- 
Bruce Evans  (bde@runx.oz.au)