Neither sequencer validates that the serialized size of a telemetry or parameter value equals the size the compiled sequence expects, so a value stored at a different size than the ground dictionary's type (a stale ParamDb entry across a type change, or ground/flight dictionary skew) is accepted and silently misread instead of failing. On fpybc PUSH_TLM_VAL/PUSH_PRM push getSize() bytes and the directives carry no expected size, so an oversized value leaves the wrong bytes in the variable plus strays on the operand stack while the sequence still reports success; on wasm the host's only bound is the value_size the guest passes, so an undersized value is written short and the guest deserializes the tail of whatever the previous read left in the shared tlm/prm buffer. Closing it needs an expected size on both paths: a schema bump putting the size in the fpybc directives, and on wasm an exact-equality check in dispatchTelemetry/dispatchParameter gated on validity first (an invalid channel comes back empty, so a blanket != would turn today's specific TLM_CHAN_NOT_FOUND/PRM_NOT_FOUND into a generic host failure).
Oversized (Ref.recvBuffComp.parameter1 is U32, stored as 6 bytes):
p: U32 = Ref.recvBuffComp.parameter1
# fpybc: takes the LAST 4 bytes, cmdResponse OK, 2 bytes stray on the stack
# wasm : BufferTooSmall, sequence fails
Undersized (stored as 0 bytes, reported VALID) — the second read returns the first read's value:
a: U32 = Ref.recvBuffComp.parameter1 # 0xDEADBEEF
b: F32 = Ref.sendBuffComp.parameter4 # stored empty
assert b == -6.259853398707798e+18, 77 # wasm: passes, b is a's bytes
The wasm half also has an action-at-a-distance bug: _emit_tlm_prm_read passes the shared tlm_prm_buffer capacity (sized to the largest read anywhere in the module) rather than this read's own max_size, so whether an oversized value is caught depends on unrelated code elsewhere. Same U32 channel, same oversized value:
; alone in the module -> BufferTooSmall, fails
%".4" = call i32 @"tlm"(i64 16777216, i8* %".3", i32 11, i8* %".2", i32 4)
; with a 42-byte struct channel read elsewhere -> no error, succeeds
%".60" = call i32 @"tlm"(i64 16777216, i8* %".59", i32 11, i8* %".58", i32 42)
That part is a one-liner in _emit_tlm_prm_read (use state.synthesized_types[node].max_size, the same type the value is deserialized at just below); it makes the existing > check consistent but does not fix the undersized direction on its own.
Neither sequencer validates that the serialized size of a telemetry or parameter value equals the size the compiled sequence expects, so a value stored at a different size than the ground dictionary's type (a stale ParamDb entry across a type change, or ground/flight dictionary skew) is accepted and silently misread instead of failing. On fpybc
PUSH_TLM_VAL/PUSH_PRMpushgetSize()bytes and the directives carry no expected size, so an oversized value leaves the wrong bytes in the variable plus strays on the operand stack while the sequence still reports success; on wasm the host's only bound is thevalue_sizethe guest passes, so an undersized value is written short and the guest deserializes the tail of whatever the previous read left in the shared tlm/prm buffer. Closing it needs an expected size on both paths: a schema bump putting the size in the fpybc directives, and on wasm an exact-equality check indispatchTelemetry/dispatchParametergated on validity first (an invalid channel comes back empty, so a blanket!=would turn today's specificTLM_CHAN_NOT_FOUND/PRM_NOT_FOUNDinto a generic host failure).Oversized (
Ref.recvBuffComp.parameter1isU32, stored as 6 bytes):Undersized (stored as 0 bytes, reported VALID) — the second read returns the first read's value:
The wasm half also has an action-at-a-distance bug:
_emit_tlm_prm_readpasses the sharedtlm_prm_buffercapacity (sized to the largest read anywhere in the module) rather than this read's ownmax_size, so whether an oversized value is caught depends on unrelated code elsewhere. Same U32 channel, same oversized value:That part is a one-liner in
_emit_tlm_prm_read(usestate.synthesized_types[node].max_size, the same type the value is deserialized at just below); it makes the existing>check consistent but does not fix the undersized direction on its own.