From 29c9dbb88331cc439fd3e05a0c8f4a971527a9da Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Wed, 26 Mar 2025 16:53:30 -0400 Subject: [PATCH] MDEV-36168 ASAN error in Item_func_latlongfromgeohash::decode_geohash decode_geohash now properly filters non ASCII values from the input. --- .../main/spatial_utility_function_geohash.result | 7 +++++++ .../main/spatial_utility_function_geohash.test | 8 ++++++++ sql/item_geofunc.cc | 16 ++++++++++++---- sql/item_geofunc.h | 5 +++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/spatial_utility_function_geohash.result b/mysql-test/main/spatial_utility_function_geohash.result index 614bbbbd6a7..2a5838c37bc 100644 --- a/mysql-test/main/spatial_utility_function_geohash.result +++ b/mysql-test/main/spatial_utility_function_geohash.result @@ -1654,3 +1654,10 @@ SELECT ST_AsText(ST_PointFromGeohash(col1, 4326)) FROM t1; ST_AsText(ST_PointFromGeohash(col1, 4326)) POINT(-145 49.3) DROP TABLE t1; +# +# MDEV-36168 ASAN global-buffer-overflow in Item_func_latlongfromgeohash::decode_geohash +# +SELECT ST_LatFromGeoHash("ї"); +ERROR HY000: Incorrect geohash value: '\0457' for function st_latfromgeohash +SELECT ST_LongFromGeoHash("ї"); +ERROR HY000: Incorrect geohash value: '\0457' for function st_longfromgeohash diff --git a/mysql-test/main/spatial_utility_function_geohash.test b/mysql-test/main/spatial_utility_function_geohash.test index 7c71b4e6f90..b68b155abc6 100644 --- a/mysql-test/main/spatial_utility_function_geohash.test +++ b/mysql-test/main/spatial_utility_function_geohash.test @@ -1453,3 +1453,11 @@ SELECT ST_LatFromGeohash(col1) FROM t1; SELECT ST_LongFromGeohash(col1) FROM t1; SELECT ST_AsText(ST_PointFromGeohash(col1, 4326)) FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-36168 ASAN global-buffer-overflow in Item_func_latlongfromgeohash::decode_geohash +--echo # +--error ER_WRONG_VALUE_FOR_TYPE +SELECT ST_LatFromGeoHash("ї"); +--error ER_WRONG_VALUE_FOR_TYPE +SELECT ST_LongFromGeoHash("ї"); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 78027e7dea2..d3ab585a1cf 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -3027,6 +3027,15 @@ const uint8_t Item_func_latlongfromgeohash::geohash_alphabet[256] = { }; +bool Item_func_latlongfromgeohash::convert_character(char in, int &out) +{ + if (in < 0) + return true; + out= Item_func_latlongfromgeohash::geohash_alphabet[(int) in]; + return false; +} + + /** Decodes a geohash string into longitude and latitude. The results are rounded, based on the length of input geohash. The function @@ -3053,10 +3062,9 @@ bool Item_func_latlongfromgeohash::decode_geohash( for (uint i = 0; i < input_length; i++) { - int converted_character = - Item_func_latlongfromgeohash::geohash_alphabet[(int) (*geohash)[i]]; - - if (converted_character == 255) { + int converted_character= -1; + if (convert_character((*geohash)[i], converted_character) || + converted_character == 255) { return true; } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 0201f19f96b..9ef9052d5a9 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -1317,12 +1317,13 @@ public: class Item_func_latlongfromgeohash : public Item_real_func { - private: +private: String buf; static const uint8_t geohash_alphabet[256]; const bool decode_longitude; + static bool convert_character(char in, int &out); - public: +public: Item_func_latlongfromgeohash(THD *thd, Item *a, bool start_on_even_bit_arg) : Item_real_func(thd, a), decode_longitude(start_on_even_bit_arg) {}