# HG changeset patch # User Floris Bruynooghe # Date 2019-09-29 22:01:58 # Node ID 2cc453284d5c473dc722c1cca1d4ea403fc5ebd2 # Parent d1d919f679f73668a40c0a1f9fb6d1f3223a0b83 patchbomb: protect email addresses from shell When patchbomb sends email via a sendmail-like program it invokes this using procutil.popen which passes the string to a shell to be parsed. To protect any special characters in the email addresses on the command line from being interpretered by the shell they must be quoted. diff --git a/mercurial/mail.py b/mercurial/mail.py --- a/mercurial/mail.py +++ b/mercurial/mail.py @@ -152,7 +152,8 @@ def _smtp(ui): def _sendmail(ui, sender, recipients, msg): '''send mail using sendmail.''' program = ui.config('email', 'method') - stremail = lambda x: stringutil.email(encoding.strtolocal(x)) + stremail = lambda x: ( + procutil.quote(stringutil.email(encoding.strtolocal(x)))) cmdline = '%s -f %s %s' % (program, stremail(sender), ' '.join(map(stremail, recipients))) ui.note(_('sending mail: %s\n') % cmdline) diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py --- a/mercurial/pycompat.py +++ b/mercurial/pycompat.py @@ -328,8 +328,11 @@ if ispy3: ret = shlex.split(s.decode('latin-1'), comments, posix) return [a.encode('latin-1') for a in ret] + shlexquote = shlex.quote + else: import cStringIO + import pipes xrange = xrange unicode = unicode @@ -393,6 +396,7 @@ else: sysplatform = sys.platform sysexecutable = sys.executable shlexsplit = shlex.split + shlexquote = pipes.quote bytesio = cStringIO.StringIO stringio = bytesio maplist = map diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -70,6 +70,7 @@ shellsplit = platform.shellsplit spawndetached = platform.spawndetached sshargs = platform.sshargs testpid = platform.testpid +quote = pycompat.shlexquote try: setprocname = osutil.setprocname diff --git a/tests/test-patchbomb.t b/tests/test-patchbomb.t --- a/tests/test-patchbomb.t +++ b/tests/test-patchbomb.t @@ -3035,6 +3035,47 @@ single rev sending [PATCH] test ... sending mail: $TESTTMP/t2/pretendmail.sh -f test foo +Shell characters in addresses + + $ hg email --date '1980-1-1 0:1' -v -t '~foo/bar@example.com' -f 'me*@example.com' -r '10' + this patch series consists of 1 patches. + + warning: invalid patchbomb.intro value "mpmwearaclownnose" + (should be one of always, never, auto) + -f me*@example.com ~foo/bar@example.com + MIME-Version: 1.0 + Content-Type: text/plain; charset="us-ascii" + Content-Transfer-Encoding: 7bit + Subject: [PATCH] dd + X-Mercurial-Node: 3b6f1ec9dde933a40a115a7990f8b320477231af + X-Mercurial-Series-Index: 1 + X-Mercurial-Series-Total: 1 + Message-Id: <3b6f1ec9dde933a40a11.315532860@test-hostname> + X-Mercurial-Series-Id: <3b6f1ec9dde933a40a11.315532860@test-hostname> + User-Agent: Mercurial-patchbomb/* (glob) + Date: Tue, 01 Jan 1980 00:01:00 +0000 + From: me*@example.com + To: ~foo/bar@example.com + + # HG changeset patch + # User test + # Date 5 0 + # Thu Jan 01 00:00:05 1970 +0000 + # Branch test + # Node ID 3b6f1ec9dde933a40a115a7990f8b320477231af + # Parent 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268 + dd + + diff -r 2f9fa9b998c5 -r 3b6f1ec9dde9 d + --- a/d Thu Jan 01 00:00:04 1970 +0000 + +++ b/d Thu Jan 01 00:00:05 1970 +0000 + @@ -1,1 +1,2 @@ + d + +d + + sending [PATCH] dd ... + sending mail: $TESTTMP/t2/pretendmail.sh -f 'me*@example.com' '~foo/bar@example.com' + Test pull url header =================================