From 2e314136ed58b6860c667e379bef22190fe84aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 22 Nov 2025 14:50:10 +0100 Subject: New upstream version 5.2 --- src/io.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'src/io.c') diff --git a/src/io.c b/src/io.c index b9041e0..ee47f5a 100644 --- a/src/io.c +++ b/src/io.c @@ -65,8 +65,14 @@ static int mkdir_gen(const char *d, unsigned int mode) if (mkdir(d, mode) == 0) /* use umask() for permissions */ #endif return 1; +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) + /* Undocumented extra error codes */ + if (errno != EEXIST && errno != EISDIR) + return -errno; +#else if (errno != EEXIST) return -errno; +#endif if (stat(d, &sb) == 0) { #if defined(_WIN32) if (sb.st_mode & S_IFDIR) @@ -98,7 +104,7 @@ EXPORT_SYMBOL struct HXdir *HXdir_open(const char *s) * and bug-concealing "char d_name[256]", while on Solaris, it is a * proper "char d_name[]". */ - size_t size = sizeof(*d); + size_t size = offsetof(struct dirent, d_name); ssize_t name_max; DIR *tmp_dh = opendir(s); if (tmp_dh == NULL) @@ -110,7 +116,6 @@ EXPORT_SYMBOL struct HXdir *HXdir_open(const char *s) */ name_max = fpathconf(dirfd(tmp_dh), _PC_NAME_MAX); if (name_max > 0) { - size -= sizeof(struct dirent) - offsetof(struct dirent, d_name); size += name_max + 1; } else { #ifdef NAME_MAX @@ -378,6 +383,8 @@ EXPORT_SYMBOL int HX_readlink(hxmc_t **target, const char *path) HXmc_setlen(target, ret); // \0 set here anyway return ret; } + if (linkbuf_size > SIZE_MAX / 2) + return -E2BIG; linkbuf_size *= 2; if (HXmc_setlen(target, linkbuf_size) == NULL) { int saved_errno = errno; @@ -483,7 +490,10 @@ EXPORT_SYMBOL int HX_getcwd(hxmc_t **target) return 1; } if (errno == ERANGE) { - if (HXmc_setlen(target, linkbuf_size *= 2) != nullptr) + if (linkbuf_size > SIZE_MAX / 2) + return -E2BIG; + linkbuf_size *= 2; + if (HXmc_setlen(target, linkbuf_size) != nullptr) continue; /* errno already set by realloc, fall into next if block */ } @@ -777,16 +787,18 @@ EXPORT_SYMBOL char *HX_slurp_fd(int fd, size_t *outsize) char *buf = malloc(bufsize); if (buf == nullptr) return nullptr; - ssize_t rdret; - while ((rdret = read(fd, buf + offset, bufsize - 1 - offset)) > 0) { + do { + assert(offset < bufsize); + ssize_t rdret = read(fd, buf + offset, bufsize - 1 - offset); + if (rdret <= 0) + break; offset += rdret; - /* - * Make it so that the next read call is not called - * with an exceptionally small size. - */ if (bufsize - offset >= 4095) + /* 4K room still, just continue reading. */ continue; - if (bufsize > SSIZE_MAX) + + /* Less than 4K room, enlarge now */ + if (bufsize > SIZE_MAX / 2) /* No more doubling */ break; bufsize *= 2; @@ -798,7 +810,7 @@ EXPORT_SYMBOL char *HX_slurp_fd(int fd, size_t *outsize) return nullptr; } buf = nbuf; - } + } while (true); buf[offset] = '\0'; if (outsize != nullptr) *outsize = offset; -- cgit v1.2.3