Subversion Repositories

?revision_form?Rev ?revision_input??revision_submit??revision_endform?

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
27 magnus 1
Origin: upstream, http://repo.or.cz/w/libtar.git/commitdiff/45448e8bae671c2f7e80b860ae0fc0cedf2bdc04
2
From: Chris Frey <cdfrey@foursquare.net>
3
Date: Tue, 1 Oct 2013 15:58:52 -0400
4
Subject: [PATCH] Fixed size_t overflow bug, as reported by Timo Warns
5
 
6
---
7
 lib/block.c | 38 ++++++++++++++++++++++++--------------
8
 1 file changed, 24 insertions(+), 14 deletions(-)
9
 
10
diff --git a/lib/block.c b/lib/block.c
11
index 2917dc6..092bc28 100644
12
--- a/lib/block.c
13
+++ b/lib/block.c
14
@@ -90,8 +90,8 @@ th_read_internal(TAR *t)
15
 int
16
 th_read(TAR *t)
17
 {
18
-       int i, j;
19
-       size_t sz;
20
+       int i;
21
+       size_t sz, j, blocks;
22
        char *ptr;
23
 
24
 #ifdef DEBUG
25
@@ -118,21 +118,26 @@ th_read(TAR *t)
26
        if (TH_ISLONGLINK(t))
27
        {
28
                sz = th_get_size(t);
29
-               j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
30
+               blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
31
+               if (blocks > ((size_t)-1 / T_BLOCKSIZE))
32
+               {
33
+                       errno = E2BIG;
34
+                       return -1;
35
+               }
36
 #ifdef DEBUG
37
                printf("    th_read(): GNU long linkname detected "
38
-                      "(%ld bytes, %d blocks)\n", sz, j);
39
+                      "(%ld bytes, %d blocks)\n", sz, blocks);
40
 #endif
41
-               t->th_buf.gnu_longlink = (char *)malloc(j * T_BLOCKSIZE);
42
+               t->th_buf.gnu_longlink = (char *)malloc(blocks * T_BLOCKSIZE);
43
                if (t->th_buf.gnu_longlink == NULL)
44
                        return -1;
45
 
46
-               for (ptr = t->th_buf.gnu_longlink; j > 0;
47
-                    j--, ptr += T_BLOCKSIZE)
48
+               for (j = 0, ptr = t->th_buf.gnu_longlink; j < blocks;
49
+                    j++, ptr += T_BLOCKSIZE)
50
                {
51
 #ifdef DEBUG
52
                        printf("    th_read(): reading long linkname "
53
-                              "(%d blocks left, ptr == %ld)\n", j, ptr);
54
+                              "(%d blocks left, ptr == %ld)\n", blocks-j, ptr);
55
 #endif
56
                        i = tar_block_read(t, ptr);
57
                        if (i != T_BLOCKSIZE)
58
@@ -163,21 +168,26 @@ th_read(TAR *t)
59
        if (TH_ISLONGNAME(t))
60
        {
61
                sz = th_get_size(t);
62
-               j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
63
+               blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
64
+               if (blocks > ((size_t)-1 / T_BLOCKSIZE))
65
+               {
66
+                       errno = E2BIG;
67
+                       return -1;
68
+               }
69
 #ifdef DEBUG
70
                printf("    th_read(): GNU long filename detected "
71
-                      "(%ld bytes, %d blocks)\n", sz, j);
72
+                      "(%ld bytes, %d blocks)\n", sz, blocks);
73
 #endif
74
-               t->th_buf.gnu_longname = (char *)malloc(j * T_BLOCKSIZE);
75
+               t->th_buf.gnu_longname = (char *)malloc(blocks * T_BLOCKSIZE);
76
                if (t->th_buf.gnu_longname == NULL)
77
                        return -1;
78
 
79
-               for (ptr = t->th_buf.gnu_longname; j > 0;
80
-                    j--, ptr += T_BLOCKSIZE)
81
+               for (j = 0, ptr = t->th_buf.gnu_longname; j < blocks;
82
+                    j++, ptr += T_BLOCKSIZE)
83
                {
84
 #ifdef DEBUG
85
                        printf("    th_read(): reading long filename "
86
-                              "(%d blocks left, ptr == %ld)\n", j, ptr);
87
+                              "(%d blocks left, ptr == %ld)\n", blocks-j, ptr);
88
 #endif
89
                        i = tar_block_read(t, ptr);
90
                        if (i != T_BLOCKSIZE)
91
-- 
92
1.8.4.rc3
93