Skip to content

File Pointer Not Reset After Size Check in validate_video_file #85

@shupandee

Description

@shupandee

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

  1. 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

  2. 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}")

  3. 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()

  4. 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

Image Image Image

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions