duckdb / duckdb/duckdb-spatial

ST_Read_Meta segfaults on any unreadable file in 1.5.5 (regression; ST_Read raises normally)

Open
#860 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
708
Forks
96
Avg merge
1d 21h
Merged PRs (30d)
5

Description

What happens

In DuckDB 1.5.5, ST_Read_Meta crashes with SIGSEGV when GDAL cannot open the input file. The process exits 139, and no exception reaches the caller. try/except blocks and other in-process error handling cannot recover from the failure.

This is specific to ST_Read_Meta. ST_Read raises duckdb.IOException for the same file. DuckDB 1.5.1 through 1.5.4 also do not crash, so the regression starts in 1.5.5.

Reproduction

import duckdb

with open("bad.geojson", "w") as f:
f.write('{"type": "FeatureCollection", "features": [INVALID')

con = duckdb.connect()
con.execute("INSTALL spatial; LOAD spatial;")
con.execute("SELECT * FROM ST_Read_Meta('bad.geojson')").fetchone()

$ python repro.py

$ echo $?
139

The script produces no output before the interpreter exits.

Versions tested

Each test used the spatial extension shipped with that DuckDB release.


duckdb | spatial extension | Result
-- | -- | --
1.5.1 |   | returns, no error
1.5.2 |   | returns, no error
1.5.3 |   | returns, no error
1.5.4 | b68b309 | returns, no error
1.5.5 | eb1e57c | SIGSEGV, exit 139

Inputs tested

The crash is not specific to the truncated JSON above. On 1.5.5, all of these inputs exit 139:

  • truncated JSON

  • plain text saved with a .geojson extension

  • an empty .geojson file

A valid GeoJSON file reads correctly. In each failing case, GDAL cannot open the file.

ST_Read handles the same error

On DuckDB 1.5.5, ST_Read raises an exception for the same malformed file instead of crashing:

con.execute("SELECT * FROM ST_Read('bad.geojson')").fetchone()

# raises duckdb.IOException

The GDAL open failure is therefore handled correctly by ST_Read but crashes ST_Read_Meta.

Impact

We found this in portolan-cli through geoparquet-io. geoparquet-io calls ST_Read_Meta to detect the CRS of every vector file it reads. One malformed file in a directory therefore kills the entire run, with no error message and no partial result.

Downstream code cannot guard against the failure because the process exits before DuckDB can return an exception. A library that needs to survive malformed input would have to isolate each call in a subprocess. We are pinning duckdb<1.5.5 for now.

Environment

  • DuckDB 1.5.5, Python client

  • spatial extension eb1e57c

  • Python 3.14.3 and 3.12.2, both affected

  • Linux 6.8.0-56-generic, x86_64, glibc 2.39

Related

Issue #544 reported a ST_Read_Meta crash in April 2025 on a different input and is now closed. This regression starts in 1.5.5 and reproduces with any unreadable file we tested.

### What happens

In DuckDB 1.5.5, `ST_Read_Meta` crashes with `SIGSEGV` when GDAL cannot open the input file. The process exits 139, and no exception reaches the caller. `try`/`except` blocks and other in-process error handling cannot recover from the failure.

This is specific to `ST_Read_Meta`. `ST_Read` raises `duckdb.IOException` for the same file. DuckDB 1.5.1 through 1.5.4 also do not crash, so the regression starts in 1.5.5.

### Reproduction

```python
import duckdb

with open("bad.geojson", "w") as f:
f.write('{"type": "FeatureCollection", "features": [INVALID')

con = duckdb.connect()
con.execute("INSTALL spatial; LOAD spatial;")
con.execute("SELECT * FROM ST_Read_Meta('bad.geojson')").fetchone()
```

```console
$ python repro.py
$ echo $?
139
```

The script produces no output before the interpreter exits.

### Versions tested

Each test used the spatial extension shipped with that DuckDB release.

| duckdb | spatial extension | Result |
| ------ | ----------------- | ------------------- |
| 1.5.1 | | returns, no error |
| 1.5.2 | | returns, no error |
| 1.5.3 | | returns, no error |
| 1.5.4 | `b68b309` | returns, no error |
| 1.5.5 | `eb1e57c` | `SIGSEGV`, exit 139 |

### Inputs tested

The crash is not specific to the truncated JSON above. On 1.5.5, all of these inputs exit 139:

* truncated JSON
* plain text saved with a `.geojson` extension
* an empty `.geojson` file

A valid GeoJSON file reads correctly. In each failing case, GDAL cannot open the file.

### `ST_Read` handles the same error

On DuckDB 1.5.5, `ST_Read` raises an exception for the same malformed file instead of crashing:

```python
con.execute("SELECT * FROM ST_Read('bad.geojson')").fetchone()
# raises duckdb.IOException
```

The GDAL open failure is therefore handled correctly by `ST_Read` but crashes `ST_Read_Meta`.

### Impact

We found this in [[portolan-cli](https://github.com/portolan-sdi/portolan-cli)](https://github.com/portolan-sdi/portolan-cli) through [[geoparquet-io](https://github.com/geoparquet/geoparquet-io)](https://github.com/geoparquet/geoparquet-io). `geoparquet-io` calls `ST_Read_Meta` to detect the CRS of every vector file it reads. One malformed file in a directory therefore kills the entire run, with no error message and no partial result.

Downstream code cannot guard against the failure because the process exits before DuckDB can return an exception. A library that needs to survive malformed input would have to isolate each call in a subprocess. We are pinning `duckdb<1.5.5` for now.

### Environment

* DuckDB 1.5.5, Python client
* spatial extension `eb1e57c`
* Python 3.14.3 and 3.12.2, both affected
* Linux 6.8.0-56-generic, x86_64, glibc 2.39

### Related

Issue #544 reported a `ST_Read_Meta` crash in April 2025 on a different input and is now closed. This regression starts in 1.5.5 and reproduces with any unreadable file we tested.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the ST_Read_Meta entry point and reproduce the failure using the Python script and unreadable GeoJSON inputs described in the issue. Compare its behavior with ST_Read on DuckDB 1.5.5 and review the 1.5.4 versus 1.5.5 regression context. Done means unreadable input returns an exception instead of terminating with SIGSEGV, with coverage for the reported cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, python
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.