Browse Source

tlv: Add validity check codegen for the tlv namespaces

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.
travis-debug
Christian Decker 5 years ago
committed by Rusty Russell
parent
commit
2519f934aa
  1. 12
      tools/gen/header_template
  2. 35
      tools/gen/impl_template
  3. 3
      wallet/test/run-wallet.c

12
tools/gen/header_template

@ -68,6 +68,18 @@ struct ${tlv.struct_name()} {
struct ${tlv.struct_name()} *${tlv.struct_name()}_new(const tal_t *ctx); 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); 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: % if tlv.name in options.expose_tlv_type:
#define TLVS_${tlv.name.upper()}_ARRAY_SIZE ${len(tlv.messages)} #define TLVS_${tlv.name.upper()}_ARRAY_SIZE ${len(tlv.messages)}
extern const struct tlv_record_type tlvs_${tlv.name}[]; extern const struct tlv_record_type tlvs_${tlv.name}[];

35
tools/gen/impl_template

@ -304,6 +304,41 @@ fail:
fromwire_fail(cursor, max); fromwire_fail(cursor, max);
return false; 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 % endfor ## END TLV's
% for msg in messages: ## START Wire Messages % for msg in messages: ## START Wire Messages

3
wallet/test/run-wallet.c

@ -554,6 +554,9 @@ void subd_req_(const tal_t *ctx UNNEEDED,
/* Generated stub for subd_send_msg */ /* Generated stub for subd_send_msg */
void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED) void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED)
{ fprintf(stderr, "subd_send_msg called!\n"); abort(); } { 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_ */ /* Generated stub for topology_add_sync_waiter_ */
void topology_add_sync_waiter_(const tal_t *ctx UNNEEDED, void topology_add_sync_waiter_(const tal_t *ctx UNNEEDED,
struct chain_topology *topo UNNEEDED, struct chain_topology *topo UNNEEDED,

Loading…
Cancel
Save