Three things that all cost memory or correctness once BigBuf is larger
than 64KB, which it already is on PM5.
BigBuf_max_traceLen() returned a uint16_t while s_bigbuf_hi is a
uint32_t. At 33272 on AT91 that is harmless; on AT32, where BigBuf runs
to several hundred kbyte, it truncates and LF sampling asks for a
fraction of the buffer that is there. Widened, along with the four
callers that assigned it straight back into a uint16_t.
BigBuf_malloc() and BigBuf_calloc() took a uint16_t chunksize, so a
request of exactly 65536 arrived as 0 and anything above wrapped. It
returned NULL for the 65536 case by accident, not by design. Both take a
uint32_t now and the guard tests the upper bound explicitly, so an
oversized request fails like any other allocation that does not fit.
The 14a tag simulation allocated its dynamic modulation buffer as a flat
512, or 4096 for ST25TA. prepare_tag_modulation() memcpy's the encoded
answer out of the ToSend buffer and tosend_stuffbit() hard caps that at
TOSEND_BUFFER_SIZE, so 1788 of ST25TA's 4096 could never be reached --
it was the largest single allocation of any tag simulation for nothing.
Meanwhile 512 is 68 bytes short of what a full 64 byte response encodes
to, at 9 bytes per byte plus 4, so those answers were refused at
modulation time.
Both are now derived from the response size and capped at what ToSend
can hold: 580 for the default tag types, 2308 for ST25TA. That also
fixes the reason the 4096 never helped -- all six call sites passed the
512 macro as max_buffer_size rather than the size actually allocated, so
ST25TA allocated 4096 and then bounds checked against 512.
Worst case for a simulation that also holds emulator memory drops from
12247 bytes of BigBuf to 10459.
Built for client, RDV4 and PM3GENERIC. Not yet run on hardware.
Co-Authored-By: Claude Opus 5 (1M context)
Bug triggered with:
lf read -s 50000
hw ping
ReadLF_realtime() in lfsampling.c never knew how many samples the client wanted — for the realtime path, lf_sample_payload_t.samples was never populated on the client side, and the ARM handler in appmain.c (CMD_LF_ACQ_RAW_ADC/CMD_LF_SNIFF_RAW_ADC) ignored it anyway. So the device just streamed samples indefinitely, only checking for a stop request roughly once per 64-sample USB burst, and even after noticing it, flushed one more trailing partial burst via async_usb_write_stop().
Meanwhile the client (WaitForRawDataTimeout in comms.c) stops listening in raw mode the instant it has collected exactly the number of bytes it asked for (e.g. 50000), then switches back to normal framed-packet parsing. Since the device kept sending more bytes past that point, those extra bytes sat unread in the pipe and got misinterpreted as a PacketResponseNGPreamble/OLD-frame header, corrupting every subsequent USB exchange (hw ping, etc.) — reproducible even with a plain lf read -s 50000, no trigger/COTAG needed.
Moreover, we make sure the client doesn't stop listening, even briefly, during stream reception.
in appmain.c and cmd added.
in cmd.c and add some code for test CEP
in em4x50.c(Do not timeout--)
in em4x70.c
in emvsim.c
in epa.c
in felica.c
in felicasim.c
in felicasim.c
in hfops.c
in hfsnoop.c
in hitag2.c
in hitag_common.c(Cross-platform implementation is incomplete.)
in hitagS.c
in hitagu.c
in i2c.c(Incomplete, continue to abstract.)
in i2c_direct.c
in iclass.c
in iso14443a.c(Sniff no finish yet)
in iso14443b.c and fixed bug for st25
in iso15693.c
in legicrf.c
in legicrfsim.c
in lfadc.c(lf_count_edge_periods_ex() improved)
in lfops.c(TI tag no finish yet)
in lfsampling.c
in lfzx.c
in mifarecmd.c
in mifaredesfire.c
in mifaresim.c
in mifaresniff_disabled.c
in mifareutil.c
in pcf7931.c
in sam_xxx
in secc & seos
in start.c
in thinfilm.c
in utils
- "lf cotag reader": now behaves mostly the same as "lf read",
except it is dedicated for COTAG.
- It makes sure to send COTAG start sequence and to use
real time sampling mode to get enough samples.
- "lf cotag demod": Working client-side COTAG demodulation implementation
(high-low raw demod + Manchester demodulation from high/low demod).
- Now uses samples directly from g_GraphBuffer
- Supports 3 types of COTAG preamble (1 active, 2 passive), which
can start anywhere in the samples.
- Prints full 128-bits of COTAG tag data in 3 formats: raw,
groupped by nibbles, and in hex, and identifies and
prints out the card number.
Signed-off-by: andrej@towelbyte.net
Check if memory allocation fails
Fix memory leak
Initialize struct in declaration
Add/Fix some notes
Remove unlikely() in favor of readability
Remove a hard-coded magic number