Description
The get_public_pmtiles endpoint in backend/src/public.rs performs file_size - 1 using unsigned (u64) arithmetic without checking for zero. If a zero-byte .pmtiles file is uploaded and published, requesting it (or sending a Range header) causes unsigned integer underflow.
Location
backend/src/public.rs, function get_public_pmtiles:
let end: u64 = if parts[1].is_empty() {
file_size - 1 // underflow when file_size == 0
} else {
parts[1].parse()...
};
let actual_end = end.min(file_size - 1); // same underflow
Impact
- Debug builds: Panic (server crash)
- Release builds: wraps to
u64::MAX, leading to incorrect Range parsing and potential huge memory allocation
A zero-byte .pmtiles file passes upload validation (the pmtiles arm returns Ok(()) without any validation), and can then be published.
Suggested Fix
Add a guard for empty files before Range parsing:
if file_size == 0 {
return Ok((
StatusCode::OK,
[
(header::CONTENT_TYPE, "application/octet-stream"),
(header::CONTENT_LENGTH, "0"),
(header::ACCEPT_RANGES, "bytes"),
],
Vec::<u8>::new(),
).into_response());
}
Also consider adding PMTiles header validation in upload.rs.
Description
The
get_public_pmtilesendpoint inbackend/src/public.rsperformsfile_size - 1using unsigned (u64) arithmetic without checking for zero. If a zero-byte.pmtilesfile is uploaded and published, requesting it (or sending a Range header) causes unsigned integer underflow.Location
backend/src/public.rs, functionget_public_pmtiles:Impact
u64::MAX, leading to incorrect Range parsing and potential huge memory allocationA zero-byte
.pmtilesfile passes upload validation (thepmtilesarm returnsOk(())without any validation), and can then be published.Suggested Fix
Add a guard for empty files before Range parsing:
Also consider adding PMTiles header validation in
upload.rs.