Changeset View
Changeset View
Standalone View
Standalone View
lib/libutil/getlocalbase.c
Show All 35 Lines | |||||
#include <paths.h> | #include <paths.h> | ||||
#include <libutil.h> | #include <libutil.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
ssize_t | ssize_t | ||||
getlocalbase(char *path, size_t pathlen) | getlocalbase(char *path, size_t pathlen) | ||||
{ | { | ||||
ssize_t tmplen; | size_t tmplen, miblen; | ||||
const char *tmppath; | const char *tmppath; | ||||
int mib[4]; | |||||
if ((pathlen == 0) || (path == NULL)) { | /* It's unlikely that the buffer would be this big */ | ||||
if ((pathlen == 0) || (pathlen > SSIZE_MAX) || (path == NULL)) { | |||||
errno = EINVAL; | errno = EINVAL; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* It's unlikely that the buffer would be this big */ | |||||
if (pathlen > SSIZE_MAX) { | |||||
errno = ENOMEM; | |||||
return (-1); | |||||
} | |||||
tmppath = NULL; | tmppath = NULL; | ||||
jrtc27: This should probably be EINVAL (and could then be folded into the previous if). | |||||
tmplen = (size_t)pathlen; | tmplen = pathlen; | ||||
if (issetugid() == 0) | if (issetugid() == 0) | ||||
tmppath = getenv("LOCALBASE"); | tmppath = getenv("LOCALBASE"); | ||||
if ((tmppath == NULL) && | if (tmppath == NULL) { | ||||
(sysctlbyname("user.localbase", path, (size_t *)&tmplen, NULL, | sysctlnametomib("user.localbase", mib, &miblen); | ||||
jrtc27Unsubmitted Not Done Inline Actionsmiblen is currently uninitialised before the call; presumably it works because it's reading random garbage on the stack that's most likely >= 2. You should probably also be checking the return value here. jrtc27: miblen is currently uninitialised before the call; presumably it works because it's reading… | |||||
0) == 0)) { | if (sysctl(mib, 4, path, &tmplen, NULL, 0) == 0) | ||||
return (tmplen); | return (tmplen); | ||||
} | } | ||||
if (tmppath == NULL) | if (tmppath == NULL) | ||||
#ifdef _PATH_LOCALBASE | #ifdef _PATH_LOCALBASE | ||||
tmppath = _PATH_LOCALBASE; | tmppath = _PATH_LOCALBASE; | ||||
#else | #else | ||||
tmppath = "/usr/local"; | tmppath = "/usr/local"; | ||||
#endif | #endif | ||||
/* | |||||
* If strlcpy() overflowed the size of the provided buffer then just | |||||
* return an error. | |||||
*/ | |||||
tmplen = strlcpy(path, tmppath, pathlen); | tmplen = strlcpy(path, tmppath, pathlen); | ||||
if ((tmplen < 0) || (tmplen >= (ssize_t)pathlen)) { | if (tmplen >= pathlen) { | ||||
Not Done Inline Actionsstrlcpy doesn't include the NUL so this to stay >=. jrtc27: strlcpy doesn't include the NUL so this to stay >=. | |||||
errno = ENOMEM; | errno = ENOMEM; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* It's unlikely that the buffer would be this big */ | /* | ||||
if (tmplen > SSIZE_MAX) { | * tmplen can't be larger than pathlen, and pathlen was already | ||||
errno = ENOMEM; | * checked to make sure it wouldn't overflow the ssize_t. Thus this | ||||
return (-1); | * cast is safe. | ||||
} | */ | ||||
return ((ssize_t)tmplen); | return ((ssize_t)tmplen); | ||||
} | } |
This should probably be EINVAL (and could then be folded into the previous if).