Describe the bug
ST_Buffer panics inside i_overlay's hole-binding solver when the input is a
valid polygon containing a degenerate (near-zero-area) interior ring, once the
buffer distance is large enough to consume that hole.
pyo3_runtime.PanicException: index out of bounds: the len is 1 but the index is 9223372036854775807
from
thread '<unnamed>' panicked at .../i_overlay-4.0.7/src/bind/solver.rs:91:33
9223372036854775807 is i64::MAX, which suggests an uninitialised sentinel index
escaping rather than an ordinary off-by-one.
We ran into this issue performing some data processing on a real-world dataset of building footprints.
The hole is required. Buffering the same exterior ring with the interior ring
dropped succeeds at every distance tried. That is consistent with the panic site being
bind/solver.rs, the code binding holes to their parent contour.
GEOS buffers the identical geometry without complaint (shapely 2.1.2 / GEOS 3.14.1),
so this looks specific to i_overlay rather than a general geometry-engine limit.
Because it surfaces as a PanicException — which subclasses BaseException, not
Exception — it cannot be caught by ordinary Python error handling, so one bad row
takes down the whole process.
To Reproduce
import sedonadb
# Valid polygon: a thin triangle containing one degenerate sliver hole.
# ST_Area 330.0808, hole area ~0.096. Coordinates are in an arbitrary local frame,
# rounded to 4 decimal places.
WKT = (
"POLYGON ("
"(0 0, 208.1046 9.4235, 208.2609 6.2574, 0 0), "
"(103.4778 4.061, 103.476 4.0517, 103.4742 4.0415, 103.4706 4.0314, "
"103.4626 3.994, 103.4626 3.9847, 103.4608 3.9746, 103.459 3.9465, "
"104.5244 3.501, 104.5307 3.5096, 104.5477 3.522, 104.5558 3.5291, "
"104.5639 3.5376, 103.4778 4.061))"
)
sd = sedonadb.connect()
# The input is valid.
print("ST_IsValid:", sd.sql(
f"SELECT ST_IsValid(ST_GeomFromWKT('{WKT}'))"
).to_arrow_table().column(0)[0].as_py())
# Panics here.
sd.sql(f"SELECT ST_Buffer(ST_GeomFromWKT('{WKT}'), 10.0)").to_arrow_table()
print("no panic")
Output:
ST_IsValid: True
thread '<unnamed>' panicked at .../i_overlay-4.0.7/src/bind/solver.rs:91:33:
index out of bounds: the len is 1 but the index is 9223372036854775807
Buffer distance dependence
| distance |
with the hole |
hole dropped |
| 0.001 |
OK (55 pts) |
OK (36 pts) |
| 0.01 |
OK (52 pts) |
OK (36 pts) |
| 0.1 |
OK (36 pts) |
OK (36 pts) |
| 1 |
OK (40 pts) |
OK (36 pts) |
| 5 |
OK (44 pts) |
OK (36 pts) |
| 5.8 |
OK (56 pts) |
OK (36 pts) |
| 6 … 70 |
panic |
OK (36 pts) |
| 75 |
OK (56 pts) |
OK (36 pts) |
| 100 |
OK (44 pts) |
OK (36 pts) |
The panic window is 6 <= distance <= 70, i.e. once the buffer is large enough to
consume the degenerate hole but before it is large enough to swallow the whole
20-unit-wide feature. The same exterior ring with the interior ring dropped never
panics at any distance.
Expected behavior
ST_Buffer returns a buffered geometry, or raises a catchable error — rather than
panicking.
What I checked
- Not invalid input —
ST_IsValid is True.
- Not
ST_MakeValid — the panic is strictly inside ST_Buffer. ST_MakeValid also
does not remove the degenerate hole, so it is not a workaround.
- Not a coordinate-system or transform issue — no transform is involved, and the panic
is unaffected by translation or uniform scaling.
- Not the buffer style — the 2-arg round form above is enough.
- Note that
bind/solver.rs is unchanged between i_overlay 4.0.6 and 4.0.7, and the
0.4.1-rc0 tag locks the same 4.0.7.
Environment
- sedonadb: 0.4.0 (PyPI), the latest published release
- i_overlay: 4.0.7
- Python: 3.12
- OS: osx-arm64
Describe the bug
ST_Bufferpanics insidei_overlay's hole-binding solver when the input is avalid polygon containing a degenerate (near-zero-area) interior ring, once the
buffer distance is large enough to consume that hole.
from
9223372036854775807isi64::MAX, which suggests an uninitialised sentinel indexescaping rather than an ordinary off-by-one.
We ran into this issue performing some data processing on a real-world dataset of building footprints.
The hole is required. Buffering the same exterior ring with the interior ring
dropped succeeds at every distance tried. That is consistent with the panic site being
bind/solver.rs, the code binding holes to their parent contour.GEOS buffers the identical geometry without complaint (shapely 2.1.2 / GEOS 3.14.1),
so this looks specific to i_overlay rather than a general geometry-engine limit.
Because it surfaces as a
PanicException— which subclassesBaseException, notException— it cannot be caught by ordinary Python error handling, so one bad rowtakes down the whole process.
To Reproduce
Output:
Buffer distance dependence
The panic window is
6 <= distance <= 70, i.e. once the buffer is large enough toconsume the degenerate hole but before it is large enough to swallow the whole
20-unit-wide feature. The same exterior ring with the interior ring dropped never
panics at any distance.
Expected behavior
ST_Bufferreturns a buffered geometry, or raises a catchable error — rather thanpanicking.
What I checked
ST_IsValidis True.ST_MakeValid— the panic is strictly insideST_Buffer.ST_MakeValidalsodoes not remove the degenerate hole, so it is not a workaround.
is unaffected by translation or uniform scaling.
bind/solver.rsis unchanged between i_overlay 4.0.6 and 4.0.7, and the0.4.1-rc0 tag locks the same 4.0.7.
Environment