From 3d7a11a676c57e6d75599572a2a4268b4b4f29dd Mon Sep 17 00:00:00 2001 From: Owen Stephens Date: Tue, 9 Oct 2018 13:24:55 +0100 Subject: [PATCH] Gracefully handle (ignore) null bytes in history lines Fixes #1789. Readline is unable to add lines to its history that contain a null byte; we should therefore avoid saving such lines to the history file, and ignore any such lines that are already present in the file. --- lib/pry/history.rb | 12 +++++++++++- spec/history_spec.rb | 8 +++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/pry/history.rb b/lib/pry/history.rb index 16dd2656..b40dac50 100644 --- a/lib/pry/history.rb +++ b/lib/pry/history.rb @@ -34,6 +34,8 @@ class Pry # @return [Integer] The number of lines loaded def load @loader.call do |line| + next if invalid_readline_line?(line) + @pusher.call(line.chomp) @history << line.chomp @original_lines += 1 @@ -44,7 +46,9 @@ class Pry # @param [String] line # @return [String] The same line that was passed in def push(line) - unless line.empty? || (@history.last && line == @history.last) + empty_or_invalid_line = line.empty? || invalid_readline_line?(line) + + unless empty_or_invalid_line || (@history.last && line == @history.last) @pusher.call(line) @history << line if !should_ignore?(line) && Pry.config.history.should_save @@ -144,5 +148,11 @@ class Pry def history_file_path File.expand_path(@file_path || Pry.config.history.file) end + + def invalid_readline_line?(line) + # `Readline::HISTORY << line` raises an `ArgumentError` if `line` + # includes a null byte + line.include?("\0") + end end end diff --git a/spec/history_spec.rb b/spec/history_spec.rb index d506da5a..fa9d7522 100644 --- a/spec/history_spec.rb +++ b/spec/history_spec.rb @@ -5,7 +5,7 @@ describe Pry do before do Pry.history.clear - @saved_history = "1\n2\n3\n" + @saved_history = "1\n2\n3\ninvalid\0 line\n" Pry.history.loader = proc do |&blk| @saved_history.lines.each { |l| blk.call(l) } @@ -28,6 +28,12 @@ describe Pry do expect(Pry.history.to_a.grep('_ += 1').count).to eq 1 end + it "does not record lines that contain a NULL byte" do + c = Pry.history.to_a.count + Pry.history << "a\0b" + expect(Pry.history.to_a.count).to eq c + end + it "does not record empty lines" do c = Pry.history.to_a.count Pry.history << ''