fuzz-tests: add a check for `bolt11_encode()`
What changed, and why it matters
This commit adds a new software test (a fuzz test) that exercises an existing invoice encoding function called bolt11_encode(). It does not change any production code, fix a bug, or alter how the software handles user data. It only adds test coverage.
No security action needed. Treat as routine test improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies tests/fuzz/fuzz-bolt11.c to add a signing callback and extend the fuzz harness so that after a successful bolt11_decode(), it calls bolt11_encode() with a deterministic dummy private key. This is purely a test/fuzzing enhancement; no library or daemon code is changed, and no security vulnerability is patched.
Changed components
tests/fuzz/fuzz-bolt11.cInspect captured patch +36 / −2
diff --git a/tests/fuzz/fuzz-bolt11.c b/tests/fuzz/fuzz-bolt11.c
index c28827ae..37d08bd3 100644
--- a/tests/fuzz/fuzz-bolt11.c
+++ b/tests/fuzz/fuzz-bolt11.c
@@ -1,6 +1,7 @@
#include "config.h"
#include <bitcoin/chainparams.h>
+#include <bitcoin/privkey.h>
#include <common/bech32.h>
#include <common/bolt11.h>
#include <common/features.h>
@@ -42,6 +43,35 @@ static size_t initial_input(uint8_t *fuzz_data, size_t size, size_t max_size)
return size;
}
+static bool test_sign(const u5 *u5bytes,
+ const u8 *hrpu8,
+ secp256k1_ecdsa_recoverable_signature *rsig,
+ void *unused UNUSED)
+{
+ struct hash_u5 hu5;
+ char *hrp;
+ struct sha256 sha;
+ struct privkey privkey;
+
+ memset(&privkey, 'a', sizeof(privkey));
+
+ hrp = tal_dup_arr(NULL, char, (char *)hrpu8, tal_count(hrpu8), 1);
+ hrp[tal_count(hrpu8)] = '\0';
+
+ hash_u5_init(&hu5, hrp);
+ hash_u5(&hu5, u5bytes, tal_count(u5bytes));
+ hash_u5_done(&hu5, &sha);
+ tal_free(hrp);
+
+ if (!secp256k1_ecdsa_sign_recoverable(secp256k1_ctx, rsig,
+ (const u8 *)&sha,
+ privkey.secret.data,
+ NULL, NULL))
+ abort();
+
+ return true;
+}
+
// We use a custom mutator to produce an input corpus that consists entirely of
// correctly encoded bech32 strings. This enables us to efficiently fuzz the
// bolt11 decoding logic without the fuzzer getting stuck on fuzzing the bech32
@@ -187,9 +217,13 @@ size_t LLVMFuzzerCustomCrossOver(const u8 *in1, size_t in1_size, const u8 *in2,
void run(const uint8_t *data, size_t size)
{
char *invoice_str = to_string(tmpctx, data, size);
- char *fail;
+ char *fail = NULL;
- bolt11_decode(tmpctx, invoice_str, NULL, NULL, NULL, &fail);
+ struct bolt11 *b11 = bolt11_decode(tmpctx, invoice_str, NULL, NULL, NULL, &fail);
+ if (b11)
+ bolt11_encode(tmpctx, b11, false, test_sign, NULL);
+ else
+ assert(fail);
clean_tmpctx();
}
Why this scored 14/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.