core-lightning/tools/gen/header_template
Rusty Russell 76813d6f90 tools/generate-wire.py: fix varsize assignment.
Code like this is suspicious:

	subtype_varsize_struct->field_0 = *fromwire_test_features(subtype_varsize_struct, cursor, plen);

In fact, it is a memory leak since we copy and don't free the fromwire
result.  Really, field_0 should be a pointer.

We don't hit this case (yet!) in spec-generated code, but I did for
bolt13.

Here's the difference in gen_test output:

```patch
  diff -ur /tmp/before/test/gen_test.c /tmp/after/test/gen_test.c
  --- /tmp/before/test/gen_test.c	2020-05-07 16:23:31.651611235 +0930
  +++ /tmp/after/test/gen_test.c	2020-05-07 16:20:54.232574482 +0930
  @@ -214,12 +214,12 @@
   static void towire_subtype_varsize_struct(u8 **p, const struct subtype_varsize_struct *subtype_varsize_struct)
   {
   
  -	towire_test_features(p, &subtype_varsize_struct->field_0);
  +	towire_test_features(p, subtype_varsize_struct->field_0);
   }
   static void fromwire_subtype_varsize_struct(const u8 **cursor, size_t *plen, struct subtype_varsize_struct *subtype_varsize_struct)
   {
   
  - 	subtype_varsize_struct->field_0 = *fromwire_test_features(subtype_varsize_struct, cursor, plen);
  + 	subtype_varsize_struct->field_0 = fromwire_test_features(subtype_varsize_struct, cursor, plen);
   }
   
   /* SUBTYPE: SUBTYPE_VAR_LEN */
  @@ -373,7 +373,7 @@
   
   	ptr = tal_arr(ctx, u8, 0);
   
  -	towire_test_features(&ptr, &r->tlv3->features);
  +	towire_test_features(&ptr, r->tlv3->features);
   
   	towire_amount_msat(&ptr, r->tlv3->amount_msat_1);
   
  @@ -385,7 +385,7 @@
   	struct tlv_test_n1 *r = vrecord;
   
   	r->tlv3 = tal(r, struct tlv_test_n1_tlv3);
  -	r->tlv3->features = *fromwire_test_features(r->tlv3, cursor, plen);
  +	r->tlv3->features = fromwire_test_features(r->tlv3, cursor, plen);
   	r->tlv3->amount_msat_1 = fromwire_amount_msat(cursor, plen);
   	r->tlv3->amount_msat_2 = fromwire_amount_msat(cursor, plen);
   }
  @@ -824,11 +824,11 @@
   
   	towire_test_short_id(&ptr, &r->tlv3->subtype);
   
  -	towire_subtype_var_len(&ptr, &r->tlv3->varlen_subtype);
  +	towire_subtype_var_len(&ptr, r->tlv3->varlen_subtype);
   
  -	towire_subtype_var_assign(&ptr, &r->tlv3->varlen_assigned);
  +	towire_subtype_var_assign(&ptr, r->tlv3->varlen_assigned);
   
  -	towire_subtype_varlen_varsize(&ptr, &r->tlv3->test_sbt_varlen_varsize);
  +	towire_subtype_varlen_varsize(&ptr, r->tlv3->test_sbt_varlen_varsize);
   
   		for (size_t i = 0; i < 2; i++)
   		towire_u32(&ptr, r->tlv3->arr_assign[i]);
  @@ -868,9 +868,9 @@
   
   	r->tlv3 = tal(r, struct tlv_test_n3_tlv3);
   	fromwire_test_short_id(cursor, plen, &r->tlv3->subtype);
  -	r->tlv3->varlen_subtype = *fromwire_subtype_var_len(r->tlv3, cursor, plen);
  -	r->tlv3->varlen_assigned = *fromwire_subtype_var_assign(r->tlv3, cursor, plen);
  -	r->tlv3->test_sbt_varlen_varsize = *fromwire_subtype_varlen_varsize(r->tlv3, cursor, plen);
  +	r->tlv3->varlen_subtype = fromwire_subtype_var_len(r->tlv3, cursor, plen);
  +	r->tlv3->varlen_assigned = fromwire_subtype_var_assign(r->tlv3, cursor, plen);
  +	r->tlv3->test_sbt_varlen_varsize = fromwire_subtype_varlen_varsize(r->tlv3, cursor, plen);
   		for (size_t i = 0; i < 2; i++) {
   		u32 tmp;
   		tmp = fromwire_u32(cursor, plen);
  diff -ur /tmp/before/test/gen_test.h /tmp/after/test/gen_test.h
  --- /tmp/before/test/gen_test.h	2020-05-07 16:23:30.399617108 +0930
  +++ /tmp/after/test/gen_test.h	2020-05-07 16:20:52.912584680 +0930
  @@ -45,7 +45,7 @@
           struct test_short_id field_1;
   };
   struct subtype_varsize_struct {
  -        struct test_features field_0;
  +        struct test_features *field_0;
   };
   struct subtype_var_len {
           struct test_short_id *field_2;
  @@ -60,15 +60,15 @@
           struct test_short_id field3[2];
   };
   struct tlv_test_n1_tlv3 {
  -        struct test_features features;
  +        struct test_features *features;
           struct amount_msat amount_msat_1;
           struct amount_msat amount_msat_2;
   };
   struct tlv_test_n3_tlv3 {
           struct test_short_id subtype;
  -        struct subtype_var_len varlen_subtype;
  -        struct subtype_var_assign varlen_assigned;
  -        struct subtype_varlen_varsize test_sbt_varlen_varsize;
  +        struct subtype_var_len *varlen_subtype;
  +        struct subtype_var_assign *varlen_assigned;
  +        struct subtype_varlen_varsize *test_sbt_varlen_varsize;
           /*  array assigtest_nable */
           u32 arr_assign[2];
           /*  array structs */
  Binary files /tmp/before/test/gen_test.o and /tmp/after/test/gen_test.o differ
  Binary files /tmp/before/test/run-test-wire and /tmp/after/test/run-test-wire differ
  Binary files /tmp/before/test/run-test-wire.o and /tmp/after/test/run-test-wire.o differ
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-09-02 09:46:37 +09:30

167 lines
5 KiB
Text

/* This file was generated by generate-wire.py */
/* Do not modify this file! Modify the _csv file it was generated from. */
/* Original template can be found at tools/gen/header_template */
#ifndef LIGHTNING_${idem}
#define LIGHTNING_${idem}
#include <ccan/tal/tal.h>
#include <wire/tlvstream.h>
#include <wire/wire.h>
% for i in includes:
${i}
% endfor
## Enum sets for wire messages & tlvs
% for enum_set in enum_sets:
enum ${enum_set['name']} {
% for msg in enum_set['set']:
% for comment in msg.msg_comments:
/* ${comment} */
% endfor
${msg.enum_name()} = ${msg.number},
% endfor
};
%endfor
## The 'name' functions for the enums
% for enum_set in enum_sets:
const char *${enum_set['name']}_name(int e);
/**
* Determine whether a given message type is defined as a message.
*
* Returns true if the message type is part of the message definitions we have
* generated parsers for, false if it is a custom message that cannot be
* handled internally.
*/
bool ${enum_set['name']}_is_defined(u16 type);
% endfor
## Structs for subtypes + tlv messages
% for struct in structs:
struct ${struct.struct_name()} {
% for f in struct.fields.values():
% for c in f.field_comments:
/* ${c} */
% endfor
% if bool(f.len_field_of):
<% continue %>
% endif
% if f.is_varlen() and f.type_obj.is_varsize():
${f.type_obj.type_name()} **${f.name};
% elif f.is_varlen() or f.type_obj.is_varsize():
${f.type_obj.type_name()} *${f.name};
% elif f.is_array():
${f.type_obj.type_name()} ${f.name}[${f.count}];
% else:
${f.type_obj.type_name()} ${f.name};
% endif
% endfor
};
% endfor
## Structs for TLVs
% for tlv in tlvs.values():
struct ${tlv.struct_name()} {
/* Raw fields including unknown ones. */
struct tlv_field *fields;
/* TODO The following explicit fields could just point into the
* tlv_field entries above to save on memory. */
% for msg in tlv.messages.values():
% if msg.singleton():
${msg.singleton().type_obj.type_name()} *${msg.name};
% else:
struct ${msg.struct_name()} *${msg.name};
% endif
% endfor
};
% endfor
% for tlv in tlvs.values():
struct ${tlv.struct_name()} *${tlv.struct_name()}_new(const tal_t *ctx);
/**
* Deserialize a TLV stream for the ${tlv.name} namespace.
*
* This function will parse any TLV stream, as long as the type, length and
* value fields are formatted correctly. Fields that are not known in the
* current namespace are stored in the `fields` member. Validity can be
* checked using ${tlv.name}_is_valid.
*/
bool fromwire_${tlv.name}(const u8 **cursor, size_t *max,
struct ${tlv.struct_name()} * record);
/**
* Serialize a TLV stream for the ${tlv.name} namespace.
*
* This function only considers known fields from the ${tlv.name} namespace,
* and will ignore any fields that may be stored in the `fields` member. This
* ensures that the resulting stream is valid according to
* `${tlv.name}_is_valid`.
*/
void towire_${tlv.name}(u8 **pptr, const void *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 false if an error was detected, otherwise returns true. If err_index
* is non-null and we detect an error it is set to the index of the first error
* detected.
*/
bool ${tlv.name}_is_valid(const struct ${tlv.struct_name()} *record,
size_t *err_index);
% 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}[];
<%!
def upper(text):
return text.upper()
%>
/* Define an enum with the constants */
enum ${tlv.name}_types {
% for msg in tlv.ordered_msgs():
${msg.struct_name()|upper} = ${msg.number},
% endfor
};
% endif
% endfor
% if options.expose_subtypes and bool(subtypes):
% for subtype in subtypes:
/* SUBTYPE: ${subtype.name.upper()} */
% for c in subtype.type_comments:
/* ${c} */
% endfor
void towire_${subtype.name}(u8 **p, const ${subtype.type_name()} *${subtype.name});
% if subtype.is_varsize():
${subtype.type_name()} *fromwire_${subtype.name}(const tal_t *ctx, const u8 **cursor, size_t *plen);
% else:
void fromwire_${subtype.name}(const u8 **cursor, size_t *plen, ${subtype.type_name()} *${subtype.name});
% endif
% endfor
% endif
% for msg in messages:
% if msg.if_token:
#if ${msg.if_token}
% endif
/* WIRE: ${msg.name.upper()} */
% for c in msg.msg_comments:
/* ${c} */
% endfor
u8 *towire_${msg.name}(const tal_t *ctx${''.join([f.arg_desc_to() for f in msg.fields.values()])});
bool fromwire_${msg.name}(${'const tal_t *ctx, ' if msg.needs_context() else ''}const void *p${''.join([f.arg_desc_from() for f in msg.fields.values()])});
% if msg.if_token:
#endif /* ${msg.if_token} */
% endif
% endfor
#endif /* LIGHTNING_${idem} */