MDEV-39981 Fix ST_GEOMFROMGEOJSON returning wrong result with reverse…#5243
MDEV-39981 Fix ST_GEOMFROMGEOJSON returning wrong result with reverse…#5243akshatnehra wants to merge 1 commit into
Conversation
…d key order ST_GEOMFROMGEOJSON requires JSON keys to appear in a specific order (type before geometries/features/geometry/coordinates). When keys appear in a different order, the JSON scanner is left in an inconsistent state because json_skip_level() is not called to advance past the value when the type has not yet been determined. Fix: add json_skip_level() calls in the geometries, features, and geometry key handlers when the type key has not yet been encountered. This mirrors the existing pattern in the coordinates handler. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
There was a problem hiding this comment.
Code Review
This pull request addresses MDEV-39981, where ST_GEOMFROMGEOJSON returns incorrect results when GeoJSON keys are in a reversed order (such as coordinates or geometries appearing before the type). The fix introduces calls to json_skip_level in sql/spatial.cc to properly skip over nested structures when searching for the type key. Comprehensive test cases have been added to verify various geometries and key orderings. No review comments were provided, and there is no additional feedback to offer.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
grooverdan
left a comment
There was a problem hiding this comment.
Thanks very much for writing this. I was currently working on MDEV-39813 and was seeing this gap in implementation.
As a bug fix, can you rebase base to 10.11. There is a chance I could take it to 106 if needed to complete MDEV-39813, but I'm reviewing this to ensure changes don't conflict.
If you can take my suggested fixes on for MDEV-39989 and put them on the same branch it would ensure they don't conflict or merge incorrectly. One more MDEV-39989 fix is in coordinates for type !== JSON_VALUE_ARRAY, break;.
This only fixes part of the geometries processing MDEV-39989 invalid calls, however the MDEV-39813 will replace the json_scan_start additional calls, and might correct the processing of other GIS types.
| @@ -0,0 +1,38 @@ | |||
| --echo # | |||
| --echo # MDEV-39981: ST_GEOMFROMGEOJSON returns wrong result with reversed key order | |||
There was a problem hiding this comment.
Can these tests be moved to the bottom of mysql-test/main/gis-json.test
| --echo # | ||
|
|
||
| --echo # GeometryCollection: type before geometries (baseline) | ||
| SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type":"GeometryCollection","geometries":[]}')); |
There was a problem hiding this comment.
If you run this test with mtr --view-protocol it will fail. The solution is to use SELECT ST_ASTEXT(......) as exp as a pattern to give every result a simple name. Same with all other queries.
Thanks for the incremental headers as separation.
| SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"foo":"bar","geometries":[],"type":"GeometryCollection","extra":123}')); | ||
|
|
||
| --echo # Deeply nested geometries before type | ||
| SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[9,10]}]}],"type":"GeometryCollection"}')); |
There was a problem hiding this comment.
could re-order the "type: Point" and its "coordinates" within the nested version.
|
|
||
| --echo # Deeply nested geometries before type | ||
| SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[9,10]}]}],"type":"GeometryCollection"}')); | ||
|
|
There was a problem hiding this comment.
Below would be `--echo # End of 10.11 tests" once moved.
| goto create_geom; | ||
| } | ||
| if (json_skip_level(je)) | ||
| goto err_return; |
There was a problem hiding this comment.
just below the below } we could append else break; which would catch where geometries is something other than an array. It could be considered part of MDEV-39989.
| if (fcoll_type_found) | ||
| goto handle_feature_collection; | ||
| if (json_skip_level(je)) | ||
| goto err_return; |
There was a problem hiding this comment.
like above, features can only be an array. Same else break (!= JSON_VALUE_ARRAY) to report error.
| if (feature_type_found) | ||
| goto handle_geometry_key; | ||
| if (json_skip_level(je)) | ||
| goto err_return; |
There was a problem hiding this comment.
Geometry is a object type only. Like above, can result in error with else break; condition
| SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[[0,0],[1,0],[1,1],[0,1],[0,0]]],"type":"Polygon"}')); | ||
|
|
||
| --echo # FeatureCollection: features before type | ||
| SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[5,6]},"properties":{}}],"type":"FeatureCollection"}')); |
There was a problem hiding this comment.
could put type: Feature after geometry and type: point after properties. I expect the same, but it adds to the completeness of type last processing.
gkodinov
left a comment
There was a problem hiding this comment.
Thank you for your contribution!
Daniel already is doing a great job in reviewing this, so I'll just restrict myself to the formalities: please rebase on 10.11 (as he has already suggested). And also format the test addition properly as suggested by him.
Description
This PR fixes MDEV-39981 where
ST_GEOMFROMGEOJSON()crashes or returns wrong results when GeoJSON keys appear in a non-standard order (e.g.,"geometries"before"type").The GeoJSON parser in
spatial.ccexpects"type"to appear before other keys. When"geometries","features", or"geometry"appear first, the parser saves the value start position for later re-parsing but fails to calljson_skip_level()to advance the scanner past the value. This leaves the JSON scanner in an inconsistent state, causing crashes or incorrect parsing of subsequent keys.The fix involves:
json_skip_level()calls in the three affected key handlers (geometries, features, geometry) when the type has not yet been determined — matching the existing pattern already used by the coordinates handler.How can this PR be tested?
Run the MTR test:
Or manually (crashes without fix):
Results from my testing
GeoJSON is now parsed correctly regardless of key order, as required by the RFC 7946 spec (key order MUST NOT affect interpretation).
Basing the PR against the correct MariaDB version
PR quality check
CODING_STANDARDS.mdfile and my PR conforms to this where appropriate.