diff --git a/mysql-test/main/lotofstack.result b/mysql-test/main/lotofstack.result index 5fb6e3bf524..ce28c4cf205 100644 --- a/mysql-test/main/lotofstack.result +++ b/mysql-test/main/lotofstack.result @@ -126,4 +126,16 @@ repeat('{"type":"GeometryCollection", "geometries":[', @len), '{"type":"Point","coordinates":[0,0]}', repeat(']}', @len) )) as exp; +# +# MDEV-41630 ST_IsValid crashes on polygons with many rings +# +SET SESSION group_concat_max_len = 200000000; +SET @rings = (SELECT GROUP_CONCAT( +CONCAT('(', seq, ' 0,', seq+1, ' 0,', seq+1, ' 1,', seq, ' 1,', seq, ' 0)') +SEPARATOR ',' +) FROM seq_1_to_100000); +SET @g = ST_GeomFromText(CONCAT('POLYGON(', @rings, ')')); +SELECT ST_IsValid(@g); +ST_IsValid(@g) +0 # End of 12.3 tests diff --git a/mysql-test/main/lotofstack.test b/mysql-test/main/lotofstack.test index 07dd51ae993..2b667e3f270 100644 --- a/mysql-test/main/lotofstack.test +++ b/mysql-test/main/lotofstack.test @@ -5,6 +5,7 @@ # making writing tests that depend on reaching # the depth hard. # +source include/have_sequence.inc; source include/not_embedded.inc; # MSAN with debug exceeds the stack early. source include/not_msan_with_debug.inc; @@ -12,7 +13,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) } # @@ -189,4 +190,18 @@ SELECT ST_GeomFromGeoJSON( )) as exp; --enable_result_log +--echo # +--echo # MDEV-41630 ST_IsValid crashes on polygons with many rings +--echo # +SET SESSION group_concat_max_len = 200000000; + +SET @rings = (SELECT GROUP_CONCAT( + CONCAT('(', seq, ' 0,', seq+1, ' 0,', seq+1, ' 1,', seq, ' 1,', seq, ' 0)') + SEPARATOR ',' +) FROM seq_1_to_100000); + +SET @g = ST_GeomFromText(CONCAT('POLYGON(', @rings, ')')); + +SELECT ST_IsValid(@g); + --echo # End of 12.3 tests diff --git a/sql/spatial.cc b/sql/spatial.cc index 056dacc2b8f..d54d2226814 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -2273,10 +2273,10 @@ int Gis_polygon::is_valid(int *valid) const collector.prepare_operation(); scan_it.init(&collector); - border_count= (char *) my_alloca(num_rings); + border_count= (char *) my_safe_alloca(num_rings); bzero(border_count, num_rings); - touches_count= (char *) my_alloca(num_rings); - internals= (char *) my_alloca(num_rings); + touches_count= (char *) my_safe_alloca(num_rings); + internals= (char *) my_safe_alloca(num_rings); while (scan_it.more_points()) { @@ -2373,9 +2373,9 @@ int Gis_polygon::is_valid(int *valid) const exit: collector.reset(); scan_it.reset(); - my_afree(border_count); - my_afree(touches_count); - my_afree(internals); + my_safe_afree(border_count, num_rings); + my_safe_afree(touches_count, num_rings); + my_safe_afree(internals, num_rings); return result; @@ -3993,7 +3993,7 @@ int Gis_multi_polygon::is_valid(int *valid) const collector.prepare_operation(); scan_it.init(&collector); - internals= (char *) my_alloca(num_geometries); + internals= (char *) my_safe_alloca(num_geometries); while (scan_it.more_points()) { @@ -4064,7 +4064,7 @@ int Gis_multi_polygon::is_valid(int *valid) const exit: collector.reset(); scan_it.reset(); - my_afree(internals); + my_safe_afree(internals, num_geometries); return result; }