This is another geospatial extension crash I found when trying to get ibis working with duckdb 1.5.3 and came across a crash in duckdb that is triggered by some of the ibis geospatial unit tests. I reported the other crash here: duckdb/duckdb-python#475
Crash happens using duckdb==1.5.3, spatial extension b68b309
I have had copilot generate the following minimal reproducer from the failing unit test:
import duckdb, tempfile, os
con = duckdb.connect()
con.load_extension("spatial")
with tempfile.TemporaryDirectory() as tmp:
con.execute(f"COPY (SELECT ST_POINT(0.0, 0.0) AS geom) TO '{tmp}/out.mapml' (FORMAT GDAL, DRIVER 'MapML')")
The GeoRSS driver is also affected. Some additional insight from copilot and extended reproducer script is below
"""
Minimal reproducer for duckdb-spatial regression:
COPY TO with DRIVER 'MapML' or DRIVER 'GEORSS' raises
"Error: basic_string: construction from null is not valid"
instead of either succeeding or returning a clear error message.
This is a C++ null-pointer dereference inside duckdb-spatial's GDAL COPY
write path: a GDAL API call returns NULL (e.g. a layer name, SRS string, or
driver capability string), and the spatial extension passes it directly to a
std::string constructor without checking for null first.
Affected formats (confirmed):
- MapML (GDAL driver short name: MapML)
- GeoRSS (GDAL driver short name: GeoRSS / GEORSS)
Both drivers appear in ST_DRIVERS() with can_open=True and can_copy=True, so
duckdb-spatial accepts their names in COPY TO without raising an early error.
Versions tested:
duckdb 1.5.3
duckdb-spatial b68b309 (installed from repository)
Python 3.13.13
Expected behaviour: either the COPY TO succeeds, or a clear GDAL/IO error is
returned (e.g. "Driver does not support writing" or a GDAL error string).
Note: only GPKG and NGW show can_copy=True in ST_DRIVERS(); the remaining
drivers that accept COPY TO (including MapML and GeoRSS) go through a
separate code path inside duckdb-spatial that does not guard against null.
"""
import os
import tempfile
import duckdb
print(f"duckdb version: {duckdb.__version__}")
con = duckdb.connect()
con.load_extension("spatial")
# Confirm both drivers are known to duckdb-spatial
for short_name in ("MapML", "GeoRSS"):
row = con.execute(
f"SELECT short_name, can_create, can_open, can_copy "
f"FROM st_drivers() WHERE short_name ILIKE '{short_name}'"
).fetchone()
print(f"{short_name} in st_drivers(): {row}")
print()
with tempfile.TemporaryDirectory() as tmp:
cases = [
("MapML", os.path.join(tmp, "out.mapml")),
("GeoRSS", os.path.join(tmp, "out.georss")),
]
for driver, path in cases:
# Smallest possible query: single point row, geometry column only
sql = f"""
COPY (SELECT ST_POINT(0.0, 0.0) AS geom)
TO '{path}' (FORMAT GDAL, DRIVER '{driver}')
"""
try:
con.execute(sql)
print(f"{driver}: OK — wrote {os.path.getsize(path)} bytes")
except duckdb.Error as e:
first_line = str(e).splitlines()[0]
print(f"{driver}: REGRESSION CONFIRMED — {type(e).__name__}: {first_line}")
Many thanks!
This is another geospatial extension crash I found when trying to get ibis working with duckdb 1.5.3 and came across a crash in duckdb that is triggered by some of the ibis geospatial unit tests. I reported the other crash here: duckdb/duckdb-python#475
Crash happens using duckdb==1.5.3, spatial extension b68b309
I have had copilot generate the following minimal reproducer from the failing unit test:
The GeoRSS driver is also affected. Some additional insight from copilot and extended reproducer script is below
Many thanks!