Refactor new getcwd code

Make sure that the "path_length *= 2" statement can't overflow.

Move the "malloc and getcwd" loop into its own function.
This commit is contained in:
Nick Mathewson 2012-05-10 14:20:15 -04:00
parent d916fc38b6
commit 57ed459b0d

View File

@ -1630,6 +1630,38 @@ get_parent_directory(char *fname)
return -1; return -1;
} }
#ifndef _WIN32
/** Return a newly allocated string containing the output of getcwd(). Return
* NULL on failure. (We can't just use getcwd() into a PATH_MAX buffer, since
* Hurd hasn't got a PATH_MAX.)
*/
static char *
alloc_getcwd(void)
{
int saved_errno = errno;
/* We use this as a starting path length. Not too large seems sane. */
#define START_PATH_LENGTH 128
/* Nobody has a maxpath longer than this, as far as I know. And if they
* do, they shouldn't. */
#define MAX_SANE_PATH_LENGTH 4096
size_t path_length = START_PATH_LENGTH;
char *path = tor_malloc(path_length);
errno = 0;
while (getcwd(path, path_length) == NULL) {
if (errno == ERANGE && path_length < MAX_SANE_PATH_LENGTH) {
path_length*=2;
path = tor_realloc(path, path_length);
} else {
tor_free(path);
return NULL;
}
}
errno = saved_errno;
return path;
}
#endif
/** Expand possibly relative path <b>fname</b> to an absolute path. /** Expand possibly relative path <b>fname</b> to an absolute path.
* Return a newly allocated string, possibly equal to <b>fname</b>. */ * Return a newly allocated string, possibly equal to <b>fname</b>. */
char * char *
@ -1645,36 +1677,25 @@ make_path_absolute(char *fname)
return absfname; return absfname;
#else #else
/* We use this as a starting path length. Not too large seems sane. */ char *absfname = NULL, *path = NULL;
#define START_PATH_LENGTH 100
size_t path_length = START_PATH_LENGTH;
char *path = tor_malloc(path_length);
char *absfname = NULL;
tor_assert(fname); tor_assert(fname);
if (fname[0] == '/') { if (fname[0] == '/') {
absfname = tor_strdup(fname); absfname = tor_strdup(fname);
} else { } else {
int save_errno = errno; path = alloc_getcwd();
errno = 0; if (path) {
while (getcwd(path, path_length) == NULL) { tor_asprintf(&absfname, "%s/%s", path, fname);
if (errno == ERANGE) { tor_free(path);
path_length*=2; } else {
path = tor_realloc(path, path_length); /* If getcwd failed, the best we can do here is keep using the
} else { * relative path. (Perhaps / isn't readable by this UID/GID.) */
/* If getcwd failed with an error other than ERANGE, the best we can log_warn(LD_GENERAL, "Unable to find current working directory: %s",
* do here is keep using the relative path. (Perhaps / isn't readable strerror(errno));
* by this UID/GID.) */ absfname = tor_strdup(fname);
absfname = tor_strdup(fname);
break;
}
} }
errno = save_errno;
tor_asprintf(&absfname, "%s/%s", path, fname);
tor_free(path);
} }
return absfname; return absfname;
#endif #endif
} }