-
Notifications
You must be signed in to change notification settings - Fork 31
Description
Description
When the validate_video_file() function encounters a validation error (empty file or file too large), it raises an exception without resetting the file pointer back to position 0. This leaves the file object's read pointer at the end of the file (EOF), making the file unusable for any subsequent operations.
What Happens
Current Code Flow:
pythondef validate_video_file(file):
file.seek(0, 2) # Move pointer to END of file
file_size = file.tell() # Get size
file.seek(0) # Reset to START - BUT this only runs if no exception is raised
if file_size == 0:
raise BadRequestError("Video file is empty") # ❌ File pointer stuck at EOF!
if file_size > MAX_FILE_SIZE:
raise PayloadTooLargeError(...) # ❌ File pointer stuck at EOF!
The Problem:
Function moves file pointer to the end to calculate size
If validation fails, it raises an exception immediately
The file.seek(0) line is never executed
File pointer remains at EOF position
Any code that catches the exception and tries to use the file will get empty reads
Concrete Example
python# Upload a file that's too large
large_video = FileStorage(stream=open('101MB_video.mp4', 'rb'), filename='video.mp4')
try:
validate_video_file(large_video)
except PayloadTooLargeError as e:
# Exception is caught, let's try to save first 1KB for debugging
print(f"Error occurred: {e.message}")
# Try to read the file to log its header
header = large_video.read(1024)
print(f"File header length: {len(header)}")
# Output: 0 ❌ - Expected: 1024
# Check pointer position
print(f"File pointer at: {large_video.tell()}")
# Output: 105906176 (at end) ❌ - Expected: 0 or 1024
Why This Is a Problem
-
Breaks Error Recovery Logic
pythondef upload_handler(request):
video = validate_upload_request(request)
try:
validate_video_file(video)
except PayloadTooLargeError:
# Maybe we want to try compressing it?
compressed = compress_video(video) # ❌ Will read 0 bytes!
return compressed -
Prevents Debugging
pythontry:
validate_video_file(uploaded_file)
except BadRequestError as e:Log the first 100 bytes for debugging
sample = uploaded_file.read(100) # ❌ Returns empty bytes!
logger.error(f"Validation failed. File sample: {sample}") -
Breaks Cleanup Operations
pythontry:
validate_video_file(video)
except Exception as e:Check if file is actually corrupted
video.seek(0) # Manual reset needed ❌
magic_bytes = video.read(4)
if magic_bytes != b'\x00\x00\x00\x1c': # Check MP4 signature
handle_corrupted_file() -
Causes Silent Failures in Tests
pythondef test_file_too_large():
large_file = create_mock_file(size=10110241024)with pytest.raises(PayloadTooLargeError):
validate_video_file(large_file)Later in test, try to verify file wasn't modified
content = large_file.read() # ❌ Returns empty, test gives false positive!
assert len(content) > 0 # Fails unexpectedly
Root Cause
The file.seek(0) reset statement is placed after the validation checks instead of being guaranteed to execute via a try-finally block or by resetting immediately after getting the size.
Expected Behavior
After validate_video_file() completes (whether successfully or with an exception), the file pointer should always be at position 0, allowing the calling code to:
Read the file contents
Retry the operation
Perform alternative processing
Log file samples for debugging
Actual Behavior
When validation fails, the file pointer is left at EOF (end of file), making subsequent read operations return empty data.
Impact
Severity: High - Breaks error handling and recovery logic
Affected Operations: Any code that catches validation exceptions and attempts to use the file
User Impact: Silent failures, inability to implement retry logic, poor debugging experience.
Please assign this issue to me @shupandee
Screenshots
