Page MenuHomeFreeBSD

D44166.id135457.diff
No OneTemporary

D44166.id135457.diff

diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c
--- a/sys/fs/tarfs/tarfs_vfsops.c
+++ b/sys/fs/tarfs/tarfs_vfsops.c
@@ -113,58 +113,46 @@
};
/*
- * Reads a len-width signed octal number from strp. Returns the value.
- * XXX Does not report errors.
+ * Reads a len-width signed octal number from strp. Returns 0 on success
+ * and non-zero on error.
*/
-static int64_t
-tarfs_str2octal(const char *strp, size_t len)
+static int
+tarfs_str2octal(const char *strp, size_t len, int64_t *num)
{
int64_t val;
size_t idx;
int sign;
- /*
- * Skip leading spaces or tabs.
- * XXX why? POSIX requires numeric fields to be 0-padded.
- */
- for (idx = 0; idx < len; idx++)
- if (strp[idx] != ' ' && strp[idx] != '\t')
- break;
-
- if (idx == len)
- return (0);
-
+ idx = 0;
if (strp[idx] == '-') {
sign = -1;
idx++;
- } else
+ } else {
sign = 1;
+ }
val = 0;
- for (; idx < len; idx++) {
+ for (; idx < len && strp[idx] != '\0' && strp[idx] != ' '; idx++) {
if (strp[idx] < '0' || strp[idx] > '7')
- break;
+ return (EINVAL);
val <<= 3;
- val += (strp[idx] - '0');
-
- /* Truncate on overflow */
- if (val > INT64_MAX / 8) {
- val = INT64_MAX;
- break;
- }
+ val += strp[idx] - '0';
+ if (val > INT64_MAX / 8)
+ return (ERANGE);
}
- return (sign > 0) ? val : -val;
+ *num = val * sign;
+ return (0);
}
/*
* Reads a len-byte extended numeric value from strp. The first byte has
* bit 7 set to indicate the format; the remaining 7 bits + the (len - 1)
* bytes that follow form a big-endian signed two's complement binary
- * number. Returns the value. XXX Does not report errors.
+ * number. Returns 0 on success and non-zero on error;
*/
-static int64_t
-tarfs_str2base256(const char *strp, size_t len)
+static int
+tarfs_str2base256(const char *strp, size_t len, int64_t *num)
{
int64_t val;
size_t idx;
@@ -183,37 +171,27 @@
for (idx = 1; idx < len; idx++) {
val <<= 8;
val |= (0xff & (int64_t)strp[idx]);
-
- /* Truncate on overflow and underflow */
- if (val > INT64_MAX / 256) {
- val = INT64_MAX;
- break;
- } else if (val < INT64_MAX / 256) {
- val = INT64_MIN;
- break;
- }
+ if (val > INT64_MAX / 256 || val < INT64_MIN / 256)
+ return (ERANGE);
}
- return (val);
+ *num = val;
+ return (0);
}
/*
* Read a len-byte numeric field from strp. If bit 7 of the first byte it
* set, assume an extended numeric value (signed two's complement);
* otherwise, assume a signed octal value.
- *
- * XXX practically no error checking or handling
*/
-static int64_t
-tarfs_str2int64(const char *strp, size_t len)
+static int
+tarfs_str2int64(const char *strp, size_t len, int64_t *num)
{
-
if (len < 1)
- return (0);
-
+ return (EINVAL);
if ((strp[0] & 0x80) != 0)
- return (tarfs_str2base256(strp, len));
- return (tarfs_str2octal(strp, len));
+ return (tarfs_str2base256(strp, len, num));
+ return (tarfs_str2octal(strp, len, num));
}
/*
@@ -521,42 +499,47 @@
}
/* get standard attributes */
- num = tarfs_str2int64(hdrp->mode, sizeof(hdrp->mode));
- if (num < 0 || num > (S_IFMT|ALLPERMS)) {
+ if (tarfs_str2int64(hdrp->mode, sizeof(hdrp->mode), &num) != 0 ||
+ num < 0 || num > (S_IFMT|ALLPERMS)) {
TARFS_DPF(ALLOC, "%s: invalid file mode at %zu\n",
__func__, TARFS_BLOCKSIZE * (blknum - 1));
mode = S_IRUSR;
} else {
mode = num & ALLPERMS;
}
- num = tarfs_str2int64(hdrp->uid, sizeof(hdrp->uid));
- if (num < 0 || num > UID_MAX) {
- TARFS_DPF(ALLOC, "%s: UID out of range at %zu\n",
+ if (tarfs_str2int64(hdrp->uid, sizeof(hdrp->uid), &num) != 0 ||
+ num < 0 || num > UID_MAX) {
+ TARFS_DPF(ALLOC, "%s: invalid UID at %zu\n",
__func__, TARFS_BLOCKSIZE * (blknum - 1));
uid = tmp->root->uid;
mode &= ~S_ISUID;
} else {
uid = num;
}
- num = tarfs_str2int64(hdrp->gid, sizeof(hdrp->gid));
- if (num < 0 || num > GID_MAX) {
- TARFS_DPF(ALLOC, "%s: GID out of range at %zu\n",
+ if (tarfs_str2int64(hdrp->gid, sizeof(hdrp->gid), &num) != 0 ||
+ num < 0 || num > GID_MAX) {
+ TARFS_DPF(ALLOC, "%s: invalid GID at %zu\n",
__func__, TARFS_BLOCKSIZE * (blknum - 1));
gid = tmp->root->gid;
mode &= ~S_ISGID;
} else {
gid = num;
}
- num = tarfs_str2int64(hdrp->size, sizeof(hdrp->size));
- if (num < 0) {
- TARFS_DPF(ALLOC, "%s: negative size at %zu\n",
+ if (tarfs_str2int64(hdrp->size, sizeof(hdrp->size), &num) != 0 ||
+ num < 0) {
+ TARFS_DPF(ALLOC, "%s: invalid size at %zu\n",
+ __func__, TARFS_BLOCKSIZE * (blknum - 1));
+ error = EINVAL;
+ goto bad;
+ }
+ sz = num;
+ if (tarfs_str2int64(hdrp->mtime, sizeof(hdrp->mtime), &num) != 0) {
+ TARFS_DPF(ALLOC, "%s: invalid modification time at %zu\n",
__func__, TARFS_BLOCKSIZE * (blknum - 1));
error = EINVAL;
goto bad;
- } else {
- sz = num;
}
- mtime = tarfs_str2int64(hdrp->mtime, sizeof(hdrp->mtime));
+ mtime = num;
rdev = NODEV;
TARFS_DPF(ALLOC, "%s: [%c] %zu @%jd %o %d:%d\n", __func__,
hdrp->typeflag[0], sz, (intmax_t)mtime, mode, uid, gid);
@@ -772,16 +755,44 @@
parent, &tnp);
break;
case TAR_TYPE_BLOCK:
- major = tarfs_str2int64(hdrp->major, sizeof(hdrp->major));
- minor = tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor));
+ if (tarfs_str2int64(hdrp->major, sizeof(hdrp->major), &num) != 0 ||
+ num < 0 || num > INT_MAX) {
+ TARFS_DPF(ALLOC, "%s: %.*s: invalid device major\n",
+ __func__, (int)namelen, name);
+ error = EINVAL;
+ goto bad;
+ }
+ major = num;
+ if (tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor), &num) != 0 ||
+ num < 0 || num > INT_MAX) {
+ TARFS_DPF(ALLOC, "%s: %.*s: invalid device minor\n",
+ __func__, (int)namelen, name);
+ error = EINVAL;
+ goto bad;
+ }
+ minor = num;
rdev = makedev(major, minor);
error = tarfs_alloc_node(tmp, namep, sep - namep, VBLK,
0, 0, mtime, uid, gid, mode, flags, NULL, rdev,
parent, &tnp);
break;
case TAR_TYPE_CHAR:
- major = tarfs_str2int64(hdrp->major, sizeof(hdrp->major));
- minor = tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor));
+ if (tarfs_str2int64(hdrp->major, sizeof(hdrp->major), &num) != 0 ||
+ num < 0 || num > INT_MAX) {
+ TARFS_DPF(ALLOC, "%s: %.*s: invalid device major\n",
+ __func__, (int)namelen, name);
+ error = EINVAL;
+ goto bad;
+ }
+ major = num;
+ if (tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor), &num) != 0 ||
+ num < 0 || num > INT_MAX) {
+ TARFS_DPF(ALLOC, "%s: %.*s: invalid device minor\n",
+ __func__, (int)namelen, name);
+ error = EINVAL;
+ goto bad;
+ }
+ minor = num;
rdev = makedev(major, minor);
error = tarfs_alloc_node(tmp, namep, sep - namep, VCHR,
0, 0, mtime, uid, gid, mode, flags, NULL, rdev,

File Metadata

Mime Type
text/plain
Expires
Thu, May 1, 3:53 AM (18 h, 7 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17872146
Default Alt Text
D44166.id135457.diff (6 KB)

Event Timeline