picopass_poller_send_frame() received into the caller-supplied rx_buffer
but trimmed instance->rx_buffer. The SAM read path passes its own
buffers, so every CRC-bearing card response silently shrank
instance->rx_buffer by two bytes: 8 after select, then 6, 4, 2, 0. The
fifth such frame called bit_buffer_set_size_bytes() with an underflowed
size and tripped its capacity furi_check.
A normal Picopass read spends exactly four trims (READ 05, READ 06, two
READ4s), landing on zero and surviving by one frame. Anything needing a
third READ4 -- an SIO too long for 64 bytes -- crashes.
READCHECK and CHECK responses carry no CRC, so they never reached the
trim; only READ, READ4 and PAGESEL did.
Drop the trim from send_frame rather than retargeting it: the SAM
expects responses with the CRC still attached, which is why the virtual
card state machine appends one and why capture_sio copies 32 of the 34
bytes a READ4 returns. identify() and select() need the trim for their
size checks, so they now do it themselves.
Claude-Session: https://claude.ai/code/session_016a4SuDfC8EkHo3MGGrRMod