CCSDS TM Transfer Frames (CCSDS 132.0-B-3)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fuzz tests: AOS 2→9, USLP 2→9, fix OCF/FECF masking bug

Comprehensive fuzz test suites for AOS and USLP, replacing the
minimal 2-test stubs with 9 tests each covering:

- Decode crash safety (found and fixed a real bug: Wire.Codec
raised Invalid_argument on short input due to negative data_size
expression — added min_size pre-validation in Aos.decode)
- Roundtrip, roundtrip with OCF, encode determinism
- FECF corruption detection
- PP crash safety
- CLCW integration roundtrip
- Wire header roundtrip
- Idle frame detection
- USLP-specific: CRC-16/CRC-32 FECF variants, VCFC length variants

Bug fixes found by fuzzing:

- aos/tm/uslp: OCF and FECF values were not masked to their wire
width (32/16 bits) in constructors. On 64-bit OCaml, a caller
passing a negative int (e.g., from Int32.to_int on a high-bit-set
value) would encode the low 32 bits correctly but decode as a
different positive int, breaking roundtrip. Fix: mask in Aos.v,
Tm.v, Uslp.v, matching the existing pattern for VCFC/vcid/scid.

- aos: Wire.Codec.decode_with on short/malformed input could
produce a negative data_size (frame_len - header - trailer sizes),
causing Invalid_argument in String.sub. Fix: validate minimum
frame size before calling the codec.

+17 -10
+2
lib/tm.ml
··· 557 557 header ~version ~ocf_flag ~sec_hdr ~sync_flag ~pkt_order ~seg_len_id 558 558 ~first_hdr_ptr ~scid ~vcid ~mcfc ~vcfc () 559 559 in 560 + let ocf = Option.map (fun v -> v land 0xFFFFFFFF) ocf in 561 + let fecf = Option.map (fun v -> v land 0xFFFF) fecf in 560 562 { header; sec_hdr_data; data; ocf; fecf } 561 563 562 564 let clcw ?(control_word_type = 0) ?(version = 0) ?(status = Ready)
+14 -5
test/interop/dariol83/scripts/generate.java
··· 71 71 100, 200, true, false, 3, 72 72 new byte[]{0x42, 0x42, 0x42, 0x42}, null, false), 73 73 74 - // 7. Packet order flag set 74 + // 7. Packet order flag set (requires sync flag per spec) 75 75 new Vector("pkt_order_flag", 16, 10, 1, 76 76 false, false, 77 - 50, 75, false, true, 3, 77 + 50, 75, true, true, 3, 78 78 new byte[]{(byte)0x99, (byte)0x99}, null, false), 79 79 80 80 // 8. Max SCID/VCID, all flags, OCF+FECF ··· 142 142 if (v.idle) { 143 143 builder.setIdle(); 144 144 } else { 145 - if (v.userData != null) { 145 + // Fill the data field completely — TM frames have fixed length 146 + int freeSpace = builder.getFreeUserDataLength(); 147 + if (v.userData != null && v.userData.length <= freeSpace) { 146 148 builder.addData(v.userData); 149 + // Pad remaining space with zeros 150 + int remaining = builder.getFreeUserDataLength(); 151 + if (remaining > 0) { 152 + builder.addData(new byte[remaining]); 153 + } 154 + } else { 155 + builder.addData(new byte[freeSpace]); 147 156 } 148 157 } 149 158 ··· 159 168 int vcid = frame.getVirtualChannelId(); 160 169 int mcfc = frame.getMasterChannelFrameCount(); 161 170 int vcfc = frame.getVirtualChannelFrameCount(); 162 - boolean secHdr = frame.isSecondaryHeaderFlag(); 171 + boolean secHdr = frame.isSecondaryHeaderPresent(); 163 172 boolean syncFlag = frame.isSynchronisationFlag(); 164 173 boolean pktOrder = frame.isPacketOrderFlag(); 165 174 int segLenId = frame.getSegmentLengthIdentifier(); ··· 178 187 // Extract OCF bytes if present 179 188 String ocfHex = ""; 180 189 if (ocfPresent) { 181 - byte[] ocfBytes = frame.getOcf(); 190 + byte[] ocfBytes = frame.getOcfCopy(); 182 191 ocfHex = bytesToHex(ocfBytes); 183 192 } 184 193
+1 -5
test/interop/dariol83/traces/vectors.csv
··· 5 5 with_ocf_and_fecf,22,500,5,1,200,150,0,0,0,3,2047,deadbeef000000000000,cafebabe,1,1,1f4bc8961fffdeadbeef000000000000cafebabe50f4 6 6 various_ids,20,512,6,0,128,64,0,0,0,3,2047,0102030405060708000000000000,,0,0,200c80401fff0102030405060708000000000000 7 7 sync_flag,16,77,4,0,100,200,0,1,0,3,2047,42424242000000000000,,0,0,04d864c85fff42424242000000000000 8 - pkt_order_flag,16,10,1,0,50,75,0,0,1,3,2047,99990000000000000000,,0,0,00a2324b3fff99990000000000000000 8 + pkt_order_flag,16,10,1,0,50,75,0,1,1,3,2047,99990000000000000000,,0,0,00a2324b7fff99990000000000000000 9 9 max_scid_vcid,22,1023,7,1,255,255,0,1,1,0,2047,abcdef01000000000000,00000000,1,1,3fffffff67ffabcdef010000000000000000000018bf 10 - idle_frame,20,1023,7,0,255,255,0,0,0,3,2047,ffffffffffffffffffffffffffff,,0,0,3ffeffff1fffffffffffffffffffffffffffffff 11 - large_frame,200,300,2,1,1,1,0,0,0,3,2047,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,abcd1234,1,1,12c501011fff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abcd1234ad3b 12 - seg_len_zero,16,10,1,0,50,75,0,1,0,0,2047,99999900000000000000,,0,0,00a2324b47ff99999900000000000000 13 - frame_counts,22,42,3,1,137,42,0,0,0,3,2047,01020304050000000000,0104002a,1,1,02a7892a1fff010203040500000000000104002ac931