From: Tulio A M Mendes Date: Sun, 19 Apr 2026 17:55:59 +0000 (-0300) Subject: Fix getcwd(NULL, 0): allocate buffer when buf is NULL (glibc extension) X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=13b43e0ea66930cee10969fd9c70bdf0de500e30;p=AdrOS.git Fix getcwd(NULL, 0): allocate buffer when buf is NULL (glibc extension) Bash calls getcwd(NULL, 0) — a glibc extension where NULL means "allocate a buffer for me". Both ulibc and newlib wrappers passed NULL straight to the kernel syscall, which returned -EFAULT because the kernel rejects user_buf == NULL. This caused: shell-init: error retrieving current directory: getcwd: cannot access parent directories: Bad address Now both wrappers handle NULL buf by malloc'ing a buffer (4096 bytes if size is 0), passing it to the kernel, and returning the allocated pointer on success (or freeing it on error). This matches glibc behavior and unblocks bash and other ported software. --- diff --git a/newlib/libgloss/adros/posix_stubs.c b/newlib/libgloss/adros/posix_stubs.c index 75459089..c796b0b6 100644 --- a/newlib/libgloss/adros/posix_stubs.c +++ b/newlib/libgloss/adros/posix_stubs.c @@ -176,8 +176,19 @@ int chdir(const char *path) { } char *getcwd(char *buf, size_t size) { + int allocated = 0; + if (!buf) { + if (size == 0) size = 4096; + buf = (char *)malloc(size); + if (!buf) { errno = ENOMEM; return 0; } + allocated = 1; + } int r = _sc2(SYS_GETCWD, (int)buf, (int)size); - if (r < 0) { errno = -r; return 0; } + if (r < 0) { + errno = -r; + if (allocated) free(buf); + return 0; + } return buf; } diff --git a/user/ulibc/src/unistd.c b/user/ulibc/src/unistd.c index 34c6ac94..6dcadb35 100644 --- a/user/ulibc/src/unistd.c +++ b/user/ulibc/src/unistd.c @@ -11,6 +11,7 @@ #include "syscall.h" #include "errno.h" #include "termios.h" +#include "stdlib.h" int read(int fd, void* buf, size_t count) { return __syscall_ret(_syscall3(SYS_READ, fd, (int)buf, (int)count)); @@ -70,8 +71,19 @@ int chdir(const char* path) { } char* getcwd(char* buf, size_t size) { + int allocated = 0; + if (!buf) { + if (size == 0) size = 4096; + buf = (char*)malloc(size); + if (!buf) { errno = ENOMEM; return NULL; } + allocated = 1; + } int r = _syscall2(SYS_GETCWD, (int)buf, (int)size); - if (r < 0) { errno = -r; return NULL; } + if (r < 0) { + errno = -r; + if (allocated) free(buf); + return NULL; + } return buf; }