Skip to content

fix(serde): raise catchable InvalidInputException instead of internal Buffer overflow on truncated/empty WKB (#866) - #867

Merged
Maxxen merged 1 commit into
duckdb:v1.5-variegatafrom
connerkup:fix/866-deserialize-zero-length-blob
Sep 10, 2026
Merged

fix(serde): raise catchable InvalidInputException instead of internal Buffer overflow on truncated/empty WKB (#866)#867
Maxxen merged 1 commit into
duckdb:v1.5-variegatafrom
connerkup:fix/866-deserialize-zero-length-blob

Conversation

@connerkup

Copy link
Copy Markdown
Contributor

Summary

Fixes #866

In column context, passing a 0-length blob (''::BLOB) through ST_GeomFromWKB(w) returns an empty 0-byte geometry blob without failing early. When subsequent vector functions (e.g. ST_GeometryType, ST_IsEmpty, ST_Dimension, ST_NPoints, ST_X, ST_Force2D) deserialize the geometry, BinaryReader::CheckSize throws an uncatchable INTERNAL Error: Buffer overflow assertion:

CREATE TABLE g AS SELECT ''::BLOB AS w;
SELECT ST_GeometryType(ST_GeomFromWKB(w)) FROM g;
-- INTERNAL Error: Buffer overflow

Because an InternalException represents an assertion failure within DuckDB rather than user input error, it cannot be caught via SQL TRY() and immediately aborts the query and invalidates the client connection. Furthermore, ST_AsText on the identical input raises a standard, catchable error:

SELECT ST_AsText(ST_GeomFromWKB(w)) FROM g;
-- Invalid Input Error: Unexpected end of binary data at position 0

Root Cause

  1. In src/spatial/util/binary_reader.hpp, BinaryReader::CheckSize threw InternalException("Buffer overflow") when ptr + size > end. A buffer underrun while reading deserialized geometry data is an invalid/truncated input condition, not an internal database assertion failure.
  2. In src/spatial/geometry/geometry_serialization.cpp, DeserializeInternal had no guard for empty buffers (buffer_size == 0), immediately triggering CheckSize(sizeof(uint8_t)) at offset 0.

Changes

  1. src/spatial/util/binary_reader.hpp:
    • Updated BinaryReader::CheckSize to compare size > static_cast<size_t>(end - ptr) (preventing integer overflow on malicious sizes) and throw:
      throw InvalidInputException("Unexpected end of binary data at position %zu",
                                  static_cast<size_t>(ptr - beg));
      This matches the exact error message and offset formatting used by DuckDB's core BlobReader.
  2. src/spatial/geometry/geometry_serialization.cpp:
    • Added pre-flight check in DeserializeInternal for buffer_size == 0 to immediately raise InvalidInputException("Unexpected end of binary data at position 0").
  3. test/sql/geometry/st_geomfromwkb.test:
    • Added regression tests verifying that zero-length WKB blobs in column context raise catchable Invalid Input Error: Unexpected end of binary data at position 0 across ST_GeometryType, ST_IsEmpty, ST_Dimension, ST_NPoints, and ST_X.
    • Verified that TRY(ST_GeometryType(...)) and TRY(ST_IsEmpty(...)) catch the error and cleanly return NULL.

@Maxxen

Maxxen commented Sep 8, 2026

Copy link
Copy Markdown
Member

Thanks!

We should probably just fix ST_GeomFromWKB in core to reject zero sized inputs anyway, so that there is no risk of creating zero sized GEOMETRY that can leak into the rest of the system.

@Maxxen
Maxxen merged commit c0c9fc9 into duckdb:v1.5-variegata Sep 10, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants