Skip to content

Directives are size-checked against MAX_DIRECTIVE_SIZE (2048) instead of the 506-byte statement argument buffer #233

Description

@zimri-leisher

FinalChecks bounds each directive by Svc.Fpy.MAX_DIRECTIVE_SIZE (2048, which sizes the in-memory directive structs), but a statement's arguments travel in an Fw::StatementArgBuffer whose capacity is FW_STATEMENT_ARG_BUFFER_MAX_SIZE = FW_COM_BUFFER_MAX_SIZE - sizeof(FwOpcodeType) - sizeof(FwPacketDescriptorType) = 506, so a directive between 507 and 2045 bytes compiles with no error or warning and is then rejected by the sequencer at load with a raw deserialize error. CONST_CMD is worse: FinalChecks bounds command arguments by FW_CMD_ARG_BUFFER_MAX_SIZE (506), but the statement buffer also holds the 4-byte FwOpcodeType, so the real ceiling is 502 — and every RUN_ARGS/VALIDATE_ARGS in the Ref dictionary has a maximum argument payload of 505-506 bytes, so a seq-run call with a long enough child path lands in the failing window while passing every compiler check. The fix is to check each directive's argument bytes against FW_STATEMENT_ARG_BUFFER_MAX_SIZE from the dictionary, accounting for the opcode that shares the buffer in the CONST_CMD case.

import fpy.test_helpers as th

for n in (506, 507):                      # PUSH_VAL carrying the message bytes
    _, dirs, _ = th.compile_seq('log("%s")\n' % ("A" * n))
    th.run_seq(None, dirs)

for path_len in (237, 238):               # CONST_CMD: 4-byte opcode + (2 + path_len) + 263
    seq = 'Ref.cmdSeq0.VALIDATE_ARGS("%s", Svc.SeqArgs())\n' % ("a" * path_len)
    _, dirs, _ = th.compile_seq(seq)
    th.run_seq(None, dirs)
case statement argBuf result
log() of 506 bytes 506 loads and runs
log() of 507 bytes 507 validation fails
command with 502 argument bytes 506 loads and runs
command with 503 argument bytes 507 validation fails
FileReadDeserializeError : Deserialize error encountered while reading BODY (1) of file s0.bin: 5 (517 bytes left out of 528)

The compiler only objects at 2046+ bytes, naming the wrong limit: Directive PUSH_VAL in sequence too large (expected at most 2048 bytes, was 2103).

Related: #224 is the same code path scoped to FwSizeStoreType = U8 dictionaries (where the symptom is a struct.error crash rather than a load failure) and names FwSizeStoreType's range as the limit; a fix that checks only what #224 describes would leave the default-config bug in place. #203's body says a long log() message compiles and is truncated at run time — above 506 bytes the sequence does not run at all.

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