[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[MiNT] another getcwd fix (includes previous patch)



Another problem with getcwd() is that it defines a variable sized buffer
for _path (which is non-ANSI as the note says).

With gcc optimizations this gets messed up and crashes, probably due to
stack corruption.

Replacing that code with dynamically allocated code works with
optimizations too.

I've also added the ENAMETOOLONG check to unx2dos().

(NOTE: this replaces the last patch)

Alan.
Index: mintlib/getcwd.c
===================================================================
RCS file: /mint/mintlib/mintlib/getcwd.c,v
retrieving revision 1.6
diff -u -r1.6 getcwd.c
--- mintlib/getcwd.c	8 Oct 2003 15:23:14 -0000	1.6
+++ mintlib/getcwd.c	7 Jan 2008 20:05:53 -0000
@@ -24,20 +24,26 @@
 char *
 __getcwd (char *buf, size_t size)
 {
-	const int len = (size > 0 ? size : PATH_MAX) + 16;
-	char _path[len]; /* XXX non ANSI */
-	char *path;
+	int len;
+	char *path, *_path;
 	char drv;
 	int buf_malloced = 0;
 	int r;
 
+	len = (size > 0 ? size : PATH_MAX) + 16;
+	_path = malloc(len);
+	if (!_path)
+		return NULL;
+
 	if (!buf) {
 		if (size == 0)
 			size = PATH_MAX;
 		
 		buf = malloc (size);
-		if (!buf)
+		if (!buf) {
+			free(_path);
 			return NULL;
+		}
 		
 		buf_malloced = 1;
 	}
@@ -52,6 +58,7 @@
 	if (r != 0 && r != -ENOSYS) {
 		if (buf_malloced)
 			free(buf);
+		free(_path);
 		__set_errno (-r);
 		return NULL;
 	}
@@ -69,6 +76,13 @@
 	else
 		/* convert DOS filename to unix */
 		_dos2unx(_path, buf, size);
+
+	if (errno == ENAMETOOLONG) {
+		if (buf_malloced)
+			free(buf);
+		free(_path);
+		return NULL;
+	}
 	
 	if (buf_malloced) {
 		size_t len = strlen (buf) + 1;
@@ -79,6 +93,8 @@
 			buf = newptr;
 	}
 
+	free(_path);
+
 	return buf;
 }
 weak_alias (__getcwd, getcwd)
Index: mintlib/unx2dos.c
===================================================================
RCS file: /mint/mintlib/mintlib/unx2dos.c,v
retrieving revision 1.5
diff -u -r1.5 unx2dos.c
--- mintlib/unx2dos.c	8 Oct 2003 15:23:14 -0000	1.5
+++ mintlib/unx2dos.c	7 Jan 2008 20:05:53 -0000
@@ -1,5 +1,6 @@
 
 #include <ctype.h>
+#include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
@@ -11,11 +12,15 @@
 
 /*
  * returns 0 for ordinary files, 1 for special files (like /dev/tty)
+ *
+ * or returns -1 on error, such as ENAMETOOLONG
  */
 
 int
 _unx2dos(const char *unx, char *dos, size_t len)
 {
+	register int unx_length = strlen(unx);
+	register int count = 0;
 	const char *u;
 	char *d, c;
 
@@ -76,6 +81,7 @@
 	}
 
 	while( (c = *u++) != 0 ) {
+		count++;
 		if (c == '/')
 			c = '\\';
 #if 0
@@ -91,8 +97,14 @@
 #endif
 		*d++ = c;
 		len--;
-		if (len == 0)
+		if (len == 0) {
+			if (count < unx_length) {
+				__set_errno(ENAMETOOLONG);
+				*d = 0;
+				return -1;
+			}
 			break;
+		}
 	}
 	*d = 0;
 	return 0;
@@ -101,6 +113,8 @@
 int
 _dos2unx(const char *dos, char *unx, size_t len)
 {
+	register int dos_length = strlen(dos);
+	register int count = 0;
 	register char c;
 
 	len--;			/* for terminating NUL */
@@ -133,14 +147,21 @@
 	/* convert slashes
 	 */
 	while ( (c = *dos++) != 0) {
+		count++;
 		if (c == '\\')
 			c = '/';
 		else if (__mint < 7)
 			c = tolower(c);
 		*unx++ = c;
 		len--;
-		if (len == 0)
+		if (len == 0) {
+			if (count < dos_length) {
+				__set_errno(ENAMETOOLONG);
+				*unx = 0;
+				return -1;
+			}
 			break;
+		}
 	}
 	*unx = 0;
 	return 0;