summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2021-02-27 00:47:49 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2021-03-16 19:20:11 +0000
commitaa15372140b6b509a26742fd85fe78dd77d9a642 (patch)
treeb9e91382bfdd60d331dc3d03d0570212a4339854 /usr/src/lib
parentf38f28fdbc29b3c5020295a6c6cb1ac52e949978 (diff)
downloadillumos-joyent-aa15372140b6b509a26742fd85fe78dd77d9a642.tar.gz
13586 getcwd() should accept a 0 length argument
Reviewed by: Jason King <jason.king@joyent.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Reviewed by: Gordon Ross <gordon.w.ross@gmail.com> Reviewed by: Robert Mustacchi <rm@fingolfin.org> Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libc/port/gen/getcwd.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/usr/src/lib/libc/port/gen/getcwd.c b/usr/src/lib/libc/port/gen/getcwd.c
index d832d798d7..62f12e027e 100644
--- a/usr/src/lib/libc/port/gen/getcwd.c
+++ b/usr/src/lib/libc/port/gen/getcwd.c
@@ -22,10 +22,9 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* getcwd() returns the pathname of the current working directory.
* On error, a NULL pointer is returned and errno is set.
@@ -34,16 +33,63 @@
#pragma weak _getcwd = getcwd
#include "lint.h"
+#include <sys/param.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <errno.h>
+#include <limits.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
char *
getcwd(char *pathname, size_t size)
{
int alloc = 0;
+ if (size == 0 && pathname == NULL) {
+ /*
+ * If no size was provided, start with a buffer that should
+ * accommodate any normal path and, if it is not big enough,
+ * keep doubling it to try and make enough space.
+ *
+ * Any non-global zone path is longer when observed from the
+ * global zone, and some filesystems, including ZFS, support
+ * paths much longer than MAXPATHLEN/_PC_PATH_MAX.
+ *
+ * To protect against unbounded memory usage, cap to 128KiB.
+ * This is an arbitrary limit which is far bigger than the
+ * length of any practical path on the system.
+ */
+ if ((size = pathconf(".", _PC_PATH_MAX)) == -1)
+ size = MAXPATHLEN;
+
+ while (size <= 0x20000) {
+ if ((pathname = reallocf(pathname, size)) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ if (syscall(SYS_getcwd, pathname, size) == 0) {
+ char *ret;
+
+ /*
+ * Shrink the buffer to the length actually
+ * required to hold the final path.
+ */
+ ret = realloc(pathname, strlen(pathname) + 1);
+ if (ret == NULL)
+ return (pathname);
+
+ return (ret);
+ }
+ if (errno != ERANGE)
+ break;
+ size <<= 1;
+ }
+ free(pathname);
+ return (NULL);
+ }
+
if (size == 0) {
errno = EINVAL;
return (NULL);