view runtime/indent/make.vim @ 33815:08f9e1eac4cf v9.0.2123

patch 9.0.2123: Problem with initializing the length of range() lists Commit: https://github.com/vim/vim/commit/df63da98d8dc284b1c76cfe1b17fa0acbd6094d8 Author: Christian Brabandt <cb@256bit.org> Date: Thu Nov 23 20:14:28 2023 +0100 patch 9.0.2123: Problem with initializing the length of range() lists Problem: Problem with initializing the length of range() lists Solution: Set length explicitly when it shouldn't contain any items range() may cause a wrong calculation of list length, which may later then cause a segfault in list_find(). This is usually not a problem, because range_list_materialize() calculates the length, when it materializes the list. In addition, in list_find() when the length of the range was wrongly initialized, it may seem to be valid, so the check for list index out-of-bounds will not be true, because it is called before the list is actually materialized. And so we may eventually try to access a null pointer, causing a segfault. So this patch does 3 things: - In f_range(), when we know that the list should be empty, explicitly set the list->lv_len value to zero. This should happen, when start is larger than end (in case the stride is positive) or end is larger than start when the stride is negative. This should fix the underlying issue properly. However, - as a safety measure, let's check that the requested index is not out of range one more time, after the list has been materialized and return NULL in case it suddenly is. - add a few more tests to verify the behaviour. fixes: #13557 closes: #13563 Co-authored-by: Tim Pope <tpope@github.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 23 Nov 2023 20:30:07 +0100
parents 6dd88e45d47d
children
line wrap: on
line source

" Vim indent file
" Language:		Makefile
" Maintainer:		Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer:	Nikolai Weibull <now@bitwi.se>
" Last Change:		2022 Apr 06

if exists("b:did_indent")
  finish
endif
let b:did_indent = 1

setlocal indentexpr=GetMakeIndent()
setlocal indentkeys=!^F,o,O,<:>,=else,=endif
setlocal nosmartindent

let b:undo_indent = "setl inde< indk< si<"

if exists("*GetMakeIndent")
  finish
endif

let s:comment_rx = '^\s*#'
let s:rule_rx = '^[^ \t#:][^#:]*:\{1,2}\%([^=:]\|$\)'
let s:continued_rule_rx = '^[^#:]*:\{1,2}\%([^=:]\|$\)'
let s:continuation_rx = '\\$'
let s:assignment_rx = '^\s*\h\w*\s*[+:?]\==\s*\zs.*\\$'
let s:folded_assignment_rx = '^\s*\h\w*\s*[+:?]\=='
" TODO: This needs to be a lot more restrictive in what it matches.
let s:just_inserted_rule_rx = '^\s*[^#:]\+:\{1,2}$'
let s:conditional_directive_rx = '^ *\%(ifn\=\%(eq\|def\)\|else\)\>'
let s:end_conditional_directive_rx = '^\s*\%(else\|endif\)\>'

function s:remove_continuation(line)
  return substitute(a:line, s:continuation_rx, "", "")
endfunction

function GetMakeIndent()
  " TODO: Should this perhaps be v:lnum -1?
"  let prev_lnum = prevnonblank(v:lnum - 1)
  let prev_lnum = v:lnum - 1
  if prev_lnum == 0
    return 0
  endif
  let prev_line = getline(prev_lnum)

  let prev_prev_lnum = prev_lnum - 1
  let prev_prev_line = prev_prev_lnum != 0 ? getline(prev_prev_lnum) : ""

  " TODO: Deal with comments.  In comments, continuations aren't interesting.
  if prev_line =~ s:continuation_rx
    if prev_prev_line =~ s:continuation_rx
      return indent(prev_lnum)
    elseif prev_line =~ s:rule_rx
      return shiftwidth()
    elseif prev_line =~ s:assignment_rx
      call cursor(prev_lnum, 1)
      if search(s:assignment_rx, 'W') != 0
        return virtcol('.') - 1
      else
        " TODO: ?
        return shiftwidth()
      endif
    else
      " TODO: OK, this might be a continued shell command, so perhaps indent
      " properly here?  Leave this out for now, but in the next release this
      " should be using indent/sh.vim somehow.
      "if prev_line =~ '^\t' " s:rule_command_rx
      "  if prev_line =~ '^\s\+[@-]\%(if\)\>'
      "    return indent(prev_lnum) + 2
      "  endif
      "endif
      return indent(prev_lnum) + shiftwidth()
    endif
  elseif prev_prev_line =~ s:continuation_rx
    let folded_line = s:remove_continuation(prev_prev_line) . ' ' . s:remove_continuation(prev_line)
    let lnum = prev_prev_lnum - 1
    let line = getline(lnum)
    while line =~ s:continuation_rx
      let folded_line = s:remove_continuation(line) . ' ' . folded_line
      let lnum -= 1
      let line = getline(lnum)
    endwhile
    let folded_lnum = lnum + 1
    if folded_line =~ s:rule_rx
      if getline(v:lnum) =~ s:rule_rx
        return 0
      else
        return &ts
      endif
    else
"    elseif folded_line =~ s:folded_assignment_rx
      if getline(v:lnum) =~ s:rule_rx
        return 0
      else
        return indent(folded_lnum)
      endif
"    else
"      " TODO: ?
"      return indent(prev_lnum)
    endif
  elseif prev_line =~ s:rule_rx
    if getline(v:lnum) =~ s:rule_rx
      return 0
    else
      return &ts
    endif
  elseif prev_line =~ s:conditional_directive_rx
    return shiftwidth()
  else
    let line = getline(v:lnum)
    if line =~ s:just_inserted_rule_rx
      return 0
    elseif line =~ s:end_conditional_directive_rx
      return v:lnum - 1 == 0 ? 0 : indent(v:lnum - 1) - shiftwidth()
    else
      return v:lnum - 1 == 0 ? 0 : indent(v:lnum - 1)
    endif
  endif
endfunction