From 11e7874fff3e3e3aa56e8a80db17310f39f64e55 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Mon, 30 Apr 2018 11:59:30 +0930 Subject: [PATCH] Improve get_self_executable_path() on Mac OS --- os.c | 18 +++++++++++++----- os.h | 4 ++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/os.c b/os.c index 5a0e2516..0a6b9e9f 100644 --- a/os.c +++ b/os.c @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #ifdef __APPLE__ #include +#include // PRIu32 #endif void log_info_mkdir(struct __sourceloc __whence, const char *path, mode_t mode, void *UNUSED(context)) @@ -360,14 +361,21 @@ ssize_t get_self_executable_path(char *buf, size_t len) #elif defined (__sun__) return read_symlink("/proc/self/path/a.out", buf, len); #elif defined (__APPLE__) + // Ensure that len is not too large. + assert(((int32_t)len)>=0); uint32_t bufsize = len; - // OSX complains if the ? : operator returns fields with different signedness - // so we cast the uint32_t bufsize to signed. We should really check to make - // sure that _NSGetExecutablePath doesn't return a value in bufsize that would - // be negative when cast. ssize_t s = _NSGetExecutablePath(buf, &bufsize); + // Ensure that _NSGetExecutablePath doesn't return a gigantic value in bufsize that would be + // negative when cast. assert(((int32_t)bufsize)>=0); - return ( s || len == 0 ) ? (int32_t)bufsize : -1; + if (len == 0) { + if (s != -1) + return WHYF("_NSGetExecutablePath(%p, &%zd) returned %zd, expecting -1", buf, len, s); + return bufsize; + } + if (s == -1) + return WHYF("_NSGetExecutablePath(%p, &%zd) returned %zd, bufsize=%"PRIu32, buf, len, s, bufsize); + return strlen(buf) + 1; // include terminating nul #else #error Unable to find executable path #endif diff --git a/os.h b/os.h index a5a9dd52..5ed43297 100644 --- a/os.h +++ b/os.h @@ -239,6 +239,10 @@ int file_exists_is_directory(const char *path); * number of bytes placed in the buffer, including the terminating nul (ie, * returns strlen(buf) + 1). * + * If the 'len' parameter is zero, then does not alter the contents of 'buf' + * but just returns the size of the buffer that would be needed to hold the + * path, including the terminating nul. + * * @author Andrew Bettison */ ssize_t get_self_executable_path(char *buf, size_t len);