aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-05-10 14:20:15 -0400
committerNick Mathewson <nickm@torproject.org>2012-05-10 14:20:15 -0400
commit57ed459b0d675d255ae452749bee9efa3c498a5b (patch)
tree2ceba7ab2b3b393720e3f5344dd99ca69ec72d6d
parentd916fc38b6386c59f3e405e2f3b35e1d505fd806 (diff)
downloadtor-57ed459b0d675d255ae452749bee9efa3c498a5b.tar
tor-57ed459b0d675d255ae452749bee9efa3c498a5b.tar.gz
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.
-rw-r--r--src/common/compat.c65
1 files changed, 43 insertions, 22 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index ec365c38a..6c833f163 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -1630,6 +1630,38 @@ get_parent_directory(char *fname)
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.
* Return a newly allocated string, possibly equal to <b>fname</b>. */
char *
@@ -1645,36 +1677,25 @@ make_path_absolute(char *fname)
return absfname;
#else
-/* We use this as a starting path length. Not too large seems sane. */
-#define START_PATH_LENGTH 100
- size_t path_length = START_PATH_LENGTH;
- char *path = tor_malloc(path_length);
- char *absfname = NULL;
+ char *absfname = NULL, *path = NULL;
tor_assert(fname);
if (fname[0] == '/') {
absfname = tor_strdup(fname);
} else {
- int save_errno = errno;
- errno = 0;
- while (getcwd(path, path_length) == NULL) {
- if (errno == ERANGE) {
- path_length*=2;
- path = tor_realloc(path, path_length);
- } else {
- /* If getcwd failed with an error other than ERANGE, the best we can
- * do here is keep using the relative path. (Perhaps / isn't readable
- * by this UID/GID.) */
- absfname = tor_strdup(fname);
- break;
- }
+ path = alloc_getcwd();
+ if (path) {
+ tor_asprintf(&absfname, "%s/%s", path, fname);
+ tor_free(path);
+ } else {
+ /* If getcwd failed, the best we can do here is keep using the
+ * relative path. (Perhaps / isn't readable by this UID/GID.) */
+ log_warn(LD_GENERAL, "Unable to find current working directory: %s",
+ strerror(errno));
+ absfname = tor_strdup(fname);
}
- errno = save_errno;
- tor_asprintf(&absfname, "%s/%s", path, fname);
- tor_free(path);
}
-
return absfname;
#endif
}