From baee8078377109bec778b77b061a56d240c34eb5 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Tue, 12 Apr 2016 19:03:07 -0700 Subject: [PATCH] fish handling of readlink() The readlink() function does not null terminate the path it returns. Remove the OS X code that deals with a path buffer that is too short. For one thing a loop isn't needed since we're told how big of a buffer is required if the first _NSGetExecutablePath() call fails. But more important it is so unlikely that the path will be longer than PATH_MAX that if it is we should just give up. Fixes 2931. (cherry picked from commit 8e103c231e74a3dda40d0a0e5a844ea8b6aa1e4b) --- src/fish.cpp | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/src/fish.cpp b/src/fish.cpp index 17cd1f16a..bde7854ee 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -92,39 +92,34 @@ extern "C" { int _NSGetExecutablePath(char* buf, uint32_t* bufsize); } -/* Return the path to the current executable. This needs to be realpath'd. */ +// Return the path to the current executable. This needs to be realpath'd. static std::string get_executable_path(const char *argv0) { - char buff[PATH_MAX]; + char buff[PATH_MAX + 1]; + #if __APPLE__ - { - /* Returns 0 on success, -1 if the buffer is too small */ - uint32_t buffSize = sizeof buff; - if (0 == _NSGetExecutablePath(buff, &buffSize)) - return std::string(buff); - - /* Loop until we're big enough */ - char *mbuff = (char *)malloc(buffSize); - while (0 > _NSGetExecutablePath(mbuff, &buffSize)) - mbuff = (char *)realloc(mbuff, buffSize); - - /* Return the string */ - std::string result = mbuff; - free(mbuff); - return result; - } -#endif - { - /* On other Unixes, try /proc directory. This might be worth breaking out into macros. */ - if (0 < readlink("/proc/self/exe", buff, sizeof buff) || // Linux - 0 < readlink("/proc/curproc/file", buff, sizeof buff) || // BSD - 0 < readlink("/proc/self/path/a.out", buff, sizeof buff)) // Solaris - { - return std::string(buff); + // On OS X use it's proprietary API to get the path to the executable. + uint32_t buffSize = sizeof buff; + if (_NSGetExecutablePath(buff, &buffSize) == 0) return std::string(buff); +#else + // On non-OS X UNIXes, try /proc directory. + ssize_t len; + len = readlink("/proc/self/exe", buff, sizeof buff); // Linux + if (len == -1) { + len = readlink("/proc/curproc/file", buff, sizeof buff); // BSD + if (len == -1) { + len = readlink("/proc/self/path/a.out", buff, sizeof buff); // Solaris } } + if (len > 0) { + buff[len] = '\0'; + return std::string(buff); + } +#endif - /* Just return argv0, which probably won't work (i.e. it's not an absolute path or a path relative to the working directory, but instead something the caller found via $PATH). We'll eventually fall back to the compile time paths. */ + // Just return argv0, which probably won't work (i.e. it's not an absolute path or a path + // relative to the working directory, but instead something the caller found via $PATH). We'll + // eventually fall back to the compile time paths. return std::string(argv0 ? argv0 : ""); }