Skip to content

Commit

Permalink
tlv: Add validity check codegen for the tlv namespaces
Browse files Browse the repository at this point in the history
Since the parser itself just parses and doesn't include validation anymore we
need to put that functionality somewhere. The validation consists of enforcing
that the types are in monotonically increasing order without duplicates and
that for the even types we know how to handle it.
  • Loading branch information
cdecker committed Nov 21, 2019
1 parent 482f914 commit 02fb929
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
12 changes: 12 additions & 0 deletions tools/gen/header_template
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ struct ${tlv.struct_name()} {
struct ${tlv.struct_name()} *${tlv.struct_name()}_new(const tal_t *ctx);
bool fromwire_${tlv.name}(const u8 **cursor, size_t *max, struct ${tlv.struct_name()} *record);

/**
* Check that the TLV stream is valid.
*
* Enforces the followin validity rules:
* - Types must be in monotonic non-repeating order
* - We must understand all even types
*
* Returns the index of the field that was invalid, or -1 if the stream is
* valid.
*/
int ${tlv.name}_is_valid(const struct ${tlv.struct_name()} *record);

% if tlv.name in options.expose_tlv_type:
#define TLVS_${tlv.name.upper()}_ARRAY_SIZE ${len(tlv.messages)}
extern const struct tlv_record_type tlvs_${tlv.name}[];
Expand Down
35 changes: 35 additions & 0 deletions tools/gen/impl_template
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,41 @@ fail:
fromwire_fail(cursor, max);
return false;
}

int ${tlv.name}_is_valid(const struct ${tlv.struct_name()} *record)
{
size_t numfields = tal_count(record->fields);
bool first = true;
u64 prev_type = 0;
for (int i=0; i<numfields; i++) {
struct tlv_field *f = &record->fields[i];
if (f->numtype % 2 == 0 && f->meta == NULL) {
/* BOLT #1:
* - otherwise, if `type` is unknown:
* - if `type` is even:
* - MUST fail to parse the `tlv_stream`.
* - otherwise, if `type` is odd:
* - MUST discard the next `length` bytes.
*/
SUPERVERBOSE("Unknown even type in TLV");
return i;
} else if (!first && f->numtype <= prev_type) {
/* BOLT #1:
* - if decoded `type`s are not monotonically-increasing:
* - MUST fail to parse the `tlv_stream`.
*/
if (f->numtype == prev_type)
SUPERVERBOSE("duplicate tlv type");
else
SUPERVERBOSE("invalid ordering");
return i;
}
first = false;
prev_type = f->numtype;
}
return -1;
}

% endfor ## END TLV's
% for msg in messages: ## START Wire Messages

Expand Down
3 changes: 3 additions & 0 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,9 @@ void subd_req_(const tal_t *ctx UNNEEDED,
/* Generated stub for subd_send_msg */
void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED)
{ fprintf(stderr, "subd_send_msg called!\n"); abort(); }
/* Generated stub for tlv_payload_is_valid */
int tlv_payload_is_valid(const struct tlv_tlv_payload *record UNNEEDED)
{ fprintf(stderr, "tlv_payload_is_valid called!\n"); abort(); }
/* Generated stub for topology_add_sync_waiter_ */
void topology_add_sync_waiter_(const tal_t *ctx UNNEEDED,
struct chain_topology *topo UNNEEDED,
Expand Down

0 comments on commit 02fb929

Please sign in to comment.