Skip to content

Neither backend checks that a telemetry/parameter value is the size the compiled sequence assumed #231

Description

@zimri-leisher

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions