diff options
-rw-r--r-- | src/nvim/memfile.c | 26 | ||||
-rw-r--r-- | src/nvim/memfile_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/memline.c | 8 |
3 files changed, 22 insertions, 14 deletions
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index f5176abd1c..d396b005a4 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -129,12 +129,16 @@ memfile_T *mf_open(char_u *fname, int flags) // must be rounded up. if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL)) - || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) + || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) { // no file or empty file mfp->mf_blocknr_max = 0; - else - mfp->mf_blocknr_max = (blocknr_T)((size + mfp->mf_page_size - 1) - / mfp->mf_page_size); + } else { + assert(sizeof(off_t) <= sizeof(blocknr_T) + && mfp->mf_page_size > 0 + && mfp->mf_page_size - 1 <= INT64_MAX - size); + mfp->mf_blocknr_max = (((blocknr_T)size + mfp->mf_page_size - 1) + / mfp->mf_page_size); + } mfp->mf_blocknr_min = -1; mfp->mf_neg_count = 0; mfp->mf_infile_count = mfp->mf_blocknr_max; @@ -151,8 +155,8 @@ memfile_T *mf_open(char_u *fname, int flags) --shift; } - assert(p_mm << shift >= p_mm); // check we don't overflow - assert(p_mm < UINT_MAX); // check we can cast to unsigned + assert(p_mm <= LONG_MAX >> shift); // check we don't overflow + assert((uintmax_t)(p_mm << shift) <= UINT_MAX); // check we can cast safely mfp->mf_used_count_max = (unsigned)(p_mm << shift) / page_size; if (mfp->mf_used_count_max < 10) mfp->mf_used_count_max = 10; @@ -706,12 +710,15 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp) return FAIL; unsigned page_size = mfp->mf_page_size; - off_t offset = (off_t)page_size * hp->bh_bnum; - unsigned size = page_size * hp->bh_page_count; + // TODO(elmart): Check (page_size * hp->bh_bnum) within off_t bounds. + off_t offset = (off_t)(page_size * hp->bh_bnum); if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { PERROR(_("E294: Seek error in swap file read")); return FAIL; } + // check for overflow; we know that page_size must be > 0 + assert(hp->bh_page_count <= UINT_MAX / page_size); + unsigned size = page_size * hp->bh_page_count; if ((unsigned)read_eintr(mfp->mf_fd, hp->bh_data, size) != size) { PERROR(_("E295: Read error in swap file")); return FAIL; @@ -758,7 +765,8 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp) } else hp2 = hp; - offset = (off_t)page_size * nr; + // TODO(elmart): Check (page_size * nr) within off_t bounds. + offset = (off_t)(page_size * nr); if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { PERROR(_("E296: Seek error in swap file write")); return FAIL; diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h index 06a7dbe01a..8fe0a6aefb 100644 --- a/src/nvim/memfile_defs.h +++ b/src/nvim/memfile_defs.h @@ -11,7 +11,7 @@ /// Blocks numbered from 0 upwards have been assigned a place in the actual /// file. The block number is equal to the page number in the file. The blocks /// with negative numbers are currently in memory only. -typedef long blocknr_T; +typedef int64_t blocknr_T; /// A hash item. /// diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 97b6dd32c1..91fbe62c18 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -639,7 +639,7 @@ static void ml_upd_block0(buf_T *buf, upd_block0_T what) ZERO_BL *b0p; mfp = buf->b_ml.ml_mfp; - if (mfp == NULL || (hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL) + if (mfp == NULL || (hp = mf_get(mfp, 0, 1)) == NULL) return; b0p = hp->bh_data; if (ml_check_b0_id(b0p) == FAIL) @@ -867,7 +867,7 @@ void ml_recover(void) /* * try to read block 0 */ - if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL) { + if ((hp = mf_get(mfp, 0, 1)) == NULL) { msg_start(); MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST); msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST); @@ -925,7 +925,7 @@ void ml_recover(void) if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) mfp->mf_blocknr_max = 0; /* no file or empty file */ else - mfp->mf_blocknr_max = (blocknr_T)(size / mfp->mf_page_size); + mfp->mf_blocknr_max = size / mfp->mf_page_size; mfp->mf_infile_count = mfp->mf_blocknr_max; /* need to reallocate the memory used to store the data */ @@ -1031,7 +1031,7 @@ void ml_recover(void) /* * get block */ - if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL) { + if ((hp = mf_get(mfp, bnum, page_count)) == NULL) { if (bnum == 1) { EMSG2(_("E309: Unable to read block 1 from %s"), mfp->mf_fname); goto theend; |