Bug #121524 ST_Transform() truncates the target SRID to 32 bits: ST_Transform(g, 4294971526) transforms to SRID 4230 instead of rais
Submitted: 15 Oct 18:33 Modified: 20 Oct 4:07
Reporter: Ke Han Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: GIS Severity:S3 (Non-critical)
Version:8.0.46, 8.4.11, 9.7.2, 26.07 OS:Any
Assigned to: CPU Architecture:Any

[15 Oct 18:33] Ke Han
Description:
Since Bug #80499 was fixed, every function that takes an SRID rejects a value
outside 0..2^32-1:

  SELECT ST_SRID(ST_GeomFromText('POINT(0 0)', 4294967296));
  -- ERROR 1690 (22003): SRID value is out of range in 'st_geomfromtext'
  SELECT ST_SRID(ST_GeomFromText('POINT(0 0)', 4326), 4294967296);
  -- ERROR 1690 (22003): SRID value is out of range in 'st_srid'

ST_Transform() does not.  Its target SRID is truncated to 32 bits, and when the
low 32 bits name an existing SRS the geometry is reprojected into it, with no
error or warning:

  SELECT ST_AsText(ST_Transform(ST_GeomFromText('POINT(63.4269121428687 10.3969184885902)', 4326), 4294971526));
  -- POINT(63.42724046084803 10.398501870897267)        4294971526 = 2^32 + 4230

  SELECT ST_AsText(ST_Transform(ST_GeomFromText('POINT(63.4269121428687 10.3969184885902)', 4326), 4230));
  -- POINT(63.42724046084803 10.398501870897267)        identical

  SELECT ST_SRID(ST_Transform(ST_GeomFromText('POINT(63.4269121428687 10.3969184885902)', 4326), 4294971526));
  -- 4230

  SELECT ST_SRID(ST_Transform(ST_GeomFromText('POINT(1 1)', 4326), 4294971622));   -- 4326  (2^32 + 4326)
  SELECT ST_SRID(ST_Transform(ST_GeomFromText('POINT(1 1)', 4326), -4294962970));  -- 4326  (negative, wraps too)

When the low 32 bits do not name an SRS, the error message names the wrong SRID:

  SELECT ST_Transform(ST_GeomFromText('POINT(1 1)', 4326), 4294967297);
  -- ERROR 3548 (SR001): There's no spatial reference system with SRID 1.

Where (trunk 3b99be40): sql/item_geofunc.cc, Item_func_st_transform::val_str(),
line 6045:

  const gis::srid_t target_srid = args[1]->val_int();

gis::srid_t is a uint32, so the longlong is narrowed without the range check the
other SRID-taking functions perform.

How to repeat:
SELECT ST_SRID(ST_Transform(ST_GeomFromText('POINT(63.4269121428687 10.3969184885902)', 4326), 4294971526));
SELECT ST_Transform(ST_GeomFromText('POINT(1 1)', 4326), 4294967297);
SELECT ST_SRID(ST_GeomFromText('POINT(0 0)', 4294967296));

-- expected: ERROR 1690 SRID value is out of range in 'st_transform'  (first two)
-- actual:   4230 / ERROR 3548 ... SRID 1.
-- the third statement is the reference: it already gives
--           ERROR 1690 SRID value is out of range in 'st_geomfromtext'

Suggested fix:
Read the target SRID as longlong and apply the same range check as the other
SRID arguments (ER_DATA_OUT_OF_RANGE, "SRID value is out of range in
'st_transform'") before converting it to gis::srid_t.
[20 Oct 4:07] Chaithra Marsur Gopala Reddy
Hi Ke Han,

Thank you for the test case. Verified as described.