Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
29339:a023e3008ae3 | 29340:fba9e366ced4 |
---|---|
856 ml_close(buf_T *buf, int del_file) | 856 ml_close(buf_T *buf, int del_file) |
857 { | 857 { |
858 if (buf->b_ml.ml_mfp == NULL) // not open | 858 if (buf->b_ml.ml_mfp == NULL) // not open |
859 return; | 859 return; |
860 mf_close(buf->b_ml.ml_mfp, del_file); // close the .swp file | 860 mf_close(buf->b_ml.ml_mfp, del_file); // close the .swp file |
861 if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY)) | 861 if (buf->b_ml.ml_line_lnum != 0 |
862 && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))) | |
862 vim_free(buf->b_ml.ml_line_ptr); | 863 vim_free(buf->b_ml.ml_line_ptr); |
863 vim_free(buf->b_ml.ml_stack); | 864 vim_free(buf->b_ml.ml_stack); |
864 #ifdef FEAT_BYTEOFF | 865 #ifdef FEAT_BYTEOFF |
865 VIM_CLEAR(buf->b_ml.ml_chunksize); | 866 VIM_CLEAR(buf->b_ml.ml_chunksize); |
866 #endif | 867 #endif |
2618 ++recursive; | 2619 ++recursive; |
2619 siemsg(_(e_ml_get_invalid_lnum_nr), lnum); | 2620 siemsg(_(e_ml_get_invalid_lnum_nr), lnum); |
2620 --recursive; | 2621 --recursive; |
2621 } | 2622 } |
2622 ml_flush_line(buf); | 2623 ml_flush_line(buf); |
2623 buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; | |
2624 errorret: | 2624 errorret: |
2625 STRCPY(questions, "???"); | 2625 STRCPY(questions, "???"); |
2626 buf->b_ml.ml_line_len = 4; | 2626 buf->b_ml.ml_line_len = 4; |
2627 buf->b_ml.ml_line_lnum = lnum; | 2627 buf->b_ml.ml_line_lnum = lnum; |
2628 return questions; | 2628 return questions; |
2684 len = end - start; | 2684 len = end - start; |
2685 | 2685 |
2686 buf->b_ml.ml_line_ptr = (char_u *)dp + start; | 2686 buf->b_ml.ml_line_ptr = (char_u *)dp + start; |
2687 buf->b_ml.ml_line_len = len; | 2687 buf->b_ml.ml_line_len = len; |
2688 buf->b_ml.ml_line_lnum = lnum; | 2688 buf->b_ml.ml_line_lnum = lnum; |
2689 buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; | 2689 buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); |
2690 } | 2690 } |
2691 if (will_change) | 2691 if (will_change) |
2692 { | |
2692 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); | 2693 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); |
2693 | 2694 #ifdef FEAT_EVAL |
2695 if (ml_get_alloc_lines && (buf->b_ml.ml_flags & ML_ALLOCATED)) | |
2696 // can't make the change in the data block | |
2697 buf->b_ml.ml_flags |= ML_LINE_DIRTY; | |
2698 #endif | |
2699 } | |
2700 | |
2701 #ifdef FEAT_EVAL | |
2702 if (ml_get_alloc_lines | |
2703 && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) == 0) | |
2704 { | |
2705 char_u *p = alloc(buf->b_ml.ml_line_len); | |
2706 | |
2707 // make sure the text is in allocated memory | |
2708 if (p != NULL) | |
2709 { | |
2710 memmove(p, buf->b_ml.ml_line_ptr, buf->b_ml.ml_line_len); | |
2711 buf->b_ml.ml_line_ptr = p; | |
2712 buf->b_ml.ml_flags |= ML_ALLOCATED; | |
2713 if (will_change) | |
2714 // can't make the change in the data block | |
2715 buf->b_ml.ml_flags |= ML_LINE_DIRTY; | |
2716 } | |
2717 } | |
2718 #endif | |
2694 return buf->b_ml.ml_line_ptr; | 2719 return buf->b_ml.ml_line_ptr; |
2695 } | 2720 } |
2696 | 2721 |
2697 /* | 2722 /* |
2698 * Check if a line that was just obtained by a call to ml_get | 2723 * Check if a line that was just obtained by a call to ml_get |
2699 * is in allocated memory. | 2724 * is in allocated memory. |
2725 * This ignores ML_ALLOCATED to get the same behavior as without the test | |
2726 * override. | |
2700 */ | 2727 */ |
2701 int | 2728 int |
2702 ml_line_alloced(void) | 2729 ml_line_alloced(void) |
2703 { | 2730 { |
2704 return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY); | 2731 return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY); |
3407 /* | 3434 /* |
3408 * Replace a line for the current buffer. Like ml_replace() with: | 3435 * Replace a line for the current buffer. Like ml_replace() with: |
3409 * "len_arg" is the length of the text, excluding NUL. | 3436 * "len_arg" is the length of the text, excluding NUL. |
3410 * If "has_props" is TRUE then "line_arg" includes the text properties and | 3437 * If "has_props" is TRUE then "line_arg" includes the text properties and |
3411 * "len_arg" includes the NUL of the text. | 3438 * "len_arg" includes the NUL of the text. |
3439 * When "copy" is TRUE copy the text into allocated memory, otherwise | |
3440 * "line_arg" must be allocated and will be consumed here. | |
3412 */ | 3441 */ |
3413 int | 3442 int |
3414 ml_replace_len( | 3443 ml_replace_len( |
3415 linenr_T lnum, | 3444 linenr_T lnum, |
3416 char_u *line_arg, | 3445 char_u *line_arg, |
3452 #endif | 3481 #endif |
3453 if (curbuf->b_ml.ml_line_lnum != lnum) | 3482 if (curbuf->b_ml.ml_line_lnum != lnum) |
3454 { | 3483 { |
3455 // another line is buffered, flush it | 3484 // another line is buffered, flush it |
3456 ml_flush_line(curbuf); | 3485 ml_flush_line(curbuf); |
3457 curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY; | |
3458 | 3486 |
3459 #ifdef FEAT_PROP_POPUP | 3487 #ifdef FEAT_PROP_POPUP |
3460 if (curbuf->b_has_textprop && !has_props) | 3488 if (curbuf->b_has_textprop && !has_props) |
3461 // Need to fetch the old line to copy over any text properties. | 3489 // Need to fetch the old line to copy over any text properties. |
3462 ml_get_buf(curbuf, lnum, TRUE); | 3490 ml_get_buf(curbuf, lnum, TRUE); |
3486 } | 3514 } |
3487 } | 3515 } |
3488 } | 3516 } |
3489 #endif | 3517 #endif |
3490 | 3518 |
3491 if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) // same line allocated | 3519 if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) |
3492 vim_free(curbuf->b_ml.ml_line_ptr); // free it | 3520 vim_free(curbuf->b_ml.ml_line_ptr); // free allocated line |
3493 | 3521 |
3494 curbuf->b_ml.ml_line_ptr = line; | 3522 curbuf->b_ml.ml_line_ptr = line; |
3495 curbuf->b_ml.ml_line_len = len; | 3523 curbuf->b_ml.ml_line_len = len; |
3496 curbuf->b_ml.ml_line_lnum = lnum; | 3524 curbuf->b_ml.ml_line_lnum = lnum; |
3497 curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; | 3525 curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; |
4062 } | 4090 } |
4063 vim_free(new_line); | 4091 vim_free(new_line); |
4064 | 4092 |
4065 entered = FALSE; | 4093 entered = FALSE; |
4066 } | 4094 } |
4067 | 4095 else if (buf->b_ml.ml_flags & ML_ALLOCATED) |
4096 vim_free(buf->b_ml.ml_line_ptr); | |
4097 | |
4098 buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); | |
4068 buf->b_ml.ml_line_lnum = 0; | 4099 buf->b_ml.ml_line_lnum = 0; |
4069 } | 4100 } |
4070 | 4101 |
4071 /* | 4102 /* |
4072 * create a new, empty, data block | 4103 * create a new, empty, data block |