Package: file / 1:5.30-1+deb9u3

cherry-pick.FILE5_30-19-g7605984c.although-i-can-t-reproduce-it-oss-fuzz-complains-about-is-tar.patch Patch series | download
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
Subject: Although I can't reproduce it, oss-fuzz complains about is_tar
Origin: FILE5_30-19-g7605984c
Upstream-Author: Christos Zoulas <christos@zoulas.com>
Date: Fri Mar 17 20:45:01 2017 +0000

    Although I can't reproduce it, oss-fuzz complains about is_tar. So rewrite
    it to make it more obvious what's going on.

--- a/src/is_tar.c
+++ b/src/is_tar.c
@@ -51,7 +51,7 @@
 #define	isodigit(c)	( ((c) >= '0') && ((c) <= '7') )
 
 private int is_tar(const unsigned char *, size_t);
-private int from_oct(int, const char *);	/* Decode octal number */
+private int from_oct(const char *, size_t);	/* Decode octal number */
 
 static const char tartype[][32] = {
 	"tar archive",
@@ -93,31 +93,35 @@
 is_tar(const unsigned char *buf, size_t nbytes)
 {
 	const union record *header = (const union record *)(const void *)buf;
-	int	i;
-	int	sum, recsum;
-	const unsigned char	*p;
+	size_t i;
+	int sum, recsum;
+	const unsigned char *p, *ep;
 
-	if (nbytes < sizeof(union record))
+	if (nbytes < sizeof(*header))
 		return 0;
 
-	recsum = from_oct(8,  header->header.chksum);
+	recsum = from_oct(header->header.chksum, sizeof(header->header.chksum));
 
 	sum = 0;
 	p = header->charptr;
-	for (i = sizeof(union record); --i >= 0;)
+	ep = header->charptr + sizeof(*header);
+	while (p < ep)
 		sum += *p++;
 
 	/* Adjust checksum to count the "chksum" field as blanks. */
-	for (i = sizeof(header->header.chksum); --i >= 0;)
+	for (i = 0; i < sizeof(header->header.chksum); i++)
 		sum -= header->header.chksum[i];
-	sum += ' ' * sizeof header->header.chksum;
+	sum += ' ' * sizeof(header->header.chksum);
 
 	if (sum != recsum)
 		return 0;	/* Not a tar archive */
 
-	if (strcmp(header->header.magic, GNUTMAGIC) == 0)
+	if (strncmp(header->header.magic, GNUTMAGIC,
+	    sizeof(header->header.magic)) == 0)
 		return 3;		/* GNU Unix Standard tar archive */
-	if (strcmp(header->header.magic, TMAGIC) == 0)
+
+	if (strncmp(header->header.magic, TMAGIC,
+	    sizeof(header->header.magic)) == 0)
 		return 2;		/* Unix Standard tar archive */
 
 	return 1;			/* Old fashioned tar archive */
@@ -130,19 +134,22 @@
  * Result is -1 if the field is invalid (all blank, or non-octal).
  */
 private int
-from_oct(int digs, const char *where)
+from_oct(const char *where, size_t digs)
 {
 	int	value;
 
+	if (digs == 0)
+		return -1;
+
 	while (isspace((unsigned char)*where)) {	/* Skip spaces */
 		where++;
-		if (--digs <= 0)
+		if (digs-- == 0)
 			return -1;		/* All blank field */
 	}
 	value = 0;
 	while (digs > 0 && isodigit(*where)) {	/* Scan til non-octal */
 		value = (value << 3) | (*where++ - '0');
-		--digs;
+		digs--;
 	}
 
 	if (digs > 0 && *where && !isspace((unsigned char)*where))