Prevent possible buffer overflow exploits under Windows. As per (the very quick) patch Patch #101801.

This commit is contained in:
Mark Hammond 2000-10-07 11:10:50 +00:00
parent 025468d246
commit 8bf9e3b943
1 changed files with 30 additions and 9 deletions

View File

@ -98,7 +98,9 @@ is_sep(char ch) /* determine if "ch" is a separator character */
#endif #endif
} }
/* assumes 'dir' null terminated in bounds. Never writes
beyond existing terminator.
*/
static void static void
reduce(char *dir) reduce(char *dir)
{ {
@ -116,7 +118,9 @@ exists(char *filename)
return stat(filename, &buf) == 0; return stat(filename, &buf) == 0;
} }
/* Assumes 'filename' MAXPATHLEN+1 bytes long -
may extend 'filename' by one character.
*/
static int static int
ismodule(char *filename) /* Is module -- check for .pyc/.pyo too */ ismodule(char *filename) /* Is module -- check for .pyc/.pyo too */
{ {
@ -132,7 +136,7 @@ ismodule(char *filename) /* Is module -- check for .pyc/.pyo too */
return 0; return 0;
} }
/* guarantees buffer will never overflow MAXPATHLEN+1 bytes */
static void static void
join(char *buffer, char *stuff) join(char *buffer, char *stuff)
{ {
@ -151,7 +155,10 @@ join(char *buffer, char *stuff)
buffer[n+k] = '\0'; buffer[n+k] = '\0';
} }
/* gotlandmark only called by search_for_prefix, which ensures
'prefix' is null terminated in bounds. join() ensures
'landmark' can not overflow prefix if too long.
*/
static int static int
gotlandmark(char *landmark) gotlandmark(char *landmark)
{ {
@ -164,7 +171,8 @@ gotlandmark(char *landmark)
return ok; return ok;
} }
/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
assumption provided by only caller, calculate_path() */
static int static int
search_for_prefix(char *argv0_path, char *landmark) search_for_prefix(char *argv0_path, char *landmark)
{ {
@ -340,11 +348,20 @@ get_progpath(void)
#ifdef MS_WIN32 #ifdef MS_WIN32
#ifdef UNICODE #ifdef UNICODE
WCHAR wprogpath[MAXPATHLEN+1]; WCHAR wprogpath[MAXPATHLEN+1];
/* Windows documents that GetModuleFileName() will "truncate",
but makes no mention of the null terminator. Play it safe.
PLUS Windows itself defines MAX_PATH as the same, but anyway...
*/
wprogpath[MAXPATHLEN]=_T('\0')';
if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) { if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {
WideCharToMultiByte(CP_ACP, 0, wprogpath, -1, progpath, MAXPATHLEN+1, NULL, NULL); WideCharToMultiByte(CP_ACP, 0,
wprogpath, -1,
progpath, MAXPATHLEN+1,
NULL, NULL);
return; return;
} }
#else #else
/* static init of progpath ensures final char remains \0 */
if (GetModuleFileName(NULL, progpath, MAXPATHLEN)) if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
return; return;
#endif #endif
@ -362,19 +379,22 @@ get_progpath(void)
#else #else
if (strchr(prog, SEP)) if (strchr(prog, SEP))
#endif #endif
strcpy(progpath, prog); strncpy(progpath, prog, MAXPATHLEN);
else if (path) { else if (path) {
while (1) { while (1) {
char *delim = strchr(path, DELIM); char *delim = strchr(path, DELIM);
if (delim) { if (delim) {
size_t len = delim - path; size_t len = delim - path;
/* ensure we can't overwrite buffer */
len = min(MAXPATHLEN,len);
strncpy(progpath, path, len); strncpy(progpath, path, len);
*(progpath + len) = '\0'; *(progpath + len) = '\0';
} }
else else
strcpy(progpath, path); strncpy(progpath, path, MAXPATHLEN);
/* join() is safe for MAXPATHLEN+1 size buffer */
join(progpath, prog); join(progpath, prog);
if (exists(progpath)) if (exists(progpath))
break; break;
@ -406,6 +426,7 @@ calculate_path(void)
#endif #endif
get_progpath(); get_progpath();
/* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
strcpy(argv0_path, progpath); strcpy(argv0_path, progpath);
reduce(argv0_path); reduce(argv0_path);
if (pythonhome == NULL || *pythonhome == '\0') { if (pythonhome == NULL || *pythonhome == '\0') {
@ -415,7 +436,7 @@ calculate_path(void)
pythonhome = NULL; pythonhome = NULL;
} }
else else
strcpy(prefix, pythonhome); strncpy(prefix, pythonhome, MAXPATHLEN);
if (envpath && *envpath == '\0') if (envpath && *envpath == '\0')
envpath = NULL; envpath = NULL;