changeset 6915:52e756b40a2b

diffs: do check of cut_off_limit on the raw diff before any parsing and allocation This redefines the exact meaning of cut_off_limit but it will still be approximately the same thing. It makes it more a limitation of what amount of work should be done, more than how much html should be outputted. It could make sense to push the limit further back to vcs to also prevent computing or allocating memory for huge diffs.
author Mads Kiilerich <mads@kiilerich.com>
date Tue, 03 Oct 2017 00:14:40 +0200
parents e85f08375dc6
children 182570502b6a
files kallithea/lib/diffs.py
diffstat 1 files changed, 12 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/lib/diffs.py	Tue Oct 03 00:14:40 2017 +0200
+++ b/kallithea/lib/diffs.py	Tue Oct 03 00:14:40 2017 +0200
@@ -137,10 +137,6 @@
 BIN_FILENODE = 7
 
 
-class DiffLimitExceeded(Exception):
-    pass
-
-
 class DiffProcessor(object):
     """
     Give it a unified or git diff and it returns a list of the files that were
@@ -204,24 +200,15 @@
         self._diff = diff
         self.adds = 0
         self.removes = 0
-        # calculate diff size
         self.diff_limit = diff_limit
-        self.cur_diff_size = 0
         self.limited_diff = False
         self.vcs = vcs
         self.parsed = self._parse_gitdiff(inline_diff=inline_diff)
 
     def _escaper(self, string):
         """
-        Do HTML escaping/markup and check the diff limit
+        Do HTML escaping/markup
         """
-        self.cur_diff_size += len(string)
-
-        # escaper gets iterated on each .next() call and it checks if each
-        # parsed line doesn't exceed the diff limit
-        if self.diff_limit is not None and self.cur_diff_size > self.diff_limit:
-            raise DiffLimitExceeded('Diff Limit Exceeded')
-
         def substitute(m):
             groups = m.groups()
             if groups[0]:
@@ -304,6 +291,10 @@
         starts.append(len(self._diff))
 
         for start, end in zip(starts, starts[1:]):
+            if self.diff_limit and end > self.diff_limit:
+                self.limited_diff = True
+                continue
+
             head, diff_lines = self._get_header(buffer(self._diff, start, end - start))
 
             op = None
@@ -363,18 +354,13 @@
 
             # a real non-binary diff
             if head['a_file'] or head['b_file']:
-                try:
-                    chunks, added, deleted = self._parse_lines(diff_lines)
-                    stats['binary'] = False
-                    stats['added'] = added
-                    stats['deleted'] = deleted
-                    # explicit mark that it's a modified file
-                    if op == 'M':
-                        stats['ops'][MOD_FILENODE] = 'modified file'
-
-                except DiffLimitExceeded:
-                    self.limited_diff = True
-                    break
+                chunks, added, deleted = self._parse_lines(diff_lines)
+                stats['binary'] = False
+                stats['added'] = added
+                stats['deleted'] = deleted
+                # explicit mark that it's a modified file
+                if op == 'M':
+                    stats['ops'][MOD_FILENODE] = 'modified file'
             else:  # Git binary patch (or empty diff)
                 # Git binary patch
                 if head['bin_patch']: