Ticket #7635: multipartparser_recusion_check.diff

File multipartparser_recusion_check.diff, 3.5 KB (added by Michael Axiak, 16 years ago)

Different way to check recursion

  • django/http/multipartparser.py

     
    270270        self._empty = False
    271271        self._leftover = ''
    272272        self.length = length
    273         self._position = 0
     273        self.position = 0
    274274        self._remaining = length
    275275
    276         # These fields are to do sanity checking to make sure we don't
    277         # have infinite loops getting/ungetting from the stream. The
    278         # purpose overall is to raise an exception if we perform lots
    279         # of stream get/unget gymnastics without getting
    280         # anywhere. Naturally this is not sound, but most probably
    281         # would indicate a bug if the exception is raised.
     276        # This field does some sanity checking to see if we have
     277        # pushed back the same number of bytes
     278        # in one chunk.
     279        # If we unget the same number of bytes a lot of times,
     280        # we're most likely in an infinite loop of some sort.
     281        self._unget_history = []
    282282
    283         # largest position tell us how far this lazystream has ever
    284         # been advanced
    285         self._largest_position = 0
    286 
    287         # "modifications since" will start at zero and increment every
    288         # time the position is modified but a new largest position is
    289         # not achieved.
    290         self._modifications_since = 0
    291 
    292283    def tell(self):
    293284        return self.position
    294285
     
    329320            self._leftover = ''
    330321        else:
    331322            output = self._producer.next()
     323            self._unget_history = []
    332324        self.position += len(output)
    333325        return output
    334326
     
    351343        Future calls to read() will return those bytes first. The
    352344        stream position and thus tell() will be rewound.
    353345        """
     346        if not bytes:
     347            return
     348        self._update_unget_history(len(bytes))
    354349        self.position -= len(bytes)
    355350        self._leftover = ''.join([bytes, self._leftover])
    356351
    357     def _set_position(self, value):
    358         if value > self._largest_position:
    359             self._modifications_since = 0
    360             self._largest_position = value
    361         else:
    362             self._modifications_since += 1
    363             if self._modifications_since > 500:
    364                 raise SuspiciousOperation(
    365                     "The multipart parser got stuck, which shouldn't happen with"
    366                     " normal uploaded files. Check for malicious upload activity;"
    367                     " if there is none, report this to the Django developers."
     352    def _update_unget_history(self, num_bytes):
     353        """
     354        Updates the unget history .. storing 50 previous ungets
     355        to make sure that they are different enough.
     356        """
     357        self._unget_history = [num_bytes] + self._unget_history[:49]
     358        number_equal = len([current_number for current_number in self._unget_history
     359                            if current_number == num_bytes])
     360
     361        if number_equal > 40:
     362            raise SuspiciousOperation(
     363                "The multipart parser got stuck, which shouldn't happen with"
     364                " normal uploaded files. Check for malicious upload activity;"
     365                " if there is none, report this to the Django developers."
    368366                )
    369367
    370         self._position = value
    371 
    372     position = property(lambda self: self._position, _set_position)
    373 
    374368class ChunkIter(object):
    375369    """
    376370    An iterable that will yield chunks of data. Given a file-like object as the
Back to Top