Mercurial > vim
diff src/memline.c @ 29340:fba9e366ced4 v9.0.0013
patch 9.0.0013: reproducing memory access errors can be difficult
Commit: https://github.com/vim/vim/commit/fa4873ccfc10e0f278dc46f39d00136fab059b19
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Jun 30 22:13:59 2022 +0100
patch 9.0.0013: reproducing memory access errors can be difficult
Problem: Reproducing memory access errors can be difficult.
Solution: When testing, copy each line to allocated memory, so that valgrind
can detect accessing memory before and/or after it. Fix uncovered
problems.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 30 Jun 2022 23:15:03 +0200 |
parents | b3828315a0d9 |
children | 23dceecc0bf8 |
line wrap: on
line diff
--- a/src/memline.c +++ b/src/memline.c @@ -858,7 +858,8 @@ ml_close(buf_T *buf, int del_file) if (buf->b_ml.ml_mfp == NULL) // not open return; mf_close(buf->b_ml.ml_mfp, del_file); // close the .swp file - if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY)) + if (buf->b_ml.ml_line_lnum != 0 + && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))) vim_free(buf->b_ml.ml_line_ptr); vim_free(buf->b_ml.ml_stack); #ifdef FEAT_BYTEOFF @@ -2620,7 +2621,6 @@ ml_get_buf( --recursive; } ml_flush_line(buf); - buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; errorret: STRCPY(questions, "???"); buf->b_ml.ml_line_len = 4; @@ -2686,17 +2686,44 @@ errorret: buf->b_ml.ml_line_ptr = (char_u *)dp + start; buf->b_ml.ml_line_len = len; buf->b_ml.ml_line_lnum = lnum; - buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; + buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); } if (will_change) + { buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); - +#ifdef FEAT_EVAL + if (ml_get_alloc_lines && (buf->b_ml.ml_flags & ML_ALLOCATED)) + // can't make the change in the data block + buf->b_ml.ml_flags |= ML_LINE_DIRTY; +#endif + } + +#ifdef FEAT_EVAL + if (ml_get_alloc_lines + && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) == 0) + { + char_u *p = alloc(buf->b_ml.ml_line_len); + + // make sure the text is in allocated memory + if (p != NULL) + { + memmove(p, buf->b_ml.ml_line_ptr, buf->b_ml.ml_line_len); + buf->b_ml.ml_line_ptr = p; + buf->b_ml.ml_flags |= ML_ALLOCATED; + if (will_change) + // can't make the change in the data block + buf->b_ml.ml_flags |= ML_LINE_DIRTY; + } + } +#endif return buf->b_ml.ml_line_ptr; } /* * Check if a line that was just obtained by a call to ml_get * is in allocated memory. + * This ignores ML_ALLOCATED to get the same behavior as without the test + * override. */ int ml_line_alloced(void) @@ -3409,6 +3436,8 @@ ml_replace(linenr_T lnum, char_u *line, * "len_arg" is the length of the text, excluding NUL. * If "has_props" is TRUE then "line_arg" includes the text properties and * "len_arg" includes the NUL of the text. + * When "copy" is TRUE copy the text into allocated memory, otherwise + * "line_arg" must be allocated and will be consumed here. */ int ml_replace_len( @@ -3454,7 +3483,6 @@ ml_replace_len( { // another line is buffered, flush it ml_flush_line(curbuf); - curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY; #ifdef FEAT_PROP_POPUP if (curbuf->b_has_textprop && !has_props) @@ -3488,8 +3516,8 @@ ml_replace_len( } #endif - if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) // same line allocated - vim_free(curbuf->b_ml.ml_line_ptr); // free it + if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) + vim_free(curbuf->b_ml.ml_line_ptr); // free allocated line curbuf->b_ml.ml_line_ptr = line; curbuf->b_ml.ml_line_len = len; @@ -4064,7 +4092,10 @@ ml_flush_line(buf_T *buf) entered = FALSE; } - + else if (buf->b_ml.ml_flags & ML_ALLOCATED) + vim_free(buf->b_ml.ml_line_ptr); + + buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); buf->b_ml.ml_line_lnum = 0; }