1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
$NetBSD: patch-ai,v 1.1 2006/09/03 17:24:16 adrianp Exp $
--- src/xheader.c.orig 2004-09-06 12:31:14.000000000 +0100
+++ src/xheader.c
@@ -783,6 +783,32 @@ code_num (uintmax_t value, char const *k
xheader_print (xhdr, keyword, sbuf);
}
+static bool
+decode_num (uintmax_t *num, char const *arg, uintmax_t maxval,
+ char const *keyword)
+{
+ uintmax_t u;
+ char *arg_lim;
+
+ if (! (ISDIGIT (*arg)
+ && (errno = 0, u = strtoumax (arg, &arg_lim, 10), !*arg_lim)))
+ {
+ ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
+ keyword, arg));
+ return false;
+ }
+
+ if (! (u <= maxval && errno != ERANGE))
+ {
+ ERROR ((0, 0, _("Extended header %s=%s is out of range"),
+ keyword, arg));
+ return false;
+ }
+
+ *num = u;
+ return true;
+}
+
static void
dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
char const *keyword __attribute__ ((unused)),
@@ -821,7 +847,7 @@ static void
gid_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), "gid"))
st->stat.st_gid = u;
}
@@ -903,7 +929,7 @@ static void
size_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "size"))
st->archive_file_size = st->stat.st_size = u;
}
@@ -918,7 +944,7 @@ static void
uid_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), "uid"))
st->stat.st_uid = u;
}
@@ -946,7 +972,7 @@ static void
sparse_size_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "GNU.sparse.size"))
st->stat.st_size = u;
}
@@ -962,10 +988,10 @@ static void
sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, SIZE_MAX, "GNU.sparse.numblocks"))
{
st->sparse_map_size = u;
- st->sparse_map = calloc(st->sparse_map_size, sizeof(st->sparse_map[0]));
+ st->sparse_map = xcalloc (u, sizeof st->sparse_map[0]);
st->sparse_map_avail = 0;
}
}
@@ -982,8 +1008,14 @@ static void
sparse_offset_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "GNU.sparse.offset"))
+ {
+ if (st->sparse_map_avail < st->sparse_map_size)
st->sparse_map[st->sparse_map_avail].offset = u;
+ else
+ ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
+ "GNU.sparse.offset", arg));
+ }
}
static void
@@ -998,15 +1030,13 @@ static void
sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
- if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
+ if (decode_num (&u, arg, SIZE_MAX, "GNU.sparse.numbytes"))
{
if (st->sparse_map_avail == st->sparse_map_size)
- {
- st->sparse_map_size *= 2;
- st->sparse_map = xrealloc (st->sparse_map,
- st->sparse_map_size
- * sizeof st->sparse_map[0]);
- }
+ st->sparse_map = x2nrealloc (st->sparse_map,
+ &st->sparse_map_size,
+ sizeof st->sparse_map[0]);
+
st->sparse_map[st->sparse_map_avail++].numbytes = u;
}
}
|