Spreadsheet import: a cell over 128 KiB, often from a stray quote, gives a server error #462

Closed
opened 2026-10-01 10:46:52 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading core/csv_import.read_sheet and feeding it an oversized field.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at core/csv_import.py:459-461 (read_sheet); core/views_import.py and the management command have not moved, and the same call still raises _csv.Error.

read_sheet iterates Python's csv.reader without catching csv.Error. The reader raises field larger than field limit (131072) when one field passes 128 KiB. An unmatched double quote early in a large file does exactly that, because everything after it is read as one field. csv.Error is not a SheetError, so the upload view answers with a server error instead of saying the file could not be read.

  • Where: core/csv_import.py:455-457 (read_sheet); core/views_import.py:28-32, which catches only csv_import.SheetError; core/management/commands/import_csv.py:50-53, which catches only OSError and SheetError.
  • What happens: read_sheet(b'Company,Role\nAcme,"' + b'x' * 200000 + b'"\n') raises _csv.Error, which is neither a SheetError nor a ValueError. Uploaded through Import → Spreadsheet, a 300 KB export whose notes cell has an unmatched quote gets a 500 page. The management command prints a traceback. A small file with the same stray quote does not fail, because the rest of it stays under the limit.
  • Why it matters: the person gets no hint about what is wrong with their file, and the log records an unhandled exception for what is ordinary bad input.
  • Fix: wrap the reading in try / except csv.Error and raise a SheetError with a translated message that names the likely cause (a quotation mark that is never closed).

Done when

  • A test in tests/test_csv_import.py calls read_sheet with a field over 131,072 characters and expects SheetError, and a view test expects a redirect with the message rather than a 500.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading `core/csv_import.read_sheet` and feeding it an oversized field. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `core/csv_import.py:459-461` (`read_sheet`); `core/views_import.py` and the management command have not moved, and the same call still raises `_csv.Error`. `read_sheet` iterates Python's `csv.reader` without catching `csv.Error`. The reader raises `field larger than field limit (131072)` when one field passes 128 KiB. An unmatched double quote early in a large file does exactly that, because everything after it is read as one field. `csv.Error` is not a `SheetError`, so the upload view answers with a server error instead of saying the file could not be read. - **Where:** `core/csv_import.py:455-457` (`read_sheet`); `core/views_import.py:28-32`, which catches only `csv_import.SheetError`; `core/management/commands/import_csv.py:50-53`, which catches only `OSError` and `SheetError`. - **What happens:** `read_sheet(b'Company,Role\nAcme,"' + b'x' * 200000 + b'"\n')` raises `_csv.Error`, which is neither a `SheetError` nor a `ValueError`. Uploaded through Import → Spreadsheet, a 300 KB export whose notes cell has an unmatched quote gets a 500 page. The management command prints a traceback. A small file with the same stray quote does not fail, because the rest of it stays under the limit. - **Why it matters:** the person gets no hint about what is wrong with their file, and the log records an unhandled exception for what is ordinary bad input. - **Fix:** wrap the reading in `try` / `except csv.Error` and raise a `SheetError` with a translated message that names the likely cause (a quotation mark that is never closed). ## Done when - A test in `tests/test_csv_import.py` calls `read_sheet` with a field over 131,072 characters and expects `SheetError`, and a view test expects a redirect with the message rather than a 500.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:46:52 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#462
No description provided.