From 023a688e3f1ebdf1b41ea97720b0ccccf7ccbfaa Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 14 Sep 2022 14:43:01 +0930 Subject: [PATCH] lightningd: fix spurious leak report. We can (and probably should!) allocate this off tmpctx rather than off the response. Also, json_add_invoice doesn't actually match the normal pattern, so fix that. ``` E ValueError: E Node errors: E Global errors: E - Node /tmp/ltests-_vbj8az8/test_pay_fail_unconfirmed_channel_1/lightning-2/ has memory leaks: [ E { E "backtrace": [ E "ccan/ccan/tal/tal.c:442 (tal_alloc_)", E "wallet/invoices.c:81 (wallet_stmt2invoice_details)", E "wallet/invoices.c:697 (invoices_get_details)", E "wallet/wallet.c:2946 (wallet_invoice_details)", E "lightningd/invoice.c:1296 (json_add_invoices)", E "lightningd/invoice.c:1370 (json_listinvoices)", E "lightningd/jsonrpc.c:625 (command_exec)", E "lightningd/jsonrpc.c:753 (rpc_command_hook_final)", E "lightningd/plugin_hook.c:280 (plugin_hook_call_)", E "lightningd/jsonrpc.c:841 (plugin_hook_call_rpc_command)", E "lightningd/jsonrpc.c:938 (parse_request)", E "lightningd/jsonrpc.c:1035 (read_json)", E "ccan/ccan/io/io.c:59 (next_plan)", E "ccan/ccan/io/io.c:407 (do_plan)", E "ccan/ccan/io/io.c:417 (io_ready)", E "ccan/ccan/io/poll.c:453 (io_loop)", E "lightningd/io_loop_with_timers.c:22 (io_loop_with_timers)", E "lightningd/lightningd.c:1194 (main)", E "../csu/libc-start.c:308 (__libc_start_main)" E ], E "label": "wallet/invoices.c:81:struct invoice_details", E "parents": [ E "common/json_stream.c:41:struct json_stream", E "ccan/ccan/io/io.c:91:struct io_conn **NOTLEAK**", E "lightningd/lightningd.c:107:struct lightningd" E ], E "value": "0x55a57a77de08" E } E ] ``` Signed-off-by: Rusty Russell --- lightningd/invoice.c | 46 ++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/lightningd/invoice.c b/lightningd/invoice.c index a0097cb61..ee3d4a0f0 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -35,8 +35,8 @@ static const char *invoice_status_str(const struct invoice_details *inv) return "unpaid"; } -static void json_add_invoice(struct json_stream *response, - const struct invoice_details *inv) +static void json_add_invoice_fields(struct json_stream *response, + const struct invoice_details *inv) { json_add_escaped_string(response, "label", inv->label); if (inv->invstring) @@ -76,6 +76,15 @@ static void json_add_invoice(struct json_stream *response, } } +static void json_add_invoice(struct json_stream *response, + const char *fieldname, + const struct invoice_details *inv) +{ + json_object_start(response, fieldname); + json_add_invoice_fields(response, inv); + json_object_end(response); +} + static struct command_result *tell_waiter(struct command *cmd, const struct invoice *inv) { @@ -85,12 +94,12 @@ static struct command_result *tell_waiter(struct command *cmd, details = wallet_invoice_details(cmd, cmd->ld->wallet, *inv); if (details->state == PAID) { response = json_stream_success(cmd); - json_add_invoice(response, details); + json_add_invoice_fields(response, details); return command_success(cmd, response); } else { response = json_stream_fail(cmd, INVOICE_EXPIRED_DURING_WAIT, "invoice expired during wait"); - json_add_invoice(response, details); + json_add_invoice_fields(response, details); json_object_end(response); return command_failed(cmd, response); } @@ -1282,21 +1291,16 @@ static void json_add_invoices(struct json_stream *response, if (label) { if (wallet_invoice_find_by_label(wallet, &invoice, label)) { details = - wallet_invoice_details(response, wallet, invoice); - json_object_start(response, NULL); - json_add_invoice(response, details); - json_object_end(response); + wallet_invoice_details(tmpctx, wallet, invoice); + json_add_invoice(response, NULL, details); } } else if (payment_hash != NULL) { if (wallet_invoice_find_by_rhash(wallet, &invoice, payment_hash)) { - json_object_start(response, NULL); - json_add_invoice( - response, - wallet_invoice_details(response, wallet, invoice)); - json_object_end(response); + details = + wallet_invoice_details(tmpctx, wallet, invoice); + json_add_invoice(response, NULL, details); } - } else { memset(&it, 0, sizeof(it)); while (wallet_invoice_iterate(wallet, &it)) { @@ -1309,9 +1313,7 @@ static void json_add_invoices(struct json_stream *response, details->local_offer_id)) continue; } - json_object_start(response, NULL); - json_add_invoice(response, details); - json_object_end(response); + json_add_invoice(response, NULL, details); } } } @@ -1446,7 +1448,7 @@ static struct command_result *json_delinvoice(struct command *cmd, } response = json_stream_success(cmd); - json_add_invoice(response, details); + json_add_invoice_fields(response, details); return command_success(cmd, response); } @@ -1629,7 +1631,8 @@ static struct command_result *fail_exists(struct command *cmd, fatal("Duplicate invoice %s not found any more?", label->s); - json_add_invoice(data, wallet_invoice_details(cmd, wallet, invoice)); + json_add_invoice_fields(data, + wallet_invoice_details(cmd, wallet, invoice)); json_object_end(data); return command_failed(cmd, data); @@ -1769,8 +1772,9 @@ static struct command_result *json_createinvoice(struct command *cmd, } response = json_stream_success(cmd); - json_add_invoice(response, - wallet_invoice_details(cmd, cmd->ld->wallet, invoice)); + json_add_invoice_fields(response, + wallet_invoice_details(cmd, cmd->ld->wallet, + invoice)); return command_success(cmd, response); }