From 885b1ecda0037fcb6647e8d69a914347ad884244 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 3 Jan 2015 00:01:46 +0100 Subject: [PATCH] darwin: fix uv_exepath(smallbuf) UV_EPERM error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing a buffer that was too small to hold the result made it fail with UV_EPERM because the -1 status code from _NSGetExecutablePath() was returned unmodified to the caller. This commit rewrites uv_exepath() to: 1. Not allocate heap memory, and 2. Not clobber the result buffer on error, and 3. Handle _NSGetExecutablePath()'s and realpath()'s idiosyncracies, and 4. Store as much of the path in the output buffer as possible, don't fail with an error. Makes it behave the same as other platforms. The result is always zero-terminated. Fixes: https://github.com/libuv/libuv/issues/103 PR-URL: https://github.com/libuv/libuv/pull/104 Reviewed-By: Saúl Ibarra Corretgé --- src/unix/darwin.c | 35 ++++++++++++++++++++--------------- test/test-get-currentexe.c | 8 ++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/unix/darwin.c b/src/unix/darwin.c index 69117d61..651545f8 100644 --- a/src/unix/darwin.c +++ b/src/unix/darwin.c @@ -65,28 +65,33 @@ uint64_t uv__hrtime(uv_clocktype_t type) { int uv_exepath(char* buffer, size_t* size) { - uint32_t usize; - int result; - char* path; - char* fullpath; + /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ + char abspath[PATH_MAX * 2 + 1]; + char exepath[PATH_MAX + 1]; + uint32_t exepath_size; + size_t abspath_size; if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; - usize = *size; - result = _NSGetExecutablePath(buffer, &usize); - if (result) return result; + exepath_size = sizeof(exepath); + if (_NSGetExecutablePath(exepath, &exepath_size)) + return -EIO; - path = malloc(2 * PATH_MAX); - fullpath = realpath(buffer, path); - if (fullpath == NULL) { - SAVE_ERRNO(free(path)); + if (realpath(exepath, abspath) != abspath) return -errno; - } - strncpy(buffer, fullpath, *size); - free(fullpath); - *size = strlen(buffer); + abspath_size = strlen(abspath); + if (abspath_size == 0) + return -EIO; + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + return 0; } diff --git a/test/test-get-currentexe.c b/test/test-get-currentexe.c index b2399172..c6091ff7 100644 --- a/test/test-get-currentexe.c +++ b/test/test-get-currentexe.c @@ -65,5 +65,13 @@ TEST_IMPL(get_currentexe) { r = uv_exepath(buffer, &size); ASSERT(r == UV_EINVAL); + memset(buffer, -1, sizeof(buffer)); + + size = 1; + r = uv_exepath(buffer, &size); + ASSERT(r == 0); + ASSERT(size == 0); + ASSERT(buffer[0] == '\0'); + return 0; }