What changed, and why it matters
This commit changes how a Keystone hardware wallet displays the destination asset for TRON (TRX) swap transactions. It adds a mapping from short/raw asset codes (like 'b' for BTC, 'e' for ETH) to human-readable names, normalizes case, strips suffixes, and handles chain/asset separators. The change is a UI/display fix for swap transaction memos, not a core cryptographic or signing change. There is no explicit security claim in the commit or supplied references.
Review whether the parsed asset name is the only user-facing indicator for swap destination, and ensure the mapping covers all assets supported by the integrated swap provider. Consider adding unit tests for memo parsing edge cases (missing colons, empty asset fields, long asset strings, unknown identifiers). No urgent security patch is indicated by the diff alone.
Security signals we found
UI parsing of untrusted swap memo data
Normalization/mapping of asset identifiers shown to user before signing
Use of bounded string helpers (strncpy_s, strcpy_s) with local temp buffer
No change to signing, approval, or cryptographic code paths
Evidence from the diff
The patch modifies GetTrxSwapDstAsset() in src/ui/gui_chain/multi/web3/gui_trx.c to parse the destination asset from a THORChain-style memo field. It introduces map_thor_asset_name() to map one/two-letter raw asset identifiers to canonical names, adds lower/upper case conversion helpers, strips a trailing ‘-…’ suffix, and collapses redundant chain.asset forms (e.g., ‘BTC.BTC’ -> ‘BTC’). A new ConvertToUpperCase() utility is added in src/utils/user_utils.c/h. The change is defensive UI normalization; it does not alter transaction signing, approval logic, or address derivation. No buffer overflow is evident: strncpy_s/strcpy_s are used with bounded lengths and a 64-byte temp buffer.
Changed components
src/ui/gui_chain/multi/web3/gui_trx.csrc/utils/user_utils.csrc/utils/user_utils.hInspect captured patch +66 / −4
diff --git a/src/ui/gui_chain/multi/web3/gui_trx.c b/src/ui/gui_chain/multi/web3/gui_trx.c
index 313912c..47c9720 100644
--- a/src/ui/gui_chain/multi/web3/gui_trx.c
+++ b/src/ui/gui_chain/multi/web3/gui_trx.c
@@ -130,6 +130,28 @@ void GetTrxToken(void *indata, void *param, uint32_t maxLen)
strcpy_s((char *)indata, maxLen, trx->detail->token);
}
+static const char* map_thor_asset_name(const char* raw) {
+ if (strcmp(raw, "b") == 0) return "BTC";
+ if (strcmp(raw, "e") == 0) return "ETH";
+ if (strcmp(raw, "r") == 0 || strcmp(raw, "rune") == 0) return "RUNE";
+ if (strcmp(raw, "a") == 0) return "AVAX";
+ if (strcmp(raw, "s") == 0) return "BSC";
+ if (strcmp(raw, "f") == 0) return "BASE.ETH";
+ if (strcmp(raw, "g") == 0) return "ATOM";
+ if (strcmp(raw, "l") == 0) return "LTC";
+ if (strcmp(raw, "c") == 0) return "BCH";
+ if (strcmp(raw, "d") == 0) return "DOGE";
+ if (strcmp(raw, "p") == 0) return "POL";
+ if (strcmp(raw, "x") == 0) return "XRP";
+ if (strcmp(raw, "o") == 0) return "SOL";
+ if (strcmp(raw, "z") == 0) return "ZEC";
+ if (strcmp(raw, "u") == 0) return "SUI";
+ if (strcmp(raw, "tr") == 0) return "TRX";
+ if (strcmp(raw, "ad") == 0) return "ADA";
+
+ return raw;
+}
+
void GetTrxSwapDstAsset(void *indata, void *param, uint32_t maxLen)
{
DisplayTron *trx = (DisplayTron *)param;
@@ -150,17 +172,47 @@ void GetTrxSwapDstAsset(void *indata, void *param, uint32_t maxLen)
const char *start = first_colon + 1;
const char *second_colon = strchr(start, ':');
+ char temp[64] = {0};
+ size_t len = 0;
+
if (second_colon) {
- size_t len = second_colon - start;
- if (len >= maxLen) len = maxLen - 1;
- strncpy_s(out, maxLen, start, len);
+ len = second_colon - start;
+ } else {
+ len = strlen(start);
+ }
+
+ if (len >= sizeof(temp)) len = sizeof(temp) - 1;
+ strncpy_s(temp, sizeof(temp), start, len);
+ temp[len] = '\0';
+
+ char *dash = strchr(temp, '-');
+ if (dash) {
+ *dash = '\0';
+ }
+
+ ConvertToLowerCase(temp);
+ const char *final_name = map_thor_asset_name(temp);
+
+ if (final_name != temp) {
+ strcpy_s(out, maxLen, final_name);
} else {
- strcpy_s(out, maxLen, start);
+ ConvertToUpperCase(temp);
+ char *separator = strpbrk(temp, "./~-");
+ if (separator) {
+ size_t chainLen = separator - temp;
+ const char *assetPart = separator + 1;
+
+ if (strncmp(temp, assetPart, chainLen) == 0 && assetPart[chainLen] == '\0') {
+ *separator = '\0';
+ }
+ }
+ strcpy_s(out, maxLen, temp);
}
}
void GetTrxSwapDstAddress(void *indata, void *param, uint32_t maxLen)
{
+ //do a mapping
DisplayTron *trx = (DisplayTron *)param;
const char *memo = trx->detail->memo;
char *out = (char *)indata;
diff --git a/src/utils/user_utils.c b/src/utils/user_utils.c
index ac30ccd..204a7b9 100644
--- a/src/utils/user_utils.c
+++ b/src/utils/user_utils.c
@@ -165,6 +165,15 @@ void ConvertToLowerCase(char *str)
}
}
+void ConvertToUpperCase(char *str)
+{
+ if (str == NULL) return;
+ while (*str) {
+ *str = (char)toupper((unsigned char)*str);
+ str++;
+ }
+}
+
inline bool CheckContainsNull(const char *str, size_t maxLen)
{
for (size_t len = 0; len < maxLen; ++len) {
diff --git a/src/utils/user_utils.h b/src/utils/user_utils.h
index 8b6ec17..539329a 100644
--- a/src/utils/user_utils.h
+++ b/src/utils/user_utils.h
@@ -23,6 +23,7 @@ void RemoveFormatChar(char *str);
void ArrayRandom(char *words, char *out, int count);
int WordsListSlice(char *words, char wordsList[][10], uint8_t wordsCount);
void ConvertToLowerCase(char *str);
+void ConvertToUpperCase(char *str);
int FindStringCharPosition(const char *str, const char destChar, int index);
int32_t GetIntValue(const cJSON *obj, const char *key, int32_t defaultValue);
void GetStringValue(const cJSON *obj, const char *key, char *value, uint32_t maxLen);
Why this scored 34/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.