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