From a9ed085a5fada2e4b9c98447c9b0d7ab4e6bfd7a Mon Sep 17 00:00:00 2001 From: KY-U Date: Thu, 6 Aug 2026 17:55:35 -0300 Subject: [PATCH] fix(psbt): reject trailing byte when parsing Require wally_psbt_from_bytes to consume the complete input buffer. Add PSBT v0 and v2 regression test cases with a trailing byte. --- src/ctest/psbts.h | 6 ++++++ src/data/psbt.json | 8 ++++++++ src/psbt.c | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/ctest/psbts.h b/src/ctest/psbts.h index 4a3907419..751aaef38 100644 --- a/src/ctest/psbts.h +++ b/src/ctest/psbts.h @@ -91,6 +91,9 @@ static const struct psbt_test invalid_psbts[] = /* PSBT v0 with duplicate 0 length script */ {"cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQgBAAEIAwEBUQA=", false, true}, + /* PSBT v0 with one P2PKH input. Outputs are empty. With trailing byte 0x00 */ + {"cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAAAA==", false, true}, + /* PSBT v2 With Global tx version number < 2 */ {"cHNidP8B+wQCAAAAAQIEAQAAAAEDBAECAwQBBAEAAQUBAAA=", false, true}, @@ -103,6 +106,9 @@ static const struct psbt_test invalid_psbts[] = /* PSBT v2 missing tx version */ {"cHNidP8B+wQCAAAAAQQBAAEFAQAA", false, true}, + /* PSBT v2 (no inputs, no outputs) with trailing byte 0x00 */ + {"cHNidP8BAgQCAAAAAQMEAAAAAAEEAQABBQEAAfsEAgAAAAAA", false, true}, + /* PSBT v3 - invalid version number */ {"cHNidP8B+wQDAAAAAQIEAgAAAAEFAQAA", false, true}, diff --git a/src/data/psbt.json b/src/data/psbt.json index 55859450a..d7baed78b 100644 --- a/src/data/psbt.json +++ b/src/data/psbt.json @@ -112,6 +112,10 @@ "comment": "PSBT v0 with duplicate 0 length script", "psbt": "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQgBAAEIAwEBUQA=" }, + { + "comment": "PSBT v0 with one P2PKH input. Outputs are empty. With trailing byte 0x00", + "psbt": "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAAAA==" + }, { "comment": "PSBT v2 With Global tx version number < 2", "psbt": "cHNidP8B+wQCAAAAAQIEAQAAAAEDBAECAwQBBAEAAQUBAAA=" @@ -128,6 +132,10 @@ "comment": "PSBT v2 missing tx version", "psbt": "cHNidP8B+wQCAAAAAQQBAAEFAQAA" }, + { + "comment": "PSBT v2 (no inputs, no outputs) with trailing byte 0x00", + "psbt": "cHNidP8BAgQCAAAAAQMEAAAAAAEEAQABBQEAAfsEAgAAAAAA" + }, { "comment": "PSBT v3 - invalid version number", "psbt": "cHNidP8B+wQDAAAAAQIEAgAAAAEFAQAA" diff --git a/src/psbt.c b/src/psbt.c index 5806aab88..5b2224d48 100644 --- a/src/psbt.c +++ b/src/psbt.c @@ -2830,6 +2830,8 @@ int wally_psbt_from_bytes(const unsigned char *bytes, size_t len, if (ret == WALLY_OK && !*cursor) ret = WALLY_EINVAL; /* Ran out of data */ + else if (ret == WALLY_OK && *max != 0) + ret = WALLY_EINVAL; /* Trailing data */ if (ret != WALLY_OK) { wally_psbt_free(*output);