What happens
A PNG with large dimensions but a small file size makes the mock raise an uncaught PIL.Image.DecompressionBombError instead of returning a response.
A 20000x20000 single-colour greyscale PNG compresses to 388 KB, so it passes the 2 MB file size checks, but decodes to 400 million pixels. Pillow refuses to open it: Image.open runs _decompression_bomb_check and raises once the pixel count exceeds twice Image.MAX_IMAGE_PIXELS, which is 178,956,970 pixels by default.
Both APIs are affected:
POST /targets -> UNCAUGHT DecompressionBombError Image size (400000000 pixels) exceeds limit of 178956970 pixels
POST /v1/query -> UNCAUGHT DecompressionBombError Image size (400000000 pixels) exceeds limit of 178956970 pixels
DecompressionBombError inherits from Exception, not from OSError, so the except OSError in _query_validators/image_validators.py::validate_image_is_image does not catch it, and neither does the except SyntaxError in _services_validators/image_validators.py::validate_image_integrity.
Through the requests and httpx backends the exception propagates out of the caller's requests.post. Through Flask and Docker it is a 500.
A consequence worth noting separately
validate_image_dimensions in src/mock_vws/_query_validators/image_validators.py checks:
max_width = 30000
max_height = 30000
Those limits are unreachable. Pillow raises at roughly 13,376 x 13,376 for a square image, so no image which would fail this check can ever be opened to be checked. The branch is dead code, and the mock therefore has no working maximum dimension check at all.
Why it matters
Real Vuforia returns a documented result code here rather than failing to respond. Anyone whose test suite feeds the mock a generated or fuzzed image, or a legitimately large scan, gets an exception from their HTTP client rather than the error response their code is written to handle — which is the specific thing a mock exists to let them test.
Suggested resolution
Catch Image.DecompressionBombError alongside the exceptions already handled in the image validators for both APIs, and return whatever real Vuforia returns for an oversized image. That needs checking against a real database to decide between BadImage and ImageTooLarge, and against the Query API for its own equivalent, so this wants a verified fake test rather than a guess.
The dimension limits then need revisiting. Either raise Image.MAX_IMAGE_PIXELS inside the mock so that the documented 30000 x 30000 limit becomes reachable and is genuinely enforced, or lower the mock's limit to something Pillow can actually reach and record the difference in docs/source/differences-to-vws.rst. Leaving an unreachable constant in place is the one option worth ruling out.
What happens
A PNG with large dimensions but a small file size makes the mock raise an uncaught
PIL.Image.DecompressionBombErrorinstead of returning a response.A 20000x20000 single-colour greyscale PNG compresses to 388 KB, so it passes the 2 MB file size checks, but decodes to 400 million pixels. Pillow refuses to open it:
Image.openruns_decompression_bomb_checkand raises once the pixel count exceeds twiceImage.MAX_IMAGE_PIXELS, which is 178,956,970 pixels by default.Both APIs are affected:
DecompressionBombErrorinherits fromException, not fromOSError, so theexcept OSErrorin_query_validators/image_validators.py::validate_image_is_imagedoes not catch it, and neither does theexcept SyntaxErrorin_services_validators/image_validators.py::validate_image_integrity.Through the
requestsandhttpxbackends the exception propagates out of the caller'srequests.post. Through Flask and Docker it is a 500.A consequence worth noting separately
validate_image_dimensionsinsrc/mock_vws/_query_validators/image_validators.pychecks:Those limits are unreachable. Pillow raises at roughly 13,376 x 13,376 for a square image, so no image which would fail this check can ever be opened to be checked. The branch is dead code, and the mock therefore has no working maximum dimension check at all.
Why it matters
Real Vuforia returns a documented result code here rather than failing to respond. Anyone whose test suite feeds the mock a generated or fuzzed image, or a legitimately large scan, gets an exception from their HTTP client rather than the error response their code is written to handle — which is the specific thing a mock exists to let them test.
Suggested resolution
Catch
Image.DecompressionBombErroralongside the exceptions already handled in the image validators for both APIs, and return whatever real Vuforia returns for an oversized image. That needs checking against a real database to decide betweenBadImageandImageTooLarge, and against the Query API for its own equivalent, so this wants a verified fake test rather than a guess.The dimension limits then need revisiting. Either raise
Image.MAX_IMAGE_PIXELSinside the mock so that the documented 30000 x 30000 limit becomes reachable and is genuinely enforced, or lower the mock's limit to something Pillow can actually reach and record the difference indocs/source/differences-to-vws.rst. Leaving an unreachable constant in place is the one option worth ruling out.