rfile::file_ofs is uint32_t but lseek()'s offset is int32_t. The
previous SEEK_SET path performed MIN(int32_t offset, int32_t length)
and assigned the int32_t result into the uint32_t file_ofs slot. A
negative offset (e.g. -1) became 0xFFFFFFFF.
The subsequent read() then computed
count = MIN(count, get_length() - file_ofs)
which underflows when file_ofs > length, producing a huge unsigned
value. memcpy(buf, get_string()[file_ofs], count) then reads from a
wild address relative to the underlying buffer base.
This is reachable over MAVFTP (any client can lseek a @SYS file via
FTP_OP_OpenFileRO + offset field) and the underlying buffer for
@SYS/storage.bin is the live EEPROM pointer from
hal.storage->get_storage_ptr(), while @SYS/flash.bin points at
0x08000000 internal flash. Either path leaks adjacent memory.
Fix: reject negative SEEK_SET offsets; compute SEEK_CUR in int64_t
and clamp into [0, length]. SEEK_END continues to return EINVAL.
Found via offensive-security benchmark on ArduPilot Plane 4.6.3
(ESL / claude-mythos main_prompt run via Factory Droid, 2026-05-21).
Amp-Thread-ID: https://ampcode.com/threads/T-019e4710-85bb-77d1-b50a-ba871a28d82b
Co-authored-by: Amp <amp@ampcode.com>
We will reserve BOARD_FLASH_SIZE for the internal flash on stm32 flash processors, use HAL_PROGRAM_SIZE_LIMIT_KB in the general code base.
Notable change here is that boards with external flash will start to get features only available with more than 2MB of program storage
Also rename from HAL_CRASHDUMP_ENABLE
Removes code based on define rather than creating empty functions. Makes it clearer what's going on in the callers.