I’m writing a BinPac flowunit analyzer, a PDU is like below:
type test_pdu = record {
lenAB : uint32; # length of rest of data
lenA : uint16; # length of dataA
dataA : bytestring &length = lenA;
dataB : bytestring &length = (lenAB - 2 - lenA);
} &byteorder=bigendian &length=(lenAB + 4);
There are 2 problems:
binpac failed to compile (cannot handle incremental input) if I remove &length=(lenAB - 2 -lenA), although the overall length of the PDU can be calculated using the 4 field length
the generated parser seems to check out-of-bound of lenA field too early:
Since we only make a new frame of length 4 in line #1588 (the flow buffer will not grow to full size until line #1607), the test in line #1597 will be evaluated to true and the parsing will fail.
I’d try reworking this, so that you have lenAB, and then another record for the rest of the data, and just setting the length of that record to lenAB. Does that work?
type test_pdu = record {
lenAB : uint32;
pduAB : test_pdu_ab(lenAB);
} &byteorder=bigendian &length=(lenAB + 4); # fail to compile without &length
type test_pdu_ab(len: uint32) = record {
lenA : uint16;
dataA : bytestring &length = lenA;
dataB : bytestring &length = (len - 2 - lenA);
} &byteorder=bigendian; # do not need &length here
Does it necessary to do those out-of-bound checks like in line #1597#1653#1668? I think we have already got filled frame with correct size when these checks are performed.