In 301/CO_PDO.c, when CO_CONFIG_PDO_BITWISE_MAPPING is enabled, a
mapped object with mappedLength == 0 bits is a legal mapping (see the
CO_PDO_t.OD_IO documentation: "mappedLengthBits can be less or equal
to the OD_IO.dataLength*8"), but nothing rejects it and two spots
compute a shift amount as "64 - mappedLength", which becomes a
shift-by-64 on a uint64_t. Shifting a 64-bit value by 64 is undefined
behaviour in C and is not portable across compilers/optimization
levels (verified: an -O0 build silently no-ops the shift so the
intended mask/skip has no effect, while an -O2 build of the same
source produces a different result for the same input).
- CO_RPDO_process(): shiftedData was computed unconditionally as
"buf64 & (UINT64_MAX >> (64 - mappedLength))"; now short-circuits to
0 when mappedLength == 0, matching the documented semantics that a
0-bit mapping should leave the target OD variable untouched.
- CO_TPDOsend(): the same masking pattern, plus a second UB spot
where the result is placed with "buf <<= (verifyLength -
mappedLength)", which is also a shift-by-64 once a preceding mapped
entry already fills the full PDO width. Both operations are now
skipped when mappedLength == 0, so a 0-bit-mapped OD variable never
contributes any of its raw bytes to the outgoing TPDO buffer.
Verified against current master (9b8beed): compiled 301/CO_PDO.c and
linked the example/ project standalone with
CO_CONFIG_PDO_BITWISE_MAPPING forced on, with no new warnings.
Independently re-derived the shift logic in an isolated harness and
confirmed the fixed code matches a portable reference mask for every
legal mappedLength (0-64) with zero mismatches, and that both the RPDO
"leftover payload leaks into a 0-bit mapped variable" scenario and the
TPDO "0-bit mapped variable leaks its raw bytes onto the bus" scenario
are eliminated at both -O0 and -O2.