darwin: fix uv_exepath(smallbuf) UV_EPERM error
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é <saghul@gmail.com>
This commit is contained in:
parent
afb319215d
commit
885b1ecda0
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user