summaryrefslogtreecommitdiff
path: root/src/io.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2025-11-22 14:50:10 +0100
committerJörg Frings-Fürst <debian@jff-webhosting.net>2025-11-22 14:50:10 +0100
commit2e314136ed58b6860c667e379bef22190fe84aa2 (patch)
tree21f897804c03c3419a0c015ace3bf9fb9c1b8e52 /src/io.c
parent50d223b12c1319b4b9c4a5b8e34866c46996cb36 (diff)
New upstream version 5.2upstream/5.2upstream
Diffstat (limited to 'src/io.c')
-rw-r--r--src/io.c34
1 files changed, 23 insertions, 11 deletions
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;