From 8f390027155325dd0043d6430868e8f05a4ed314 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 23 Mar 2022 10:01:14 +1030 Subject: [PATCH] tools/generate-wire.py: have printwire routines do demarshal. This works better in general: let printwire_x do the work of figuring out how to demarshal x. This is particularly important for TLVs, which require a call to tlv_x_new() first. Signed-off-by: Rusty Russell --- devtools/print_wire.c | 180 +++++++++++++++++++++++++--------- devtools/print_wire.h | 39 ++++---- tools/gen/print_impl_template | 33 +------ tools/test/enum.c | 8 +- tools/test/enum.h | 3 +- tools/test/run-test-wire.c | 17 +++- 6 files changed, 178 insertions(+), 102 deletions(-) diff --git a/devtools/print_wire.c b/devtools/print_wire.c index 4523ecd7e..482a1afe0 100644 --- a/devtools/print_wire.c +++ b/devtools/print_wire.c @@ -7,29 +7,90 @@ #include #include -void printwire_u8(const char *fieldname, const u8 *v) +bool printwire_u8(const char *fieldname, const u8 **cursor, size_t *plen) { - printf("%u\n", *v); + u8 v = fromwire_u8(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED u8 %s**\n", fieldname); + return false; + } + printf("%u\n", v); + return true; } -void printwire_u16(const char *fieldname, const u16 *v) +bool printwire_u16(const char *fieldname, const u8 **cursor, size_t *plen) { - printf("%u\n", *v); + u16 v = fromwire_u16(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED u16 %s**\n", fieldname); + return false; + } + printf("%u\n", v); + return true; } -void printwire_u32(const char *fieldname, const u32 *v) +bool printwire_u32(const char *fieldname, const u8 **cursor, size_t *plen) { - printf("%u\n", *v); + u32 v = fromwire_u32(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED u32 %s**\n", fieldname); + return false; + } + printf("%u\n", v); + return true; } -void printwire_u64(const char *fieldname, const u64 *v) +bool printwire_u64(const char *fieldname, const u8 **cursor, size_t *plen) { - printf("%"PRIu64"\n", *v); + u64 v = fromwire_u64(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED u64 %s**\n", fieldname); + return false; + } + printf("%"PRIu64"\n", v); + return true; } -void printwire_wireaddr(const char *fieldname, const struct wireaddr *wireaddr) +bool printwire_tu16(const char *fieldname, const u8 **cursor, size_t *plen) { - printf("%s\n", fmt_wireaddr(tmpctx, wireaddr)); + u16 v = fromwire_tu16(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED tu16 %s**\n", fieldname); + return false; + } + printf("%u\n", v); + return true; +} + +bool printwire_tu32(const char *fieldname, const u8 **cursor, size_t *plen) +{ + u32 v = fromwire_tu32(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED tu32 %s**\n", fieldname); + return false; + } + printf("%u\n", v); + return true; +} + +bool printwire_tu64(const char *fieldname, const u8 **cursor, size_t *plen) +{ + u64 v = fromwire_tu64(cursor, plen); + if (!*cursor) { + printf("**TRUNCATED tu64 %s**\n", fieldname); + return false; + } + printf("%"PRIu64"\n", v); + return true; +} + +bool printwire_wireaddr(const char *fieldname, const u8 **cursor, size_t *plen) +{ + struct wireaddr w; + if (!fromwire_wireaddr(cursor, plen, &w)) + return false; + printf("%s\n", fmt_wireaddr(tmpctx, &w)); + return true; } /* Returns false if we ran out of data. */ @@ -37,15 +98,17 @@ static bool print_hexstring(const u8 **cursor, size_t *plen, size_t len) { while (len) { u8 v = fromwire_u8(cursor, plen); - if (!*cursor) + if (!*cursor) { + printf("**TRUNCATED**\n"); return false; + } printf("%02x", v); len--; } return true; } -static void printwire_alias(const u8 **cursor, size_t *plen, size_t len) +static bool printwire_alias(const u8 **cursor, size_t *plen, size_t len) { struct utf8_state utf8 = UTF8_STATE_INIT; const char *p = (const char *)*cursor; @@ -83,11 +146,12 @@ static void printwire_alias(const u8 **cursor, size_t *plen, size_t len) hexdump: if (!print_hexstring(cursor, plen, len)) - return; + return false; printf(" ]\n"); + return true; } -static void printwire_addresses(const u8 **cursor, size_t *plen, size_t len) +static bool printwire_addresses(const u8 **cursor, size_t *plen, size_t len) { struct wireaddr addr; size_t to_go = len; @@ -99,23 +163,24 @@ static void printwire_addresses(const u8 **cursor, size_t *plen, size_t len) printf(" %s", fmt_wireaddr(NULL, &addr)); } if (!*cursor) - return; + return false; if (to_go) { printf(" UNKNOWN:"); if (!print_hexstring(cursor, plen, len)) - return; + return false; } printf(" ]\n"); + return true; } -static void printwire_encoded_short_ids(const u8 **cursor, size_t *plen, size_t len) +static bool printwire_encoded_short_ids(const u8 **cursor, size_t *plen, size_t len) { struct short_channel_id *scids; u8 *arr = fromwire_tal_arrn(tmpctx, cursor, plen, len); if (!arr) - return; + return false; printf("["); scids = decode_short_ids(tmpctx, arr); @@ -139,34 +204,32 @@ static void printwire_encoded_short_ids(const u8 **cursor, size_t *plen, size_t || arr[0] == ARR_UNCOMPRESSED || arr[0] == ARR_ZLIB) { printf(" **CORRUPT**"); - return; + return true; } else { printf(" UNKNOWN:"); print_hexstring(cursor, plen, len); } } printf(" ]\n"); + return true; } -void printwire_u8_array(const char *fieldname, const u8 **cursor, size_t *plen, size_t len) +bool printwire_u8_array(const char *fieldname, const u8 **cursor, size_t *plen, size_t len) { - if (streq(fieldname, "node_announcement.alias")) { - printwire_alias(cursor, plen, len); - return; - } - if (streq(fieldname, "node_announcement.addresses")) { - printwire_addresses(cursor, plen, len); - return; - } - if (strends(fieldname, ".encoded_short_ids")) { - printwire_encoded_short_ids(cursor, plen, len); - return; - } + if (streq(fieldname, "node_announcement.alias")) + return printwire_alias(cursor, plen, len); + + if (streq(fieldname, "node_announcement.addresses")) + return printwire_addresses(cursor, plen, len); + + if (strends(fieldname, ".encoded_short_ids")) + return printwire_encoded_short_ids(cursor, plen, len); printf("["); if (!print_hexstring(cursor, plen, len)) - return; + return false; printf("]\n"); + return true; } static const struct tlv_print_record_type * @@ -220,25 +283,48 @@ fail: } #define PRINTWIRE_TYPE_TO_STRING(T, N) \ - void printwire_##N(const char *fieldname, const T *v) \ + bool printwire_##N(const char *fieldname, const u8 **cursor, \ + size_t *plen) \ { \ - const char *s = type_to_string(NULL, T, v); \ + T v; \ + fromwire_##N(cursor, plen, &v); \ + if (!*cursor) { \ + printf("**TRUNCATED " stringify(N) "\n"); \ + return false; \ + } \ + const char *s = type_to_string(NULL, T, &v); \ printf("%s\n", s); \ tal_free(s); \ + return true; \ + } + +#define PRINTWIRE_ASSIGNABLE_STRUCT_TO_STRING(N) \ + bool printwire_##N(const char *fieldname, const u8 **cursor, \ + size_t *plen) \ + { \ + struct N v = fromwire_##N(cursor, plen); \ + if (!*cursor) { \ + printf("**TRUNCATED " stringify(N) "\n"); \ + return false; \ + } \ + const char *s = type_to_string(NULL, struct N, &v); \ + printf("%s\n", s); \ + tal_free(s); \ + return true; \ } #define PRINTWIRE_STRUCT_TYPE_TO_STRING(T) \ PRINTWIRE_TYPE_TO_STRING(struct T, T) -PRINTWIRE_STRUCT_TYPE_TO_STRING(bitcoin_blkid); -PRINTWIRE_STRUCT_TYPE_TO_STRING(bitcoin_txid); -PRINTWIRE_STRUCT_TYPE_TO_STRING(channel_id); -PRINTWIRE_STRUCT_TYPE_TO_STRING(node_id); -PRINTWIRE_STRUCT_TYPE_TO_STRING(preimage); -PRINTWIRE_STRUCT_TYPE_TO_STRING(pubkey); -PRINTWIRE_STRUCT_TYPE_TO_STRING(sha256); -PRINTWIRE_STRUCT_TYPE_TO_STRING(secret); -PRINTWIRE_STRUCT_TYPE_TO_STRING(short_channel_id); -PRINTWIRE_STRUCT_TYPE_TO_STRING(amount_sat); -PRINTWIRE_STRUCT_TYPE_TO_STRING(amount_msat); -PRINTWIRE_TYPE_TO_STRING(secp256k1_ecdsa_signature, secp256k1_ecdsa_signature); +PRINTWIRE_STRUCT_TYPE_TO_STRING(bitcoin_blkid) +PRINTWIRE_STRUCT_TYPE_TO_STRING(bitcoin_txid) +PRINTWIRE_STRUCT_TYPE_TO_STRING(channel_id) +PRINTWIRE_STRUCT_TYPE_TO_STRING(node_id) +PRINTWIRE_STRUCT_TYPE_TO_STRING(preimage) +PRINTWIRE_STRUCT_TYPE_TO_STRING(pubkey) +PRINTWIRE_STRUCT_TYPE_TO_STRING(sha256) +PRINTWIRE_STRUCT_TYPE_TO_STRING(secret) +PRINTWIRE_STRUCT_TYPE_TO_STRING(short_channel_id) +PRINTWIRE_ASSIGNABLE_STRUCT_TO_STRING(amount_sat) +PRINTWIRE_ASSIGNABLE_STRUCT_TO_STRING(amount_msat) +PRINTWIRE_TYPE_TO_STRING(secp256k1_ecdsa_signature, secp256k1_ecdsa_signature) diff --git a/devtools/print_wire.h b/devtools/print_wire.h index 59f054dde..060ef8a29 100644 --- a/devtools/print_wire.h +++ b/devtools/print_wire.h @@ -16,26 +16,29 @@ typedef u64 bigsize; #define printwire_bigsize printwire_u64 struct wireaddr; -void printwire_u8(const char *fieldname, const u8 *v); -void printwire_u16(const char *fieldname, const u16 *v); -void printwire_u32(const char *fieldname, const u32 *v); -void printwire_u64(const char *fieldname, const u64 *v); -void printwire_u8_array(const char *fieldname, const u8 **cursor, size_t *plen, size_t len); +bool printwire_u8(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_u16(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_u32(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_u64(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_tu16(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_tu32(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_tu64(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_u8_array(const char *fieldname, const u8 **cursor, size_t *plen, size_t len); bool printwire_tlvs(const char *tlv_name, const u8 **cursor, size_t *plen, const struct tlv_print_record_type types[], size_t num_types); -void printwire_bitcoin_blkid(const char *fieldname, const struct bitcoin_blkid *bitcoin_blkid); -void printwire_wireaddr(const char *fieldname, const struct wireaddr *wireaddr); -void printwire_bitcoin_txid(const char *fieldname, const struct bitcoin_txid *bitcoin_txid); -void printwire_channel_id(const char *fieldname, const struct channel_id *channel_id); -void printwire_amount_sat(const char *fieldname, const struct amount_sat *sat); -void printwire_amount_msat(const char *fieldname, const struct amount_msat *msat); -void printwire_preimage(const char *fieldname, const struct preimage *preimage); -void printwire_pubkey(const char *fieldname, const struct pubkey *pubkey); -void printwire_node_id(const char *fieldname, const struct node_id *id); -void printwire_secp256k1_ecdsa_signature(const char *fieldname, const secp256k1_ecdsa_signature *); -void printwire_sha256(const char *fieldname, const struct sha256 *sha256); -void printwire_secret(const char *fieldname, const struct secret *secret); -void printwire_short_channel_id(const char *fieldname, const struct short_channel_id *short_channel_id); +bool printwire_bitcoin_blkid(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_wireaddr(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_bitcoin_txid(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_channel_id(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_amount_sat(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_amount_msat(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_preimage(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_pubkey(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_node_id(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_secp256k1_ecdsa_signature(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_sha256(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_secret(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_short_channel_id(const char *fieldname, const u8 **cursor, size_t *plen); #endif /* LIGHTNING_DEVTOOLS_PRINT_WIRE_H */ diff --git a/tools/gen/print_impl_template b/tools/gen/print_impl_template index 996d44b1c..8b4d24653 100644 --- a/tools/gen/print_impl_template +++ b/tools/gen/print_impl_template @@ -59,39 +59,14 @@ bool print${options.enum_name}_message(const u8 *msg) % else: for (size_t i = 0; i < ${f.size()}; i++) { % endif - printf("{\n"); - % if f.type_obj.is_subtype() or f.type_obj.is_varsize(): - printf("{\n"); - printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen); - printf("}\n"); - % else: - ${f.type_obj.type_name()} v; - % if f.type_obj.is_assignable(): - v = fromwire_${f.type_obj.name}(cursor, plen); - % else: - fromwire_${f.type_obj.name}(cursor, plen, &v); - % endif - ${truncate_check()} -<% typename = f.type_obj.name if not f.type_obj.is_truncated() else f.type_obj.name[1:] %>\ - printwire_${typename}(tal_fmt(NULL, "%s.${f.name}", fieldname), &v); - % endif + if (!printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen)) + return false; } printf("]"); % endif -${truncate_check()} \ - % elif f.type_obj.is_subtype() or f.type_obj.is_varsize(): - printf("{\n"); - printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen); - printf("}\n"); % else: - % if f.type_obj.is_assignable(): - ${f.type_obj.type_name()} ${f.name} = fromwire_${f.type_obj.name}(cursor, plen); - % else: - ${f.type_obj.type_name()} ${f.name}; - fromwire_${f.type_obj.name}(cursor, plen, &${f.name}); - % endif - <% typename = f.type_obj.name if not f.type_obj.is_truncated() else f.type_obj.name[1:] %> - printwire_${typename}(tal_fmt(NULL, "%s.${f.name}", fieldname), &${f.name}); ${truncate_check()} \ + if (!printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen)) + return false; % endif % endfor \ diff --git a/tools/test/enum.c b/tools/test/enum.c index b8ad28ee5..3d1c50180 100644 --- a/tools/test/enum.c +++ b/tools/test/enum.c @@ -13,7 +13,11 @@ enum test_enum fromwire_test_enum(const u8 **cursor, size_t *max) return TEST_ONE; } -void printwire_test_enum(const char *fieldname, const enum test_enum *test_enum) +bool printwire_test_enum(const char *fieldname, const u8 **cursor, size_t *max) { - printf("%u\n", *test_enum); + enum test_enum e = fromwire_test_enum(cursor, max); + if (!*cursor) + return false; + printf("%u\n", e); + return true; } diff --git a/tools/test/enum.h b/tools/test/enum.h index 702105e94..bc75e7211 100644 --- a/tools/test/enum.h +++ b/tools/test/enum.h @@ -2,6 +2,7 @@ #define LIGHTNING_TOOLS_TEST_ENUM_H #include "config.h" #include +#include #include #define TEST_IFDEF 0 @@ -13,6 +14,6 @@ enum test_enum { void towire_test_enum(u8 **pptr, const enum test_enum test_enum); enum test_enum fromwire_test_enum(const u8 **cursor, size_t *max); -void printwire_test_enum(const char *fieldname, const enum test_enum *test_enum); +bool printwire_test_enum(const char *fieldname, const u8 **cursor, size_t *max); #endif /* LIGHTNING_TOOLS_TEST_ENUM_H */ diff --git a/tools/test/run-test-wire.c b/tools/test/run-test-wire.c index 1898d8d93..b409715e1 100644 --- a/tools/test/run-test-wire.c +++ b/tools/test/run-test-wire.c @@ -10,24 +10,31 @@ /* Generated stub for fromwire_peektype */ int fromwire_peektype(const u8 *cursor UNNEEDED) { fprintf(stderr, "fromwire_peektype called!\n"); abort(); } +/* Could not find declaration for fromwire_test_enum */ /* Generated stub for printwire_amount_msat */ -void printwire_amount_msat(const char *fieldname UNNEEDED, const struct amount_msat *msat UNNEEDED) +bool printwire_amount_msat(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED) { fprintf(stderr, "printwire_amount_msat called!\n"); abort(); } /* Generated stub for printwire_tlvs */ bool printwire_tlvs(const char *tlv_name UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED, const struct tlv_print_record_type types[] UNNEEDED, size_t num_types UNNEEDED) { fprintf(stderr, "printwire_tlvs called!\n"); abort(); } +/* Generated stub for printwire_tu32 */ +bool printwire_tu32(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED) +{ fprintf(stderr, "printwire_tu32 called!\n"); abort(); } +/* Generated stub for printwire_tu64 */ +bool printwire_tu64(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED) +{ fprintf(stderr, "printwire_tu64 called!\n"); abort(); } /* Generated stub for printwire_u16 */ -void printwire_u16(const char *fieldname UNNEEDED, const u16 *v UNNEEDED) +bool printwire_u16(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED) { fprintf(stderr, "printwire_u16 called!\n"); abort(); } /* Generated stub for printwire_u32 */ -void printwire_u32(const char *fieldname UNNEEDED, const u32 *v UNNEEDED) +bool printwire_u32(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED) { fprintf(stderr, "printwire_u32 called!\n"); abort(); } /* Generated stub for printwire_u64 */ -void printwire_u64(const char *fieldname UNNEEDED, const u64 *v UNNEEDED) +bool printwire_u64(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED) { fprintf(stderr, "printwire_u64 called!\n"); abort(); } /* Generated stub for printwire_u8_array */ -void printwire_u8_array(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED, size_t len UNNEEDED) +bool printwire_u8_array(const char *fieldname UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED, size_t len UNNEEDED) { fprintf(stderr, "printwire_u8_array called!\n"); abort(); } /* AUTOGENERATED MOCKS END */