1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-41622 INSERT crashes on deeply nested GeometryCollection

- get_data_size() and init_from_wkb() return their error values on
  stack overrun, not a valid-looking length
- add stack checks to the remaining recursive GeometryCollection
  methods: wkt, json, mbr, area, length, dimension, store_shapes
- test non-GEOMETRY column and SELECT paths

Assisted-by: Claude:claude-opus-5-5
This commit is contained in:
Sergei Golubchik
2026-10-19 15:50:37 +02:00
parent 718b550de5
commit 156dd2ff36
3 changed files with 74 additions and 3 deletions

View File

@@ -116,3 +116,20 @@ ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stac
SELECT ExtractValue('<a/>', REPEAT('/n', 100000));
ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable.
# End of 10.6 tests
#
# MDEV-41622 INSERT crashes on deeply nested GeometryCollection
#
set @g=concat(0x00000000, 0x0107000000, repeat(0x010000000107000000, 400000), 0x00000000);
create table t1 (g geometry);
create table t2 (g polygon);
insert t1 values (@g);
insert t2 values (@g);
select st_astext(@g);
select st_asgeojson(@g);
select st_envelope(@g);
select st_area(@g);
select st_length(@g);
select st_dimension(@g);
select st_boundary(@g);
drop table t1, t2;
# End of 10.11 tests

View File

@@ -12,7 +12,7 @@ if (`select count(*) from information_schema.system_variables
where variable_name='have_sanitizer'
and global_value REGEXP '(A|UB)SAN'`)
{
--skip Can't be run in UBSAN/ASAN (stack size predictability)
--skip Cannot be run in UBSAN/ASAN (stack size predictability)
}
#
@@ -172,3 +172,33 @@ SELECT ExtractValue('<a/>', REPEAT('(', 100000));
SELECT ExtractValue('<a/>', REPEAT('/n', 100000));
--echo # End of 10.6 tests
--echo #
--echo # MDEV-41622 INSERT crashes on deeply nested GeometryCollection
--echo #
set @g=concat(0x00000000, 0x0107000000, repeat(0x010000000107000000, 400000), 0x00000000);
create table t1 (g geometry);
create table t2 (g polygon);
--disable_result_log
--error ER_STACK_OVERRUN_NEED_MORE
insert t1 values (@g);
--error ER_STACK_OVERRUN_NEED_MORE
insert t2 values (@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_astext(@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_asgeojson(@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_envelope(@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_area(@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_length(@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_dimension(@g);
--error ER_STACK_OVERRUN_NEED_MORE
select st_boundary(@g);
--enable_result_log
drop table t1, t2;
--echo # End of 10.11 tests

View File

@@ -1,6 +1,6 @@
/*
Copyright (c) 2002, 2013, Oracle and/or its affiliates.
Copyright (c) 2011, 2021, MariaDB Corporation.
Copyright (c) 2011, 2026, MariaDB plc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -3359,6 +3359,9 @@ uint32 Gis_geometry_collection::get_data_size() const
n_objects= uint4korr(data);
data+= 4;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return GET_SIZE_ERROR;
while (n_objects--)
{
uint32 wkb_type,object_size;
@@ -3491,7 +3494,7 @@ uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len,
n_geom= wkb_get_uint(wkb, bo);
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&wkb_orig))
return 1;
return 0;
if (res->reserve(4, 512))
return 0;
@@ -3578,6 +3581,9 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt,
n_objects= uint4korr(data);
data+= 4;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
if (n_objects == 0)
{
txt->append(STRING_WITH_LEN(" EMPTY"), 512);
@@ -3622,6 +3628,9 @@ bool Gis_geometry_collection::get_data_as_json(String *txt, uint max_dec_digits,
n_objects= uint4korr(data);
data+= 4;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
bool any_objects= false;
txt->qs_append('[');
while (n_objects--)
@@ -3666,6 +3675,9 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
if (n_objects == 0)
goto exit;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
while (n_objects--)
{
uint32 wkb_type;
@@ -3704,6 +3716,9 @@ int Gis_geometry_collection::area(double *ar, const char **end) const
if (n_objects == 0)
goto exit;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
while (n_objects--)
{
uint32 wkb_type;
@@ -3744,6 +3759,9 @@ int Gis_geometry_collection::geom_length(double *len, const char **end) const
if (n_objects == 0)
goto exit;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
while (n_objects--)
{
uint32 wkb_type;
@@ -3841,6 +3859,9 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
n_objects= uint4korr(data);
data+= 4;
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
*res_dim= 0;
while (n_objects--)
{
@@ -3887,6 +3908,9 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const
return 0;
}
if (check_stack_overrun(current_thd, STACK_MIN_SIZE, (uchar*)&buffer))
return 1;
if (trn->start_collection(n_objects))
return 1;