[前][次][番号順一覧][スレッド一覧]

ruby-changes:55959

From: Nobuyoshi <ko1@a...>
Date: Sun, 2 Jun 2019 22:58:42 +0900 (JST)
Subject: [ruby-changes:55959] Nobuyoshi Nakada: f4b060d8d7 (trunk): Check conditional nestings in INPUTRC

https://git.ruby-lang.org/ruby.git/commit/?id=f4b060d8d7

From f4b060d8d7f927306cbbe24df888a09112acd4c8 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Sun, 2 Jun 2019 12:14:29 +0900
Subject: Check conditional nestings in INPUTRC

Closes: https://github.com/ruby/ruby/pull/2222

diff --git a/lib/reline/config.rb b/lib/reline/config.rb
index 7c51535..1415a39 100644
--- a/lib/reline/config.rb
+++ b/lib/reline/config.rb
@@ -5,6 +5,10 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L5
 
   DEFAULT_PATH = '~/.inputrc'
 
+  class InvalidInputrc < RuntimeError
+    attr_accessor :file, :lineno
+  end
+
   VARIABLE_NAMES = %w{
     bind-tty-special-chars
     blink-matching-paren
@@ -41,7 +45,7 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L45
     @additional_key_bindings = {} # from inputrc
     @default_key_bindings = {} # environment-dependent
     @skip_section = nil
-    @if_stack = []
+    @if_stack = nil
     @editing_mode_label = :emacs
     @keymap_label = :emacs
     @key_actors = {}
@@ -89,8 +93,11 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L93
       return nil
     end
 
-    read_lines(lines)
+    read_lines(lines, file)
     self
+  rescue InvalidInputrc => e
+    warn e.message
+    nil
   end
 
   def key_bindings
@@ -106,13 +113,19 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L113
     @default_key_bindings = {}
   end
 
-  def read_lines(lines)
-    lines.each do |line|
+  def read_lines(lines, file = nil)
+    conditions = [@skip_section, @if_stack]
+    @skip_section = nil
+    @if_stack = []
+
+    lines.each_with_index do |line, no|
       next if line.start_with?('#')
 
+      no += 1
+
       line = line.chomp.gsub(/^\s*/, '')
       if line[0, 1] == '$'
-        handle_directive(line[1..-1])
+        handle_directive(line[1..-1], file, no)
         next
       end
 
@@ -130,9 +143,14 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L143
         @additional_key_bindings[keystroke] = func
       end
     end
+    unless @if_stack.empty?
+      raise InvalidInputrc, "#{file}:#{@if_stack.last[1]}: unclosed if"
+    end
+  ensure
+    @skip_section, @if_stack = conditions
   end
 
-  def handle_directive(directive)
+  def handle_directive(directive, file, no)
     directive, args = directive.split(' ')
     case directive
     when 'if'
@@ -145,17 +163,18 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L163
         condition = true if args == 'Ruby'
         condition = true if args == 'Reline'
       end
-      unless @skip_section.nil?
-        @if_stack << @skip_section
-      end
+      @if_stack << [file, no, @skip_section]
       @skip_section = !condition
     when 'else'
+      if @if_stack.empty?
+        raise InvalidInputrc, "#{file}:#{no}: unmatched else"
+      end
       @skip_section = !@skip_section
     when 'endif'
-      @skip_section = nil
-      unless @if_stack.empty?
-        @skip_section = @if_stack.pop
+      if @if_stack.empty?
+        raise InvalidInputrc, "#{file}:#{no}: unmatched endif"
       end
+      @skip_section = @if_stack.pop
     when 'include'
       read(args)
     end
diff --git a/test/reline/test_config.rb b/test/reline/test_config.rb
index d6f1ce5..c00c4f8 100644
--- a/test/reline/test_config.rb
+++ b/test/reline/test_config.rb
@@ -117,6 +117,33 @@ class Reline::Config::Test < Reline::TestCase https://github.com/ruby/ruby/blob/trunk/test/reline/test_config.rb#L117
     end
   end
 
+  def test_unclosed_if
+    e = assert_raise(Reline::Config::InvalidInputrc) do
+      @config.read_lines(<<~LINES.split(/(?<=\n)/), "INPUTRC")
+        $if Ruby
+      LINES
+    end
+    assert_equal "INPUTRC:1: unclosed if", e.message
+  end
+
+  def test_unmatched_else
+    e = assert_raise(Reline::Config::InvalidInputrc) do
+      @config.read_lines(<<~LINES.split(/(?<=\n)/), "INPUTRC")
+        $else
+      LINES
+    end
+    assert_equal "INPUTRC:1: unmatched else", e.message
+  end
+
+  def test_unmatched_endif
+    e = assert_raise(Reline::Config::InvalidInputrc) do
+      @config.read_lines(<<~LINES.split(/(?<=\n)/), "INPUTRC")
+        $endif
+      LINES
+    end
+    assert_equal "INPUTRC:1: unmatched endif", e.message
+  end
+
   def test_default_key_bindings
     @config.add_default_key_binding('abcd'.bytes, 'EFGH'.bytes)
     @config.read_lines(<<~'LINES'.split(/^/))
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]