Module Name: src Committed By: riastradh Date: Sat Jan 25 15:31:06 UTC 2014
Modified Files: src/usr.bin/vndcompress: offtab.c vndcompress.c vnduncompress.c Log Message: Fix some more integer overflow/truncation issues. Arithmetic in C is hard. Let's go shopping! To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/usr.bin/vndcompress/offtab.c \ src/usr.bin/vndcompress/vnduncompress.c cvs rdiff -u -r1.23 -r1.24 src/usr.bin/vndcompress/vndcompress.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/vndcompress/offtab.c diff -u src/usr.bin/vndcompress/offtab.c:1.10 src/usr.bin/vndcompress/offtab.c:1.11 --- src/usr.bin/vndcompress/offtab.c:1.10 Thu Jan 23 14:17:05 2014 +++ src/usr.bin/vndcompress/offtab.c Sat Jan 25 15:31:06 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: offtab.c,v 1.10 2014/01/23 14:17:05 joerg Exp $ */ +/* $NetBSD: offtab.c,v 1.11 2014/01/25 15:31:06 riastradh Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: offtab.c,v 1.10 2014/01/23 14:17:05 joerg Exp $"); +__RCSID("$NetBSD: offtab.c,v 1.11 2014/01/25 15:31:06 riastradh Exp $"); #include <sys/types.h> #include <sys/endian.h> @@ -104,28 +104,27 @@ offtab_read_window(struct offtab *offtab __CTASSERT(MAX_WINDOW_SIZE <= (SIZE_MAX / sizeof(uint64_t))); __CTASSERT(MAX_N_OFFSETS <= (OFF_MAX / sizeof(uint64_t))); assert(window_start < offtab->ot_n_offsets); - assert(offtab->ot_fdpos <= - (OFF_MAX - (off_t)(window_start * sizeof(uint64_t)))); + const off_t window_offset = ((off_t)window_start * + (off_t)sizeof(uint64_t)); + assert(offtab->ot_fdpos <= (OFF_MAX - window_offset)); + const off_t window_pos = (offtab->ot_fdpos + window_offset); assert(ISSET(read_flags, OFFTAB_READ_SEEK) || (lseek(offtab->ot_fd, 0, SEEK_CUR) == offtab->ot_fdpos) || ((lseek(offtab->ot_fd, 0, SEEK_CUR) == -1) && (errno == ESPIPE))); const size_t n_req = (window_size * sizeof(uint64_t)); const ssize_t n_read = (ISSET(read_flags, OFFTAB_READ_SEEK) - ? pread_block(offtab->ot_fd, offtab->ot_window, n_req, - (offtab->ot_fdpos + (window_start * sizeof(uint64_t)))) + ? pread_block(offtab->ot_fd, offtab->ot_window, n_req, window_pos) : read_block(offtab->ot_fd, offtab->ot_window, n_req)); if (n_read == -1) { (*offtab->ot_report)("read offset table at %"PRIuMAX, - (uintmax_t)(offtab->ot_fdpos + - (window_start * sizeof(uint64_t)))); + (uintmax_t)window_pos); return false; } assert(n_read >= 0); if ((size_t)n_read != (window_size * sizeof(uint64_t))) { (*offtab->ot_reportx)("partial read of offset table" " at %"PRIuMAX": %zu != %zu", - (uintmax_t)(offtab->ot_fdpos + - (window_start * sizeof(uint64_t))), + (uintmax_t)window_pos, (size_t)n_read, (size_t)(window_size * sizeof(uint64_t))); return false; @@ -160,12 +159,13 @@ offtab_write_window(struct offtab *offta __CTASSERT(MAX_WINDOW_SIZE <= (SIZE_MAX / sizeof(uint64_t))); __CTASSERT(MAX_N_OFFSETS <= (OFF_MAX / sizeof(uint64_t))); assert(offtab->ot_window_start < offtab->ot_n_offsets); - assert(offtab->ot_fdpos <= - (OFF_MAX - (off_t)(offtab->ot_window_start * sizeof(uint64_t)))); + const off_t window_offset = ((off_t)offtab->ot_window_start * + (off_t)sizeof(uint64_t)); + assert(offtab->ot_fdpos <= (OFF_MAX - window_offset)); + const off_t window_pos = (offtab->ot_fdpos + window_offset); const ssize_t n_written = pwrite(offtab->ot_fd, offtab->ot_window, (window_size * sizeof(uint64_t)), - (offtab->ot_fdpos + - (offtab->ot_window_start * sizeof(uint64_t)))); + window_pos); if (n_written == -1) err_ss(1, "write initial offset table"); assert(n_written >= 0); @@ -283,10 +283,10 @@ offtab_reset_read(struct offtab *offtab, if (offtab->ot_window_size < offtab->ot_n_offsets) { __CTASSERT(MAX_N_OFFSETS <= (OFF_MAX / sizeof(uint64_t))); - assert(offtab->ot_fdpos <= (OFF_MAX - - (off_t)(offtab->ot_n_offsets * sizeof(uint64_t)))); - const off_t first_offset = (offtab->ot_fdpos + - (offtab->ot_n_offsets * sizeof(uint64_t))); + const off_t offtab_bytes = ((off_t)offtab->ot_n_offsets * + (off_t)sizeof(uint64_t)); + assert(offtab->ot_fdpos <= (OFF_MAX - offtab_bytes)); + const off_t first_offset = (offtab->ot_fdpos + offtab_bytes); if (lseek(offtab->ot_fd, first_offset, SEEK_SET) == -1) { (*offtab->ot_report)("lseek to first offset 0x%"PRIx64, first_offset); @@ -371,13 +371,15 @@ offtab_reset_write(struct offtab *offtab } offtab->ot_window_start = 0; - __CTASSERT(MAX_N_OFFSETS <= (OFF_MAX / sizeof(uint64_t))); + __CTASSERT(MAX_N_OFFSETS <= + (MIN(OFF_MAX, UINT64_MAX) / sizeof(uint64_t))); + const off_t offtab_bytes = ((off_t)offtab->ot_n_offsets * + sizeof(uint64_t)); assert(offtab->ot_fdpos <= - (OFF_MAX - (off_t)(offtab->ot_n_offsets * sizeof(uint64_t)))); - const uint64_t first_offset = (offtab->ot_fdpos + - (offtab->ot_n_offsets * sizeof(uint64_t))); - assert(first_offset <= OFF_MAX); - offtab->ot_window[0] = htobe64(first_offset); + ((off_t)MIN(OFF_MAX, UINT64_MAX) - offtab_bytes)); + const off_t first_offset = (offtab->ot_fdpos + offtab_bytes); + assert(first_offset <= (off_t)MIN(OFF_MAX, UINT64_MAX)); + offtab->ot_window[0] = htobe64((uint64_t)first_offset); offtab_write_window(offtab); if (lseek(offtab->ot_fd, first_offset, SEEK_SET) == -1) @@ -412,11 +414,11 @@ offtab_checkpoint(struct offtab *offtab, if (ISSET(flags, OFFTAB_CHECKPOINT_SYNC)) { __CTASSERT(MAX_N_OFFSETS <= (OFF_MAX / sizeof(uint64_t))); - assert(offtab->ot_fdpos - <= (OFF_MAX - (off_t)(n_offsets * sizeof(uint64_t)))); + const off_t sync_bytes = ((off_t)n_offsets * + (off_t)sizeof(uint64_t)); + assert(offtab->ot_fdpos <= (OFF_MAX - sync_bytes)); if (fsync_range(offtab->ot_fd, (FFILESYNC | FDISKSYNC), - offtab->ot_fdpos, - (offtab->ot_fdpos + (n_offsets * sizeof(uint64_t)))) + offtab->ot_fdpos, (offtab->ot_fdpos + sync_bytes)) == -1) warn_ss("fsync of offset table failed"); } Index: src/usr.bin/vndcompress/vnduncompress.c diff -u src/usr.bin/vndcompress/vnduncompress.c:1.10 src/usr.bin/vndcompress/vnduncompress.c:1.11 --- src/usr.bin/vndcompress/vnduncompress.c:1.10 Wed Jan 22 06:18:00 2014 +++ src/usr.bin/vndcompress/vnduncompress.c Sat Jan 25 15:31:06 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vnduncompress.c,v 1.10 2014/01/22 06:18:00 riastradh Exp $ */ +/* $NetBSD: vnduncompress.c,v 1.11 2014/01/25 15:31:06 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: vnduncompress.c,v 1.10 2014/01/22 06:18:00 riastradh Exp $"); +__RCSID("$NetBSD: vnduncompress.c,v 1.11 2014/01/25 15:31:06 riastradh Exp $"); #include <sys/endian.h> @@ -158,7 +158,8 @@ vnduncompress(int argc, char **argv, con __CTASSERT(sizeof(header) <= (OFF_MAX - (MAX_N_OFFSETS * sizeof(uint64_t)))); __CTASSERT(OFF_MAX <= UINT64_MAX); - uint64_t offset = (sizeof(header) + (n_offsets * sizeof(uint64_t))); + uint64_t offset = (sizeof(header) + + ((uint64_t)n_offsets * sizeof(uint64_t))); uint32_t blkno; (void)offtab_prepare_get(&offtab, 0); uint64_t last = offtab_get(&offtab, 0); Index: src/usr.bin/vndcompress/vndcompress.c diff -u src/usr.bin/vndcompress/vndcompress.c:1.23 src/usr.bin/vndcompress/vndcompress.c:1.24 --- src/usr.bin/vndcompress/vndcompress.c:1.23 Fri Jan 24 17:30:18 2014 +++ src/usr.bin/vndcompress/vndcompress.c Sat Jan 25 15:31:06 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vndcompress.c,v 1.23 2014/01/24 17:30:18 christos Exp $ */ +/* $NetBSD: vndcompress.c,v 1.24 2014/01/25 15:31:06 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: vndcompress.c,v 1.23 2014/01/24 17:30:18 christos Exp $"); +__RCSID("$NetBSD: vndcompress.c,v 1.24 2014/01/25 15:31:06 riastradh Exp $"); #include <sys/endian.h> @@ -307,10 +307,12 @@ info_signal_handler(int signo __unused) const uint64_t nread = ((uint64_t)S->blkno * (uint64_t)S->blocksize); assert(S->n_blocks > 0); + __CTASSERT(CLOOP2_OFFSET_TABLE_OFFSET <= + (UINT64_MAX / sizeof(uint64_t))); __CTASSERT(MAX_N_BLOCKS <= ((UINT64_MAX / sizeof(uint64_t)) - CLOOP2_OFFSET_TABLE_OFFSET)); const uint64_t nwritten = (S->offset <= (CLOOP2_OFFSET_TABLE_OFFSET + - (S->n_blocks * sizeof(uint64_t)))? + ((uint64_t)S->n_blocks * sizeof(uint64_t)))? 0 : S->offset); /* snprintf_ss can't do floating-point, so do fixed-point instead. */ @@ -533,7 +535,7 @@ compress_init(int argc, char **argv, con /* Start at the beginning of the image. */ S->blkno = 0; S->offset = (sizeof(struct cloop2_header) + - (S->n_offsets * sizeof(uint64_t))); + ((uint64_t)S->n_offsets * sizeof(uint64_t))); S->n_checkpointed_blocks = 0; /* Good to go and ready for interruption by a signal. */