assets: improve empty ticker support
What changed, and why it matters
This commit hardens how the Blockstream Jade hardware wallet handles assets that have no ticker symbol. Previously, if an asset's ticker was missing (NULL), the code could pass a NULL pointer to string-length functions, which can cause crashes or undefined behavior. The fix substitutes a single-space placeholder string for missing tickers and adds a test case for such an asset. It is a defensive robustness improvement rather than a confirmed exploitable vulnerability.
Treat as a low-risk hardening fix. Review whether any other asset_info fields (issuer_domain, asset_id, etc.) can be NULL and apply similar guards. Verify the new test passes and consider backporting to supported firmware branches.
Security signals we found
NULL-pointer dereference risk in asset ticker handling
Defensive null-check added before strlen()
New test fixture for NULL ticker asset path
Memory-safety hardening in asset metadata parsing
Evidence from the diff
In main/assets.c, assets_get_info() now checks snapshot_asset->ticker before assigning it. If the ticker is NULL, it uses the new ASSET_EMPTY_TICKER macro (defined in main/assets.h as a one-space string) and computes strlen() on the guaranteed non-NULL pointer. A new test fixture, liquid_tx_snapshot_null_ticker.json, exercises signing a Liquid transaction whose output asset has a NULL ticker. The change prevents potential NULL-pointer dereferences/undefined behavior when displaying or processing snapshot assets without tickers.
Changed components
main/assets.cmain/assets.hLiquid asset snapshot handlingTransaction signing UI/data pathInspect captured patch +30 / −2
### main/assets.c
@@ -255,8 +255,9 @@ bool assets_get_info(const network_t network_id, const asset_info_t* assets, con
asset_info_out->issuer_domain = snapshot_asset->issuer_domain;
asset_info_out->issuer_domain_len = strlen(snapshot_asset->issuer_domain);
- asset_info_out->ticker = snapshot_asset->ticker;
- asset_info_out->ticker_len = strlen(snapshot_asset->ticker);
+ // Assets without a ticker are displayed with a common empty ticker string
+ asset_info_out->ticker = snapshot_asset->ticker ? snapshot_asset->ticker : ASSET_EMPTY_TICKER;
+ asset_info_out->ticker_len = strlen(asset_info_out->ticker);
asset_info_out->precision = snapshot_asset->precision;
return true;
### main/assets.h
@@ -12,6 +12,9 @@
#define ASSET_TICKER_MIN_LEN 3
#define ASSET_TICKER_MAX_LEN 24
+// String replacing an empty (NULL) ticker for snapshot assets
+#define ASSET_EMPTY_TICKER " "
+
// NOTE: strings here may not be nul-terminated as may directly reference message fields
typedef struct _asset_info {
const char* asset_id;
### tests/rpc/data/sign_tx/liquid_tx_snapshot_null_ticker.json
@@ -0,0 +1,24 @@
+{
+ "input": {
+ "network": "localtest-liquid",
+ "txn": "0x0200000000012413047d152348db4342763a0eece0d99e6e2983b3b46eda07ede58d28f201ad0100000000ffffffff020193e3fb28a01fb15d6b93854f13cff416f686b6bc01056184bcff18b89b0bf7000100000000000000010017a9142e0ef2990318d8c9f7cee627650ba2a84fdda449870125b251070e29ca19043cf33ccd7324e2ddab03ecc4ae0b5e77c4fc0e5cf6c95a0100000000000f4240000000000000",
+ "trusted_commitments": [
+ null,
+ null
+ ],
+ "change": null,
+ "inputs": [
+ {
+ "is_witness": false,
+ "script": "0x76a9145f4fcd4a757c2abf6a0691f59dffae18852bbd7388ac",
+ "path": [
+ 0
+ ]
+ }
+ ]
+ },
+ "expected_output": [
+ "0x304402204522e729c1ec9c59b33c4ffdf7b93a60a54ff7401513c24e33ed1810789f22c9022003812f813fe6e70c5470e8fd4121fc57e39018c5543d6cb1b103d13f1338671c01"
+ ],
+ "description": "Output has a snapshot asset \"Sphinx test badge\" with a NULL ticker"
+}Why this scored 29/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.