summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/redmine/scm/adapters/mercurial_adapter.rb15
-rw-r--r--test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb19
2 files changed, 34 insertions, 0 deletions
diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb
index 064849f94..2c7121356 100644
--- a/lib/redmine/scm/adapters/mercurial_adapter.rb
+++ b/lib/redmine/scm/adapters/mercurial_adapter.rb
@@ -32,6 +32,8 @@ module Redmine
# raised if hg command exited with error, e.g. unknown revision.
class HgCommandAborted < CommandFailed; end
+ # raised if bad command argument detected before executing hg.
+ class HgCommandArgumentError < CommandFailed; end
class << self
def client_command
@@ -286,8 +288,21 @@ module Redmine
end
end
+ # command options which may be processed earlier, by faulty parser in hg
+ HG_EARLY_BOOL_ARG = /^--(debugger|profile|traceback)$/
+ HG_EARLY_LIST_ARG = /^(--(config|cwd|repo(sitory)?)\b|-R)/
+ private_constant :HG_EARLY_BOOL_ARG, :HG_EARLY_LIST_ARG
+
# Runs 'hg' command with the given args
def hg(*args, &block)
+ # as of hg 4.4.1, early parsing of bool options is not terminated at '--'
+ if args.any? { |s| s =~ HG_EARLY_BOOL_ARG }
+ raise HgCommandArgumentError, "malicious command argument detected"
+ end
+ if args.take_while { |s| s != '--' }.any? { |s| s =~ HG_EARLY_LIST_ARG }
+ raise HgCommandArgumentError, "malicious command argument detected"
+ end
+
repo_path = root_url || url
full_args = ['-R', repo_path, '--encoding', 'utf-8']
full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}"
diff --git a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
index 0512cc74c..e0458ce55 100644
--- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
@@ -21,6 +21,7 @@ class MercurialAdapterTest < ActiveSupport::TestCase
HELPERS_DIR = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
TEMPLATE_NAME = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
+ HgCommandArgumentError = Redmine::Scm::Adapters::MercurialAdapter::HgCommandArgumentError
REPOSITORY_PATH = repository_path('mercurial')
CHAR_1_HEX = "\xc3\x9c"
@@ -443,6 +444,24 @@ class MercurialAdapterTest < ActiveSupport::TestCase
assert_equal "UTF-8", adpt2.path_encoding
end
+ def test_bad_early_options
+ assert_raise HgCommandArgumentError do
+ @adapter.diff('sources/welcome_controller.rb', '--config=alias.rhdiff=!xterm')
+ end
+ assert_raise HgCommandArgumentError do
+ @adapter.entries('--debugger')
+ end
+ assert_raise HgCommandArgumentError do
+ @adapter.revisions(nil, nil, nil, limit: '--repo=otherrepo')
+ end
+ assert_raise HgCommandArgumentError do
+ @adapter.nodes_in_branch('default', limit: '--repository=otherrepo')
+ end
+ assert_raise HgCommandArgumentError do
+ @adapter.nodes_in_branch('-Rotherrepo')
+ end
+ end
+
private
def test_hgversion_for(hgversion, version)