Skip to content

Commit b7bf681

Browse files
authored
fix(xdr): reject AssetCode12 JSON codes shorter than 5 bytes (#1585)
1 parent a4bc598 commit b7bf681

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

src/xdr/values/to-json.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,14 @@ OVERRIDES.set("AssetCode12", {
737737
if (typeof json !== "string") {
738738
throw new XdrError("AssetCode12: expected escaped-string JSON");
739739
}
740-
return padRightZeros(XdrString.fromJson(json).bytes, 12);
740+
const bytes = XdrString.fromJson(json).bytes;
741+
if (bytes.length < 5) {
742+
throw new XdrError(
743+
"AssetCode12: code must be at least 5 bytes; " +
744+
"use AssetCode4 for shorter codes",
745+
);
746+
}
747+
return padRightZeros(bytes, 12);
741748
},
742749
});
743750

test/unit/xdr/to_json.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,33 @@ describe("SEP-0051 conformance — Stellar-specific asset codes & integers", ()
10591059
expect(json.asset_code).toBe("USDTether");
10601060
});
10611061

1062+
it("AssetCode12.fromJson rejects codes shorter than 5 bytes", () => {
1063+
expect(() => AssetCode12.fromJson("USD")).toThrow(/at least 5 bytes/);
1064+
expect(() => AssetCode12.fromJson("")).toThrow(/at least 5 bytes/);
1065+
expect(() => AssetCode12.fromJson("ABCD")).toThrow(/at least 5 bytes/);
1066+
// 5 escaped bytes (3 chars + 2 NULs, as toJson emits) are still accepted.
1067+
expect(Array.from(AssetCode12.fromJson("ABC\\0\\0").value)).toEqual([
1068+
65, 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1069+
]);
1070+
});
1071+
1072+
it("Asset.fromJson rejects a credit_alphanum12 code shorter than 5 bytes", () => {
1073+
expect(() =>
1074+
Asset.fromJson({
1075+
credit_alphanum12: { asset_code: "USD", issuer: STRKEY },
1076+
}),
1077+
).toThrow(/at least 5 bytes/);
1078+
});
1079+
1080+
it("Asset.fromJson keeps the alphanum12 discriminant for genuine 5-12 byte codes", () => {
1081+
const round = Asset.fromJson({
1082+
credit_alphanum12: { asset_code: "USDTether", issuer: STRKEY },
1083+
});
1084+
const wire = round.toXdr();
1085+
// AssetType discriminant is the first 4 bytes: 2 = ASSET_TYPE_CREDIT_ALPHANUM12.
1086+
expect(Array.from(wire.slice(0, 4))).toEqual([0, 0, 0, 2]);
1087+
});
1088+
10621089
it("rule 28: Int128Parts → decimal string", () => {
10631090
expect(
10641091
ScVal.scvI128(new Int128Parts({ hi: 0n, lo: 12345n })).toJson(),

0 commit comments

Comments
 (0)