[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
MiNTlib pl46: more robust filename handling
Hi!
The current handling of filenames in the MiNTlib is very fragile. If
names longer than PATH_MAX are passed the stack gets overwritten when
converting the name to GEMDOS format. Here is a patch that makes it
more robust by adding another parameter to _unx2dos and _dos2unx that
spezifies the size of the output buffer. (The compatibility functions
unx2dos and dos2unx remain unchanged.) Filenames longer than PATH_MAX
are simply truncated.
diff -ur orig/chdir.c lib/chdir.c
--- orig/chdir.c Tue Jul 19 18:53:04 1994
+++ lib/chdir.c Sun Sep 10 19:18:32 1995
@@ -22,7 +22,7 @@
assert ((dir != NULL));
- (void)_unx2dos(dir, tmp); /* convert Unix filename to DOS */
+ (void)_unx2dos(dir, tmp, sizeof (tmp)); /* convert Unix filename to DOS */
d = tmp;
old = Dgetdrv();
if (*d && *(d+1) == ':') {
diff -ur orig/chmod.c lib/chmod.c
--- orig/chmod.c Tue Mar 14 01:16:34 1995
+++ lib/chmod.c Sun Sep 10 19:18:54 1995
@@ -19,7 +19,7 @@
int dosattrib = 0, r;
char path[PATH_MAX];
- (void)_unx2dos(_path, path);
+ (void)_unx2dos(_path, path, sizeof (path));
r = (int)Fchmod(path, mode);
#if 1
/* Kludge: on dos filesystems return success for dirs
diff -ur orig/chown.c lib/chown.c
--- orig/chown.c Tue Mar 14 01:10:58 1995
+++ lib/chown.c Sun Sep 10 19:19:16 1995
@@ -20,7 +20,7 @@
int r;
char name[PATH_MAX];
- (void)_unx2dos(_name, name);
+ (void)_unx2dos(_name, name, sizeof (name));
r = (int)Fchown(name, uid, gid);
if (r && (r != -EINVAL)) {
errno = -r;
diff -ur orig/do_stat.c lib/do_stat.c
--- orig/do_stat.c Tue Mar 14 01:10:58 1995
+++ lib/do_stat.c Sun Sep 10 19:29:56 1995
@@ -64,7 +64,7 @@
/*
* _unx2dos returns 1 for device names (like /dev/con)
*/
- nval = _unx2dos(_path, path);
+ nval = _unx2dos(_path, path, sizeof (path));
/* try to use the build in stat() call, but if the system does not
* have it, record that and never try again
@@ -98,7 +98,7 @@
return -1;
}
buf[PATH_MAX] = 0;
- _dos2unx (buf, buf1);
+ _dos2unx (buf, buf1, sizeof (buf1));
st->st_size = strlen (buf1);
}
return 0;
diff -ur orig/execp.c lib/execp.c
--- orig/execp.c Tue Jul 19 18:53:26 1994
+++ lib/execp.c Sun Sep 10 19:30:20 1995
@@ -30,7 +30,8 @@
{
const char *execname;
char buffer[PATH_MAX];
- execname = _buffindfile(name, getenv("PATH"), extensions,buffer);
+ execname = _buffindfile(name, getenv("PATH"), extensions,buffer,
+ sizeof (buffer));
if (!execname) {
errno = ENOENT;
return -1; /* file not found */
diff -ur orig/getcwd.c lib/getcwd.c
--- orig/getcwd.c Wed Mar 2 19:08:24 1994
+++ lib/getcwd.c Sun Sep 10 19:31:36 1995
@@ -53,10 +53,10 @@
path[0] = '\\';
path[1] = '\0';
}
- _dos2unx((char *)path, buf);
+ _dos2unx((char *)path, buf, size);
return buf;
}
- _dos2unx(_path, buf); /* convert DOS filename to unix */
+ _dos2unx(_path, buf, size); /* convert DOS filename to unix */
return buf;
}
diff -ur orig/lib.h lib/lib.h
--- orig/lib.h Wed Mar 2 19:49:54 1994
+++ lib/lib.h Sun Sep 10 20:17:48 1995
@@ -17,15 +17,15 @@
typedef int (*fnmapfunc_t) __PROTO((const char *, char *));
#endif
-__EXTERN int _unx2dos __PROTO((const char *, char *));
-__EXTERN int _dos2unx __PROTO((const char *, char *));
+__EXTERN int _unx2dos __PROTO((const char *, char *, size_t));
+__EXTERN int _dos2unx __PROTO((const char *, char *, size_t));
#ifndef __MINT__
__EXTERN int unx2dos __PROTO((const char *, char *));
__EXTERN int dos2unx __PROTO((const char *, char *));
__EXTERN void fnmapfunc __PROTO((fnmapfunc_t u2dos, fnmapfunc_t dos2u));
#endif
-__EXTERN int _path_dos2unx __PROTO((const char *, char *));
-__EXTERN int _path_unx2dos __PROTO((const char *, char *));
+__EXTERN int _path_dos2unx __PROTO((const char *, char *, size_t));
+__EXTERN int _path_unx2dos __PROTO((const char *, char *, size_t));
__EXTERN long _write __PROTO((int, const void *, unsigned long));
__EXTERN long _read __PROTO((int, void *, unsigned long));
diff -ur orig/link.c lib/link.c
--- orig/link.c Mon Sep 19 18:54:08 1994
+++ lib/link.c Sun Sep 10 19:31:54 1995
@@ -24,8 +24,8 @@
errno = EXDEV;
return -1;
}
- _unx2dos(_old, old);
- _unx2dos(_new, new);
+ _unx2dos(_old, old, sizeof (old));
+ _unx2dos(_new, new, sizeof (new));
r = Flink(old, new);
if (r < 0) {
diff -ur orig/main.c lib/main.c
--- orig/main.c Wed Jan 19 22:12:12 1994
+++ lib/main.c Sun Sep 10 19:36:00 1995
@@ -196,6 +196,7 @@
}
if (!strncmp(s, p, len) && s[len] == '=') {
+ size_t size;
len++;
tmp = s + len; /* tmp now after '=' */
cnt = 1;
@@ -204,11 +205,11 @@
cnt++;
tmp++;
}
- _envp[i] = (char *)
- malloc((size_t)
- (tmp - s + cnt * 5));
+ size = tmp - s + cnt * 5;
+ _envp[i] = (char *) malloc(size);
strncpy(_envp[i], s, len);
- _path_dos2unx(s + len, _envp[i] + len);
+ _path_dos2unx(s + len, _envp[i] + len,
+ size - len);
_envp[i] = (char *) realloc(_envp[i],
strlen(_envp[i]) + 1);
break;
@@ -224,6 +225,7 @@
if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
s[3] == 'H' && s[4] == '=')
{
+ size_t size;
tmp = s + 5; /* tmp now after '=' */
cnt = 1;
while (*tmp)
@@ -233,10 +235,10 @@
cnt++;
tmp++;
}
- _envp[i] = (char *) malloc((size_t)
- (tmp - s + cnt * 5));
+ size = tmp - s + cnt * 5;
+ _envp[i] = (char *) malloc(size);
strncpy(_envp[i], s, 5);
- _path_dos2unx(s + 5, _envp[i] + 5);
+ _path_dos2unx(s + 5, _envp[i] + 5, size - 5);
_envp[i] = (char *) realloc(_envp[i],
strlen(_envp[i]) + 1);
break;
diff -ur orig/mkdir.c lib/mkdir.c
--- orig/mkdir.c Mon Sep 19 18:54:26 1994
+++ lib/mkdir.c Sun Sep 10 19:36:10 1995
@@ -23,7 +23,7 @@
int rv;
char path[PATH_MAX];
- _unx2dos(_path, path);
+ _unx2dos(_path, path, sizeof (path));
rv = stat(path, &statbuf); /* Stat directory */
if (rv == 0) { /* Does it exist ? */
diff -ur orig/mkfifo.c lib/mkfifo.c
--- orig/mkfifo.c Tue Mar 14 01:11:08 1995
+++ lib/mkfifo.c Sun Sep 10 19:36:20 1995
@@ -28,7 +28,7 @@
for id code pid&0x7fff and time>>1 in base-36, this just fits
in pipefs' limit of 14 chars... */
- _unx2dos(_path, path);
+ _unx2dos(_path, path, sizeof (path));
s = linkf + sizeof "u:\\pipe\\n$" - 1;
*s++ = ((mode >> 6) & 7) + '0';
*s++ = ((mode >> 3) & 7) + '0';
diff -ur orig/mknod.c lib/mknod.c
--- orig/mknod.c Tue Mar 14 01:11:10 1995
+++ lib/mknod.c Sun Sep 10 19:36:36 1995
@@ -33,7 +33,7 @@
if (S_ISFIFO(mode) || ((mode & S_IFMT) == 010000)) {
return (mkfifo(path, (mode_t) mode));
}
- _unx2dos (path, _path);
+ _unx2dos (path, _path, sizeof (_path));
err = Dcntl (MFS_MKNOD, _path,
((long) mode & 0xffff) | ((long) dev << 16));
if (err >= 0)
diff -ur orig/open.c lib/open.c
--- orig/open.c Tue Mar 21 01:08:12 1995
+++ lib/open.c Sun Sep 10 19:37:10 1995
@@ -74,7 +74,7 @@
va_end(argp);
#endif
- _unx2dos(_filename, filename);
+ _unx2dos(_filename, filename, sizeof (filename));
/* use the umask() setting to get the right permissions */
if (__umask == -1)
diff -ur orig/opendir.c lib/opendir.c
--- orig/opendir.c Tue Mar 14 01:21:54 1995
+++ lib/opendir.c Sun Sep 10 19:37:38 1995
@@ -47,7 +47,7 @@
return d;
}
- _unx2dos(uname, name);
+ _unx2dos(uname, name, sizeof (name));
r = Dopendir(name, 0);
if (r != -EINVAL) {
diff -ur orig/readdir.c lib/readdir.c
--- orig/readdir.c Tue Mar 14 01:11:12 1995
+++ lib/readdir.c Sun Sep 10 19:38:34 1995
@@ -89,7 +89,7 @@
}
dd->d_ino = __inode++;
dd->d_off++;
- _dos2unx(d->dta.dta_name, dd->d_name);
+ _dos2unx(d->dta.dta_name, dd->d_name, sizeof (dd->d_name));
dd->d_reclen = (short)strlen(dd->d_name);
return dd;
}
diff -ur orig/rename.c lib/rename.c
--- orig/rename.c Tue Mar 14 01:24:00 1995
+++ lib/rename.c Sun Sep 10 19:38:52 1995
@@ -19,8 +19,8 @@
struct stat oldstat;
struct stat newstat;
- _unx2dos(_oldname, oldname);
- _unx2dos(_newname, newname);
+ _unx2dos(_oldname, oldname, sizeof (oldname));
+ _unx2dos(_newname, newname, sizeof (newname));
if (__mint
&& (Fxattr(1, newname, &newstat) == 0)
diff -ur orig/rmdir.c lib/rmdir.c
--- orig/rmdir.c Tue Mar 14 01:11:16 1995
+++ lib/rmdir.c Sun Sep 10 19:39:32 1995
@@ -15,7 +15,7 @@
char path[PATH_MAX];
int r;
- _unx2dos(_path, path);
+ _unx2dos(_path, path, sizeof (path));
r = Ddelete(path);
if (r < 0) {
long d;
diff -ur orig/spawn.c lib/spawn.c
--- orig/spawn.c Tue Jul 19 18:53:36 1994
+++ lib/spawn.c Sun Sep 10 19:41:58 1995
@@ -211,7 +211,7 @@
errno = EINVAL;
return -1;
}
- (void)_unx2dos(_path, path); /* convert filename, if necessary */
+ (void)_unx2dos(_path, path, sizeof (path)); /* convert filename, if necessary */
if (!envp)
envp = environ;
@@ -283,7 +283,8 @@
goto need_more_core;
strncpy(s, p, len);
- _path_unx2dos(p + len, s + len);
+ _path_unx2dos(p + len, s + len,
+ left - len);
while (*s) {
s++; left--;
@@ -316,7 +317,7 @@
if (left - (strlen(p) + cnt * 2 + 1) < min_left)
goto need_more_core;
- _path_unx2dos(p, s);
+ _path_unx2dos(p, s, left);
while (*s) {
s++; left--;
diff -ur orig/statfs.c lib/statfs.c
--- orig/statfs.c Fri Sep 17 20:10:40 1993
+++ lib/statfs.c Sun Sep 10 19:42:26 1995
@@ -54,7 +54,7 @@
* Also f_type is 1 for V1 filesystems and 2 for V2 (it
* is zero for TOS).
*/
- _unx2dos (path, _path);
+ _unx2dos (path, _path, sizeof (_path));
if(Dcntl(0x104,_path, (long) &mfsinfo)==0)
{
buf->f_type = 1+mfsinfo.version;
diff -ur orig/symlink.c lib/symlink.c
--- orig/symlink.c Mon Sep 19 18:56:46 1994
+++ lib/symlink.c Sun Sep 10 19:43:18 1995
@@ -25,9 +25,9 @@
long r;
if (__mint >= 9) {
- _unx2dos(old, path);
- _unx2dos(new, linkname);
- r = Fsymlink(path, linkname);
+ _unx2dos(old, linkname, sizeof (linkname));
+ _unx2dos(new, path, sizeof (path));
+ r = Fsymlink(linkname, path);
if (r) {
struct stat sb;
@@ -59,7 +59,7 @@
errno = EINVAL;
return -1;
}
- _unx2dos(unxname, filename);
+ _unx2dos(unxname, filename, sizeof (filename));
r = Freadlink(PATH_MAX, linkto, filename);
if (r < 0) {
if (r == -EACCES) {
@@ -78,7 +78,7 @@
return -1;
}
linkto[PATH_MAX] = 0;
- _dos2unx(linkto, filename);
+ _dos2unx(linkto, filename, sizeof (filename));
l = strlen(filename);
if (l > siz) {
errno = ERANGE;
diff -ur orig/sysconf.c lib/sysconf.c
--- orig/sysconf.c Fri Sep 17 20:10:42 1993
+++ lib/sysconf.c Sun Sep 10 19:43:30 1995
@@ -54,7 +54,7 @@
char path[PATH_MAX];
if(__mint) {
- _unx2dos (_path, path);
+ _unx2dos (_path, path, sizeof (path));
r = Dpathconf(path, var);
if (var == _PC_NO_TRUNC)
return r ? -1 : 0;
diff -ur orig/system.c lib/system.c
--- orig/system.c Tue Jul 19 18:53:14 1994
+++ lib/system.c Sun Sep 10 19:43:50 1995
@@ -172,7 +172,7 @@
/* now actually run the program */
if (*infile) {
- (void)_unx2dos(infile,path);
+ (void)_unx2dos(infile,path, sizeof (path));
infd = (int)Fopen(path, 0);
if (infd < __SMALLEST_VALID_HANDLE) {
perror(infile);
@@ -182,7 +182,7 @@
(void)Fforce(0, infd);
}
if (*outfile) {
- (void)_unx2dos(outfile,path);
+ (void)_unx2dos(outfile,path, sizeof (path));
if (append) {
outfd = (int)Fopen(path, 2);
if (outfd < __SMALLEST_VALID_HANDLE)
diff -ur orig/truncate.c lib/truncate.c
--- orig/truncate.c Tue Mar 21 00:43:10 1995
+++ lib/truncate.c Sun Sep 10 19:44:00 1995
@@ -34,11 +34,13 @@
int fh, res;
char filename[PATH_MAX];
- (void) _unx2dos (_filename, filename);
+ (void) _unx2dos (_filename, filename, sizeof (filename));
res = -EINVAL;
if (__mint > 92)
{
res = (int) Dcntl(FTRUNCATE, (long) filename, (long) &length);
+ if (res == 0)
+ return res;
if (res != -EINVAL)
{
if ((res == -EPATH) && (_enoent(filename)))
diff -ur orig/ttyname.c lib/ttyname.c
--- orig/ttyname.c Wed Nov 3 19:45:16 1993
+++ lib/ttyname.c Sun Sep 10 19:44:54 1995
@@ -56,7 +56,7 @@
if (testsb.st_dev == sb->st_dev &&
testsb.st_ino == sb->st_ino) {
Dclosedir(drv);
- _dos2unx (_name, name);
+ _dos2unx (_name, name, L_ctermid);
return 1;
}
}
diff -ur orig/unlink.c lib/unlink.c
--- orig/unlink.c Wed Mar 2 19:08:38 1994
+++ lib/unlink.c Sun Sep 10 19:45:06 1995
@@ -27,7 +27,7 @@
char name[PATH_MAX];
int r;
- _unx2dos(filename, name);
+ _unx2dos(filename, name, sizeof (name));
r = (int)Fdelete(name);
diff -ur orig/unx2dos.c lib/unx2dos.c
--- orig/unx2dos.c Sat Dec 4 21:22:20 1993
+++ lib/unx2dos.c Sun Sep 10 20:30:48 1995
@@ -5,6 +5,7 @@
#include <types.h>
#include <param.h>
#include <support.h>
+#include <limits.h>
#include "lib.h"
extern int __mint;
@@ -17,14 +18,16 @@
*/
int
-_unx2dos(unx, dos)
+_unx2dos(unx, dos, len)
const char *unx;
char *dos;
+ size_t len;
{
const char *u;
char *d, c;
dos[0] = 0;
+ len--; /* for terminating NUL */
u = unx; d = dos;
if (!strncmp(u, "/dev/", 5)) {
u += 5;
@@ -35,19 +38,23 @@
d[0] = *u++;
d[1] = ':';
d += 2;
+ len -= 2;
}
/* check for a unix device name */
else if (__mint) {
if (__mint >= 8) {
strcpy(d, "U:\\dev\\"); d += 7;
+ len -= 7;
} else {
strcpy(d, "V:\\");
d += 3;
+ len -= 3;
}
}
else {
- strcpy(d, u);
- strcat(d, ":");
+ strncpy(d, u, len);
+ len -= strlen (u);
+ strncat(d, ":", len);
if (!strcmp(d, "tty:"))
strcpy(d, "con:");
return 1;
@@ -56,12 +63,15 @@
u += 6;
if (__mint >= 9) {
strcpy(d, "U:\\pipe\\"); d += 8;
+ len -= 8;
} else {
strcpy(d, "Q:\\"); d += 3;
+ len -= 3;
}
} else if (*u == '/' && _rootdir) {
*d++ = _rootdir;
*d++ = ':';
+ len -= 2;
}
while( (c = *u++) != 0 ) {
@@ -73,23 +83,29 @@
if ( (d > &dos[1] && d[-2] == '\\')
|| (d == &dos[1]) ) {
*dos = d[-1];
+ len += d - (dos + 1);
d = dos+1;
}
}
#endif
*d++ = c;
+ len--;
+ if (len == 0)
+ break;
}
*d = 0;
return 0;
}
int
-_dos2unx(dos, unx)
+_dos2unx(dos, unx, len)
const char *dos;
char *unx;
+ size_t len;
{
register char c;
+ len--; /* for terminating NUL */
/* replace A:\x with /dev/a/x,
* replace A:\x with /x, if _rootdir is 'a',
* replace A:\x with /a/x, if _rootdir is 'u'.
@@ -105,12 +121,15 @@
if (_rootdir != 'u') {
*unx++ = '/'; *unx++ = 'd';
*unx++ = 'e'; *unx++ = 'v';
+ len -= 4;
}
*unx++ = '/';
*unx++ = dev;
+ len -= 2;
}
if (*dos != '/' && *dos != '\\') {
*unx++ = '/';
+ len--;
}
}
/* convert slashes
@@ -121,24 +140,20 @@
else if (__mint < 7)
c = tolower(c);
*unx++ = c;
+ len--;
+ if (len == 0)
+ break;
}
*unx = 0;
return 0;
}
-#ifdef __GNUC__
-
-asm(".stabs \"_unx2dos\",5,0,0,__unx2dos"); /* dept of clean tricks */
-asm(".stabs \"_dos2unx\",5,0,0,__dos2unx"); /* dept of clean tricks */
-
-#else /* ! __GNUC__ */
-
int
unx2dos(unx, dos)
const char *unx;
char *dos;
{
- return _unx2dos(unx, dos);
+ return _unx2dos(unx, dos, PATH_MAX);
}
int
@@ -146,15 +161,14 @@
const char *dos;
char *unx;
{
- return _dos2unx(dos, unx);
+ return _dos2unx(dos, unx, PATH_MAX);
}
-#endif
-
int
-_path_unx2dos(unx, dos)
+_path_unx2dos(unx, dos, len)
const char *unx;
char *dos;
+ size_t len;
{
char buf[MAXPATHLEN], *s;
@@ -165,14 +179,22 @@
unx++;
break;
}
- *s++ = *unx++;
+ if (s < buf + sizeof (buf) - 1)
+ *s++ = *unx;
+ unx++;
}
*s = 0;
- _unx2dos(buf, dos);
- while (*dos)
+ _unx2dos(buf, dos, len);
+ while (*dos) {
dos++;
- if (*unx)
- *dos++ = ',';
+ len--;
+ }
+ if (len <= 10)
+ break;
+ if (*unx) {
+ *dos++ = ',';
+ len--;
+ }
}
*dos = 0;
@@ -180,9 +202,10 @@
}
int
-_path_dos2unx(dos, unx)
+_path_dos2unx(dos, unx, len)
const char *dos;
char *unx;
+ size_t len;
{
char buf[MAXPATHLEN], *s;
@@ -193,14 +216,22 @@
dos++;
break;
}
- *s++ = *dos++;
+ if (s < buf + sizeof (buf) - 1)
+ *s++ = *dos;
+ dos++;
}
*s = 0;
- _dos2unx(buf, unx);
- while (*unx)
+ _dos2unx(buf, unx, len);
+ while (*unx) {
unx++;
- if (*dos)
- *unx++ = ':';
+ len--;
+ }
+ if (len <= 10)
+ break;
+ if (*dos) {
+ *unx++ = ':';
+ len--;
+ }
}
*unx = 0;
diff -ur orig/utime.c lib/utime.c
--- orig/utime.c Tue Mar 14 01:11:20 1995
+++ lib/utime.c Sun Sep 10 19:45:26 1995
@@ -73,7 +73,7 @@
modtime = actime;
}
- (void)_unx2dos(_filename, filename);
+ (void)_unx2dos(_filename, filename, sizeof (filename));
settime.actime = (unsigned short) ((actime >> 16) & 0xFFFF);
settime.acdate = (unsigned short) (actime & 0xFFFF);
----------------------------------------------------------------------
diff -ur orig/support.h include/support.h
--- orig/support.h Tue Jul 19 19:08:42 1994
+++ include/support.h Sun Sep 10 19:09:44 1995
@@ -27,8 +27,8 @@
#endif
#endif
-__EXTERN int _unx2dos __PROTO((const char *, char *));
-__EXTERN int _dos2unx __PROTO((const char *, char *));
+__EXTERN int _unx2dos __PROTO((const char *, char *, size_t));
+__EXTERN int _dos2unx __PROTO((const char *, char *, size_t));
__EXTERN int _full_dos2unx __PROTO((char *dos, char *unx));
__EXTERN void fnmapfunc __PROTO((fnmapfunc_t u2dos, fnmapfunc_t dos2u));
__EXTERN int unx2dos __PROTO((const char *u, char *d));
--
Andreas Schwab "And now for something
schwab@issan.informatik.uni-dortmund.de completely different"