| 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 = [] |
| 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." |