cpio: Check number arguments before casts

Make sure that supplied arguments actually fit into target data types.
Print an error if numbers are too large instead of silently truncating
them.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This commit is contained in:
Tobias Stoeckmann committed 2026-03-16 14:19:30 +01:00
1 parent f59ed04545
commit 71d8195f2e
2 files changed
+19 -8

No files matched your search

+11 -4
View File
@@ -11,6 +11,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
@@ -347,9 +350,10 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
owner->gid = pwent->pw_gid;
} else {
char *end;
unsigned long val;
errno = 0;
owner->uid = (int)strtoul(user, &end, 10);
if (errno || *end != '\0') {
val = strtoul(user, &end, 10);
if (errno || *end != '\0' || val > (unsigned)INT_MAX) {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user);
errbuff[sizeof(errbuff) - 1] = '\0';
@@ -357,6 +361,7 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
*errmsg = errbuff;
return (-1);
}
owner->uid = (int)val;
}
free(user);
}
@@ -373,15 +378,17 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
}
} else {
char *end;
unsigned long val;
errno = 0;
owner->gid = (int)strtoul(g, &end, 10);
if (errno || *end != '\0') {
val = strtoul(g, &end, 10);
if (errno || *end != '\0' || val > (unsigned)INT_MAX) {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g);
errbuff[sizeof(errbuff) - 1] = '\0';
*errmsg = errbuff;
return (-1);
}
owner->gid = (int)val;
}
}
return (0);
+8 -4
View File
@@ -33,6 +33,9 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -116,7 +119,8 @@ main(int argc, char *argv[])
struct cpio_owner owner;
const char *errmsg;
char *tptr;
int opt, t;
int opt;
long t;
cpio = &_cpio;
memset(cpio, 0, sizeof(*cpio));
@@ -204,13 +208,13 @@ main(int argc, char *argv[])
case 'C': /* NetBSD/OpenBSD */
errno = 0;
tptr = NULL;
t = (int)strtol(cpio->argument, &tptr, 10);
if (errno || t <= 0 || *(cpio->argument) == '\0' ||
t = strtol(cpio->argument, &tptr, 10);
if (errno || t <= 0 || t > INT_MAX || *(cpio->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid blocksize: %s",
cpio->argument);
}
cpio->bytes_per_block = t;
cpio->bytes_per_block = (int)t;
break;
case 'c': /* POSIX 1997 */
cpio->format = "odc";