Compute GeoCoord's UTM/MGRS/OSGR/OLC lazily instead of eagerly (#10996)
GeoCoord's constructor unconditionally computed all five coordinate representations (DMS, UTM, MGRS, OSGR, OLC) via setCoords(), even though most callers only ever read one. The UTM conversion alone pulls in a chain of libm trig functions (atan, __kernel_tan, __ieee754_acos, __ieee754_pow, __kernel_rem_pio2/__ieee754_rem_pio2) that then have to be linked in regardless of whether anything is ever displayed. The only screen consumer (UIRenderer.cpp's GPS coordinate display) already dispatches on a single configured format and reads exactly one representation per call - never more than one. Compute DMS eagerly (cheap, most commonly needed) and defer UTM/MGRS/OSGR/OLC to first access via their own getters, tracked with per-representation mutable dirty flags, so a caller that never touches a given representation never pulls in its conversion code or the trig functions it needs. On stm32wl, GeoCoord's heavy constructor is reached only through NMEAWPL.cpp's NMEA/CalTopo serial export (GPS-gated, so wio-e5 only), which only ever reads the DMS getters - so this recovers 8,288 bytes flash there (of the 10,172-byte ceiling if the whole feature were cut) with the feature fully intact and zero behavior change on any platform. Updated test_geocoord_extreme_coords_no_oob (the existing regression test for a historical out-of-bounds crash in the UTM/MGRS conversion on extreme lat/lon) to explicitly call each representation's getter, since it previously relied on the constructor eagerly triggering all four conversions - which this change intentionally defers. Verified: full native test suite passes (586/586 test cases, including this one under ASan), and rak4631 (nRF52, screen-equipped, where the UTM/MGRS/OSGR/OLC getters are actually reachable) builds successfully. Assisted-by: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Andrew Yong <me@ndoo.sg> Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
co-authored by
GitHub
Ben Meadors
parent
269b974e96
commit
dd509a8ecf
@@ -214,7 +214,8 @@ static void test_cryptoKeyIsPublic_invalidKeyIsNotPublic()
|
||||
// Pre-fix, latitude_i = INT32_MAX made latLongToUTM read latBands[36] on a 21-char string
|
||||
// (stack-buffer-overflow at GeoCoord.cpp:128, an AddressSanitizer abort); extreme longitude produced
|
||||
// a negative UTM zone feeding the MGRS letter tables. The fix clamps the zone/band/col/row indices.
|
||||
// This exercises the fix under the coverage env's ASan.
|
||||
// This exercises the fix under the coverage env's ASan. Each representation is computed lazily,
|
||||
// so its getter must be called explicitly here to exercise its conversion path.
|
||||
static void test_geocoord_extreme_coords_no_oob()
|
||||
{
|
||||
const int32_t vals[] = {INT32_MIN, INT32_MAX, INT32_MIN + 1, INT32_MAX - 1, 0, 1, -1, 900000000, -900000000, // +/-90 deg
|
||||
@@ -223,7 +224,13 @@ static void test_geocoord_extreme_coords_no_oob()
|
||||
const size_t n = sizeof(vals) / sizeof(vals[0]);
|
||||
for (size_t i = 0; i < n; i++)
|
||||
for (size_t j = 0; j < n; j++) {
|
||||
GeoCoord g(vals[i], vals[j], 0); // ctor -> setCoords() -> UTM/MGRS/OSGR/OLC
|
||||
GeoCoord g(vals[i], vals[j], 0); // ctor -> setCoords() -> DMS only
|
||||
// Force UTM/MGRS/OSGR/OLC computation (each lazy on first getter access).
|
||||
g.getUTMZone();
|
||||
g.getMGRSZone();
|
||||
g.getOSGRE100k();
|
||||
char olcCode[OLC_CODE_LEN + 1];
|
||||
g.getOLCCode(olcCode);
|
||||
// Surviving every extreme pair (no ASan fault) means the index clamps hold.
|
||||
TEST_ASSERT_EQUAL_INT32(vals[i], g.getLatitude());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user