diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-06-30 22:13:59 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-06-30 22:13:59 +0100 |
commit | fa4873ccfc10e0f278dc46f39d00136fab059b19 (patch) | |
tree | 55d4275e939188fc973d53bcf19e3d6136e6efe6 /src/memline.c | |
parent | cdbfc6dbab1d63aa56af316d6b13e37939e7f7a8 (diff) |
patch 9.0.0013: reproducing memory access errors can be difficultv9.0.0013
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.
Diffstat (limited to 'src/memline.c')
-rw-r--r-- | src/memline.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/src/memline.c b/src/memline.c index 83aa2c68d5..2f73477b5f 100644 --- 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, int copy) * "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; } |