• docs/zmodem_comparison.md src/hash/crc32.h src/sbbs3/zmodem.c

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Mon Aug 24 22:46:27 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/77503916899457263ce9bb86
    Modified Files:
    docs/zmodem_comparison.md src/hash/crc32.h src/sbbs3/zmodem.c
    Log Message:
    zmodem: CRC received spans with crc32_update(), not a duplicate of it

    The bulk receive path added in the commit that introduced the optional recv_span callback CRC'd each span with a new static inline
    ucrc32_span() in crc32.h. That function was byte-for-byte the loop crc32_update() (src/hash/crc32.c:170) has always been -- slicing-by-4
    for the bulk, byte-at-a-time for the tail -- differing only in argument
    order. zmodem.c already includes crc32.h, so the helper it needed was
    already declared in the header it was editing.

    Call crc32_update() and delete ucrc32_span(). No functional change:
    5 clean 256 MB receives verify byte-identical and the 3e-6 corruption
    gate passes 5 of 5. Throughput is unmoved -- 484.2 MB/s against
    486.5 for the inline version, receiver CPU 0.55 s either way, a
    difference well inside the +/-5 % code-layout noise documented in docs/zmodem_comparison.md 3.5. A span averages 36 bytes, so trading an
    inlined loop for one call per span costs nothing measurable.

    The send path keeps its open-coded loop: zmodem_send_data_subpkt()
    interleaves the CRC with zmodem_tx_masked() four bytes at a time, so it
    needs the per-4-byte granularity and cannot call a whole-span helper.

    Found by Rob Swindell, who asked whether crc32_update() did not already
    do this. It did.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net