commit 9eaae59b79fdaf8385e84c944383e7e7571d721b
parent 9fab59bfda03a8c32bcaef131cd84c8c6cb634f6
Author: Florian Dold <dold@taler.net>
Date: Tue, 21 Jul 2026 11:43:23 +0200
util: test that toFullString does not rewrite the URI
Diffstat:
1 file changed, 39 insertions(+), 0 deletions(-)
diff --git a/packages/taler-util/src/payto.test.ts b/packages/taler-util/src/payto.test.ts
@@ -340,3 +340,42 @@ test("payto bitcoin accepts every witness version", (t) => {
"error",
);
});
+
+test("toFullString does not rewrite the URI", (t) => {
+ // The full payto is hashed verbatim by TALER_full_payto_hash, so it must
+ // not be routed through a URL parser: that resolves dot segments and
+ // percent-encodes spaces, making the string that is hashed and the string
+ // that is paid name different accounts.
+ const cases: Array<[string, string]> = [
+ [
+ "payto://x-taler-bank/bank.com/../../evil/acct",
+ "payto://x-taler-bank/bank.com/../../evil/acct",
+ ],
+ ["payto://void/a/../b", "payto://void/a/../b"],
+ [
+ "payto://x-taler-bank/bank.com/ac ct",
+ "payto://x-taler-bank/bank.com/ac ct",
+ ],
+ ];
+ for (const [input, expected] of cases) {
+ const r = Paytos.fromString(input);
+ assert.strictEqual(r.tag, "ok", input);
+ assert.strictEqual(Paytos.toFullString(Result.unpack(r)), expected);
+ }
+});
+
+test("toFullString keeps the query parameters", (t) => {
+ const r = Paytos.fromString(
+ "payto://iban/DE75512108001245126199?receiver-name=Ann&msg=a%2Fb",
+ );
+ assert.strictEqual(r.tag, "ok");
+ const full = Paytos.toFullString(Result.unpack(r));
+ assert.strictEqual(
+ full,
+ "payto://iban/DE75512108001245126199?receiver-name=Ann&msg=a%2Fb",
+ );
+ // and the round trip still holds
+ const again = Paytos.fromString(full);
+ assert.strictEqual(again.tag, "ok");
+ assert.strictEqual(Paytos.toFullString(Result.unpack(again)), full);
+});