Django

Code

Show
Ignore:
Timestamp:
07/14/08 00:04:57 (6 months ago)
Author:
brosner
Message:

newforms-admin: Merged from trunk up to [7917].

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/newforms-admin

    • Property svnmerge-integrated changed from /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7880 to /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7921
  • django/branches/newforms-admin/django/http/multipartparser.py

    r7881 r7922  
    271271        self._leftover = '' 
    272272        self.length = length 
    273         self._position = 0 
     273        self.position = 0 
    274274        self._remaining = length 
    275  
    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. 
    282  
    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 
     275        self._unget_history = [] 
    291276 
    292277    def tell(self): 
     
    330315        else: 
    331316            output = self._producer.next() 
     317            self._unget_history = [] 
    332318        self.position += len(output) 
    333319        return output 
     
    352338        stream position and thus tell() will be rewound. 
    353339        """ 
     340        if not bytes: 
     341            return 
     342        self._update_unget_history(len(bytes)) 
    354343        self.position -= len(bytes) 
    355344        self._leftover = ''.join([bytes, self._leftover]) 
    356345 
    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." 
    368                 ) 
    369  
    370         self._position = value 
    371  
    372     position = property(lambda self: self._position, _set_position) 
     346    def _update_unget_history(self, num_bytes): 
     347        """ 
     348        Updates the unget history as a sanity check to see if we've pushed 
     349        back the same number of bytes in one chunk. If we keep ungetting the 
     350        same number of bytes many times (here, 50), we're mostly likely in an 
     351        infinite loop of some sort. This is usually caused by a 
     352        maliciously-malformed MIME request. 
     353        """ 
     354        self._unget_history = [num_bytes] + self._unget_history[:49] 
     355        number_equal = len([current_number for current_number in self._unget_history 
     356                            if current_number == num_bytes]) 
     357 
     358        if number_equal > 40: 
     359            raise SuspiciousOperation( 
     360                "The multipart parser got stuck, which shouldn't happen with" 
     361                " normal uploaded files. Check for malicious upload activity;" 
     362                " if there is none, report this to the Django developers." 
     363            ) 
    373364 
    374365class ChunkIter(object):