From 31d1e6afaee043eacd09b4d131ed2b39f8620b8d Mon Sep 17 00:00:00 2001 From: Scott Boudreaux <121303252+Scottcjn@users.noreply.github.com> Date: Thu, 25 Jun 2026 20:18:20 +0000 Subject: [PATCH] Make polygonToCells fuzzer test portable across endianness (#964) The fuzzer_crash regression test built its polygon by reinterpreting a raw byte buffer as LatLng doubles (verts = (LatLng *)data), so the decoded vertices -- and the resulting cell count -- depended on the host's floating-point byte order. On big-endian architectures the same bytes decode to different doubles (the first vertex's latitude is even NaN), so maxPolygonToCellsSizeExperimental returns sz=3 instead of 1 and the sz == 1 assertion fails. Specify the vertices as explicit hex-float literals (the exact values the original bytes decoded to) so the test uses identical input on every architecture. This keeps the sz == 1 check meaningful and reproduces the original fuzzer scenario everywhere. Verified on a native big-endian POWER8 (ppc64) host: the test passes, and it continues to pass on little-endian. --- CHANGELOG.md | 2 ++ .../testPolygonToCellsReportedExperimental.c | 20 +++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f078191fde..51e334cd2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The public API of this library consists of the functions declared in file [h3api.h.in](./src/h3lib/include/h3api.h.in). ## [Unreleased] +### Fixed +- Fixed the `polygonToCells` fuzzer regression test to use explicit double literals instead of reinterpreting raw bytes, so it is portable across endianness (#964) ## [4.5.0] - 2026-05-21 ### Added diff --git a/src/apps/testapps/testPolygonToCellsReportedExperimental.c b/src/apps/testapps/testPolygonToCellsReportedExperimental.c index 9c7c1418ae..9ef9a9a1ca 100644 --- a/src/apps/testapps/testPolygonToCellsReportedExperimental.c +++ b/src/apps/testapps/testPolygonToCellsReportedExperimental.c @@ -30,22 +30,22 @@ SUITE(polygonToCells_reported) { // fuzzer crash due to inconsistent handling of CONTAINMENT_OVERLAPPING TEST(fuzzer_crash) { - uint8_t data[] = { - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0xa, 0xa, 0xa, 0xa, 0xa, 0xff, + // The vertices below are the exact doubles that the original fuzzer + // input (a raw byte buffer reinterpreted as LatLng) decoded to on a + // little-endian host. Spelling them out as hex-float literals makes + // the test decode identical values on every architecture regardless + // of byte order, instead of reinterpreting raw bytes (see #964). + LatLng verts[] = { + {0x0.000000000ffffp-1022, 0x0p+0}, + {0x1.fff00000ap-1008, -0x1.a0a0a0a0ap+1009}, }; uint8_t res = 0; - size_t vertsSize = sizeof(data); - int numVerts = vertsSize / sizeof(LatLng); - GeoPolygon geoPolygon; geoPolygon.numHoles = 0; geoPolygon.holes = NULL; - geoPolygon.geoloop.numVerts = numVerts; - // Offset by 1 since *data was used for `res`, above. - geoPolygon.geoloop.verts = (LatLng *)(data); + geoPolygon.geoloop.numVerts = 2; + geoPolygon.geoloop.verts = verts; uint32_t flags = CONTAINMENT_OVERLAPPING; int64_t sz;