Skip to content

Commit 6ef2739

Browse files
committed
fix(RemoteProgress): improve message sanitization
Don't allow `, ` prefixes or suffixes in messages. Fixes #438
1 parent b6a6a10 commit 6ef2739

File tree

3 files changed

+22
-10
lines changed

3 files changed

+22
-10
lines changed

doc/source/changes.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ Changelog
77

88
* Fix: bug in ``git-blame --incremental`` output parser that broken when
99
commit messages contained ``\r`` characters
10-
* Fix: progress handler exceptions are not caught anymore, which would
11-
usually just hide bugs previously.
12-
* Fix: The ``Git.execute`` method will now redirect ``stdout`` to
13-
``devnull`` if ``with_stdout`` is false, which is the intended behaviour
14-
based on the parameter's documentation.
10+
* Fix: progress handler exceptions are not caught anymore, which would usually just hide bugs
11+
previously.
12+
* Fix: The `Git.execute` method will now redirect `stdout` to `devnull` if `with_stdout` is false,
13+
which is the intended behaviour based on the parameter's documentation.
14+
* Fix: `RemoteProgress` will now strip the ', ' prefix or suffix from messages.
1515

1616
2.0.2 - Fixes
1717
=============

git/test/test_remote.py

+8
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ def update(self, op_code, cur_count, max_count=None, message=''):
6262
# check each stage only comes once
6363
op_id = op_code & self.OP_MASK
6464
assert op_id in (self.COUNTING, self.COMPRESSING, self.WRITING)
65+
66+
if op_code & self.WRITING > 0:
67+
if op_code & self.BEGIN > 0:
68+
assert not message, 'should not have message when remote begins writing'
69+
elif op_code & self.END > 0:
70+
assert message
71+
assert not message.startswith(', '), "Sanitize progress messages: '%s'" % message
72+
assert not message.endswith(', '), "Sanitize progress messages: '%s'" % message
6573

6674
self._stages_per_op.setdefault(op_id, 0)
6775
self._stages_per_op[op_id] = self._stages_per_op[op_id] | (op_code & self.STAGE_MASK)

git/util.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,16 @@ class RemoteProgress(object):
171171
STAGE_MASK = BEGIN | END
172172
OP_MASK = ~STAGE_MASK
173173

174+
DONE_TOKEN = 'done.'
175+
TOKEN_SEPARATOR = ', '
176+
174177
__slots__ = ("_cur_line", "_seen_ops")
175-
re_op_absolute = re.compile("(remote: )?([\w\s]+):\s+()(\d+)()(.*)")
176-
re_op_relative = re.compile("(remote: )?([\w\s]+):\s+(\d+)% \((\d+)/(\d+)\)(.*)")
178+
re_op_absolute = re.compile(r"(remote: )?([\w\s]+):\s+()(\d+)()(.*)")
179+
re_op_relative = re.compile(r"(remote: )?([\w\s]+):\s+(\d+)% \((\d+)/(\d+)\)(.*)")
177180

178181
def __init__(self):
179182
self._seen_ops = list()
183+
self._cur_line = None
180184

181185
def _parse_progress_line(self, line):
182186
"""Parse progress information from the given line as retrieved by git-push
@@ -257,11 +261,11 @@ def _parse_progress_line(self, line):
257261
# END message handling
258262

259263
message = message.strip()
260-
done_token = ', done.'
261-
if message.endswith(done_token):
264+
if message.endswith(self.DONE_TOKEN):
262265
op_code |= self.END
263-
message = message[:-len(done_token)]
266+
message = message[:-len(self.DONE_TOKEN)]
264267
# END end message handling
268+
message = message.strip(self.TOKEN_SEPARATOR)
265269

266270
self.update(op_code,
267271
cur_count and float(cur_count),

0 commit comments

Comments
 (0)