From: Chris Frey Date: Tue, 1 Oct 2013 19:58:52 +0000 (-0400) Subject: Fixed size_t overflow bug, as reported by Timo Warns X-Git-Tag: v1.2.20~1 X-Git-Url: https://repo.or.cz/w/libtar.git/commitdiff_plain/45448e8bae671c2f7e80b860ae0fc0cedf2bdc04?hp=a4846f7e862b92f1ff47d08224da63b8fdf1e13a Fixed size_t overflow bug, as reported by Timo Warns --- diff --git a/lib/block.c b/lib/block.c index 2917dc6..092bc28 100644 --- a/lib/block.c +++ b/lib/block.c @@ -90,8 +90,8 @@ th_read_internal(TAR *t) int th_read(TAR *t) { - int i, j; - size_t sz; + int i; + size_t sz, j, blocks; char *ptr; #ifdef DEBUG @@ -118,21 +118,26 @@ th_read(TAR *t) if (TH_ISLONGLINK(t)) { sz = th_get_size(t); - j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); + blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); + if (blocks > ((size_t)-1 / T_BLOCKSIZE)) + { + errno = E2BIG; + return -1; + } #ifdef DEBUG printf(" th_read(): GNU long linkname detected " - "(%ld bytes, %d blocks)\n", sz, j); + "(%ld bytes, %d blocks)\n", sz, blocks); #endif - t->th_buf.gnu_longlink = (char *)malloc(j * T_BLOCKSIZE); + t->th_buf.gnu_longlink = (char *)malloc(blocks * T_BLOCKSIZE); if (t->th_buf.gnu_longlink == NULL) return -1; - for (ptr = t->th_buf.gnu_longlink; j > 0; - j--, ptr += T_BLOCKSIZE) + for (j = 0, ptr = t->th_buf.gnu_longlink; j < blocks; + j++, ptr += T_BLOCKSIZE) { #ifdef DEBUG printf(" th_read(): reading long linkname " - "(%d blocks left, ptr == %ld)\n", j, ptr); + "(%d blocks left, ptr == %ld)\n", blocks-j, ptr); #endif i = tar_block_read(t, ptr); if (i != T_BLOCKSIZE) @@ -163,21 +168,26 @@ th_read(TAR *t) if (TH_ISLONGNAME(t)) { sz = th_get_size(t); - j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); + blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); + if (blocks > ((size_t)-1 / T_BLOCKSIZE)) + { + errno = E2BIG; + return -1; + } #ifdef DEBUG printf(" th_read(): GNU long filename detected " - "(%ld bytes, %d blocks)\n", sz, j); + "(%ld bytes, %d blocks)\n", sz, blocks); #endif - t->th_buf.gnu_longname = (char *)malloc(j * T_BLOCKSIZE); + t->th_buf.gnu_longname = (char *)malloc(blocks * T_BLOCKSIZE); if (t->th_buf.gnu_longname == NULL) return -1; - for (ptr = t->th_buf.gnu_longname; j > 0; - j--, ptr += T_BLOCKSIZE) + for (j = 0, ptr = t->th_buf.gnu_longname; j < blocks; + j++, ptr += T_BLOCKSIZE) { #ifdef DEBUG printf(" th_read(): reading long filename " - "(%d blocks left, ptr == %ld)\n", j, ptr); + "(%d blocks left, ptr == %ld)\n", blocks-j, ptr); #endif i = tar_block_read(t, ptr); if (i != T_BLOCKSIZE)