truename: fix array overrun (pick from fdpp)

Picked from the commit at fe1c4dc7fe

The referenced issue is at https://github.com/dosemu2/fdpp/issues/212

The patch was applied using unix2dos on the patch file
then `patch -p1 --binary` with the patch file as stdin.
The original used a new define for the maximum path length.
As there is no difference to our current SFTMAX define I
changed this hunk to retain the SFTMAX use.

This fixes a bug when eg function 3Dh receives a buffer
that starts with ".\" but the byte in memory before this
buffer happens to be also a dot. I ran into this problem
semi-randomly during building EDR-DOS with the most recent
WarpLink build. If WarpLink was placed somewhat low in the
Low Memory Area then one of its function 3Dh calls would
happen to have a dot before the pathname buffer. (I had to
load lCDebug using the last fit strategy then enter TSR mode,
to catch the bug without the presence of the debugger working
around the occurrence of the bug.)

Original commit Metadata:

From: Stas Sergeev <stsp@users.sourceforge.net>
Date: Wed, 1 Feb 2023 13:01:55 +0500
Subject: [PATCH] truename: fix array overrun [fixes #212]

src[-2] was peeking into a random memory location.
It seems entire truename() is written by some morons... :(
Its completely unreadable and full of bugs.
This commit is contained in:
C. Masloch 2023-08-26 22:22:30 +02:00 committed by Kenneth J Davis
parent 29ccb6e454
commit 132a0a9f94
1 changed files with 13 additions and 9 deletions

View File

@ -185,7 +185,10 @@ long DosMkTmp(BYTE FAR * pathname, UWORD attr)
*/
#define PATH_ERROR goto errRet
#define PATH_ERROR() \
fstrchr(src, '/') == 0 && fstrchr(src, '\\') == 0 \
? DE_FILENOTFND \
: DE_PATHNOTFND
#define PATHLEN 128
@ -249,7 +252,7 @@ STATIC const char _DirChars[] = "\"[]:|<>+=;,";
#define addChar(c) \
{ \
if (p >= dest + SFTMAX) PATH_ERROR; /* path too long */ \
if (p >= dest + SFTMAX) return PATH_ERROR(); /* path too long */ \
*p++ = c; \
}
@ -526,14 +529,18 @@ invalid_path:
if(*src == '.')
{
int dots = 1;
/* special directory component */
++src;
if (*src == '.') /* skip the second dot */
{
++src;
dots++;
}
if (*src == '/' || *src == '\\' || *src == '\0')
{
--p; /* backup the backslash */
if (src[-2] == '.')
if (dots == 2)
{
/* ".." entry */
/* remove last path component */
@ -545,12 +552,9 @@ invalid_path:
}
/* ill-formed .* or ..* entries => return error */
errRet:
/* The error is either PATHNOTFND or FILENOTFND
depending on if it is not the last component */
return fstrchr(src, '/') == 0 && fstrchr(src, '\\') == 0
? DE_FILENOTFND
: DE_PATHNOTFND;
return PATH_ERROR();
}
/* normal component */
@ -583,7 +587,7 @@ invalid_path:
if (c == '.')
{
if (state & PNE_DOT) /* multiple dots are ill-formed */
PATH_ERROR;
return PATH_ERROR();
/* strip trailing dot */
if (*src == '/' || *src == '\\' || *src == '\0')
break;
@ -595,7 +599,7 @@ invalid_path:
state |= PNE_WILDCARD;
if (i) { /* name length in limits */
--i;
if (!DirChar(c)) PATH_ERROR;
if (!DirChar(c)) return PATH_ERROR();
addChar(c);
}
}