Properly exclude SWAP-related code if ENABLE_SWAP != 1
What changed, and why it matters
This commit is a build-system cleanup for Ledger's Bitcoin app. It wraps all code related to the optional 'SWAP' feature inside #ifdef HAVE_SWAP guards so that, when the app is compiled without SWAP support, none of that code is compiled or linked. The change removes unconditional references to swap-specific global variables and functions from non-swap source files. On its own this is a hardening/compilation-fix change rather than a fix for an active, exploitable vulnerability in already-shipped code.
Treat as a defensive build-hardening commit. Review that HAVE_SWAP is correctly defined in all build configurations and that no other optional feature leaves similar dead-code references. No urgent patch deployment is indicated by the diff alone, but verify the change compiles cleanly for both SWAP and non-SWAP targets.
Security signals we found
Build-time feature gating for optional SWAP code paths
Removal of unconditional references to swap-specific globals from core handlers
No change to transaction signing, address derivation, or user-confirmation logic when SWAP is enabled
No explicit vulnerability, CVE, or security incident described in commit message
Evidence from the diff
The patch gates the entire contents of src/swap/.c and src/swap/.h behind #ifdef HAVE_SWAP, and removes unconditional #include ‘swap_globals.h’ from io_ext.c, get_wallet_address.c and main.c. It also wraps runtime uses of G_called_from_swap and G_swap_state in the same guard. This prevents compilation failures and removes dead code paths when ENABLE_SWAP != 1. The commit does not change any logic when HAVE_SWAP is defined, nor does it alter cryptographic, parsing, or authorization behavior.
Changed components
src/boilerplate/io_ext.csrc/handler/get_wallet_address.csrc/handler/sign_psbt.csrc/main.csrc/swap/bip32_path.csrc/swap/bip32_path.hsrc/swap/handle_check_address.csrc/swap/handle_get_printable_amount.csrc/swap/handle_swap_sign_transaction.csrc/swap/handle_swap_sign_transaction.hsrc/swap/swap_globals.csrc/swap/swap_globals.hInspect captured patch +56 / −7
diff --git a/src/boilerplate/io_ext.c b/src/boilerplate/io_ext.c
index 537d6c7..61ff7b1 100644
--- a/src/boilerplate/io_ext.c
+++ b/src/boilerplate/io_ext.c
@@ -33,7 +33,6 @@
#include "dispatcher.h"
#include "display.h"
#include "sw.h"
-#include "swap_globals.h"
uint16_t G_output_len = 0;
@@ -80,9 +79,13 @@ void ioe_reset_timeouts() {
void ioe_show_processing_screen() {
if (!G_was_processing_screen_shown) {
G_was_processing_screen_shown = true;
+#ifdef HAVE_SWAP
if (!G_called_from_swap) {
+#endif /* HAVE_SWAP */
nbgl_useCaseSpinner(ui_get_processing_screen_text());
+#ifdef HAVE_SWAP
}
+#endif /* HAVE_SWAP */
}
}
diff --git a/src/debug-helpers/debug.c b/src/debug-helpers/debug.c
index f64245b..5c9ad33 100644
--- a/src/debug-helpers/debug.c
+++ b/src/debug-helpers/debug.c
@@ -45,4 +45,4 @@ void print_stack_pointer(const char *file, int line, const char *func_name) {
(void) file, (void) line, (void) func_name; // avoid warnings when DEBUG == 0
PRINTF("STACK (%s) %s:%d: %08x\n", func_name, file, line, get_stack_pointer());
-}
\ No newline at end of file
+}
diff --git a/src/handler/get_wallet_address.c b/src/handler/get_wallet_address.c
index 71364a3..b152fb7 100644
--- a/src/handler/get_wallet_address.c
+++ b/src/handler/get_wallet_address.c
@@ -42,7 +42,6 @@
#include "script.h"
#include "segwit_addr.h"
#include "sw.h"
-#include "swap_globals.h"
#include "wallet.h"
void handler_get_wallet_address(dispatcher_context_t *dc, uint8_t protocol_version) {
@@ -155,12 +154,14 @@ void handler_get_wallet_address(dispatcher_context_t *dc, uint8_t protocol_versi
is_wallet_default = false;
}
+#ifdef HAVE_SWAP
// Swap feature: check that the wallet policy is a default one
if (G_called_from_swap && !is_wallet_default) {
PRINTF("Must be a default wallet policy for swap feature\n");
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_NONDEFAULT_POLICY);
finalize_exchange_sign_transaction(false);
}
+#endif /* HAVE_SWAP */
{
uint8_t computed_wallet_id[32];
diff --git a/src/handler/sign_psbt.c b/src/handler/sign_psbt.c
index c323c79..0957ec7 100644
--- a/src/handler/sign_psbt.c
+++ b/src/handler/sign_psbt.c
@@ -1021,6 +1021,7 @@ preprocess_outputs(dispatcher_context_t *dc,
return true;
}
+#ifdef HAVE_SWAP
static bool __attribute__((noinline))
execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
LOG_PROCESSOR(__FILE__, __LINE__, __func__);
@@ -1192,6 +1193,7 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
return true;
}
+#endif /* HAVE_SWAP */
static bool __attribute__((noinline))
display_output(dispatcher_context_t *dc,
@@ -2167,6 +2169,7 @@ void handler_sign_psbt(dispatcher_context_t *dc, uint8_t protocol_version) {
// we execute the signing flow only if we're expected to produce any signature
// (including, possibly, any MuSig2 partial signature from Round 2 of MuSig2)
if (!only_signing_for_musig || st.has_musig2_pub_nonces) {
+#ifdef HAVE_SWAP
if (G_called_from_swap) {
/** SWAP CHECKS
*
@@ -2175,7 +2178,9 @@ void handler_sign_psbt(dispatcher_context_t *dc, uint8_t protocol_version) {
// During swaps, the user approval was already obtained in the exchange app
if (!execute_swap_checks(dc, &st)) return;
- } else {
+ } else
+#endif /* HAVE_SWAP */
+ {
/** TRANSACTION CONFIRMATION
*
* Display each non-change output, and transaction fees, and acquire user confirmation,
@@ -2193,7 +2198,10 @@ void handler_sign_psbt(dispatcher_context_t *dc, uint8_t protocol_version) {
*/
int sign_result = sign_transaction(dc, &st, cache, &signing_state, internal_inputs);
- if (!G_called_from_swap) {
+#ifdef HAVE_SWAP
+ if (!G_called_from_swap)
+#endif /* HAVE_SWAP */
+ {
ui_post_processing_confirm_transaction(dc, sign_result);
}
@@ -2201,10 +2209,12 @@ void handler_sign_psbt(dispatcher_context_t *dc, uint8_t protocol_version) {
return;
}
+#ifdef HAVE_SWAP
// Only if called from swap, the app should terminate after sending the response
if (G_called_from_swap) {
G_swap_state.should_exit = true;
}
+#endif /* HAVE_SWAP */
}
// MuSig2: if there is an active session at the end of round 1, we move it to persistent
diff --git a/src/main.c b/src/main.c
index 0d6bf3e..c2d6e5c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -38,7 +38,6 @@
#include "parser.h"
#include "sw.h"
#include "swap_globals.h"
-#include "swap_lib_calls.h"
#include "wallet.h"
#ifdef HAVE_BOLOS_APP_STACK_CANARY
@@ -91,7 +90,9 @@ static void initialize_app_globals() {
// we need the globals initialization to happen _after_ calling copy_transaction_parameters when
// processing a SIGN_TRANSACTION request from the swap app (which initializes the other fields
// of G_swap_state).
+#ifdef HAVE_SWAP
G_swap_state.should_exit = false;
+#endif /* HAVE_SWAP */
}
/**
@@ -147,7 +148,7 @@ void app_main() {
cmd.lc,
cmd.lc,
cmd.data);
-
+#ifdef HAVE_SWAP
if (G_called_from_swap) {
if (cmd.cla != CLA_APP) {
ioe_send_sw(SW_CLA_NOT_SUPPORTED);
@@ -163,14 +164,17 @@ void app_main() {
}
}
+#endif /* HAVE_SWAP */
// Dispatch structured APDU command to handler
apdu_dispatcher(COMMAND_DESCRIPTORS,
sizeof(COMMAND_DESCRIPTORS) / sizeof(COMMAND_DESCRIPTORS[0]),
ui_menu_main,
&cmd);
+#ifdef HAVE_SWAP
if (G_called_from_swap && G_swap_state.should_exit) {
// Bitcoin app will keep listening as long as it does not receive a valid TX
finalize_exchange_sign_transaction(true);
}
+#endif /* HAVE_SWAP */
}
}
diff --git a/src/swap/bip32_path.c b/src/swap/bip32_path.c
index 2d08007..1af5bfe 100644
--- a/src/swap/bip32_path.c
+++ b/src/swap/bip32_path.c
@@ -1,3 +1,4 @@
+#ifdef HAVE_SWAP
#include "bip32_path.h"
@@ -17,3 +18,5 @@ bool parse_serialized_path(bip32_path_t* path,
}
return true;
}
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/bip32_path.h b/src/swap/bip32_path.h
index 8abf7ad..521ace0 100644
--- a/src/swap/bip32_path.h
+++ b/src/swap/bip32_path.h
@@ -1,5 +1,7 @@
#pragma once
+#ifdef HAVE_SWAP
+
#include <stdbool.h>
/* SDK headers */
@@ -16,3 +18,5 @@ typedef struct bip32_path {
bool parse_serialized_path(bip32_path_t* path,
unsigned char* serialized_path,
unsigned char serialized_path_length);
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/handle_check_address.c b/src/swap/handle_check_address.c
index c3c472f..74eac53 100644
--- a/src/swap/handle_check_address.c
+++ b/src/swap/handle_check_address.c
@@ -1,3 +1,5 @@
+#ifdef HAVE_SWAP
+
#include <string.h>
/* SDK headers */
@@ -134,3 +136,5 @@ void swap_handle_check_address(check_address_parameters_t* params) {
PRINTF("Addresses match\n");
params->result = 1;
}
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/handle_get_printable_amount.c b/src/swap/handle_get_printable_amount.c
index 2af6bc1..ea9989e 100644
--- a/src/swap/handle_get_printable_amount.c
+++ b/src/swap/handle_get_printable_amount.c
@@ -1,3 +1,5 @@
+#ifdef HAVE_SWAP
+
/* SDK headers */
#include "read.h"
#include "swap_lib_calls.h"
@@ -23,3 +25,5 @@ void swap_handle_get_printable_amount(get_printable_amount_parameters_t *params)
(uint64_t) (read_u64_be(amount, 0)), // Cast prevents weird compilo bug
params->printable_amount);
}
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/handle_swap_sign_transaction.c b/src/swap/handle_swap_sign_transaction.c
index a8f0d9b..5f446e1 100644
--- a/src/swap/handle_swap_sign_transaction.c
+++ b/src/swap/handle_swap_sign_transaction.c
@@ -1,3 +1,5 @@
+#ifdef HAVE_SWAP
+
#include <assert.h>
#include "handle_swap_sign_transaction.h"
@@ -94,3 +96,5 @@ void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_succes
*G_swap_sign_return_value_address = is_success;
os_lib_end();
}
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/handle_swap_sign_transaction.h b/src/swap/handle_swap_sign_transaction.h
index cecb0f9..8e2a785 100644
--- a/src/swap/handle_swap_sign_transaction.h
+++ b/src/swap/handle_swap_sign_transaction.h
@@ -1,3 +1,7 @@
#pragma once
+#ifdef HAVE_SWAP
+
void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_success);
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/swap_globals.c b/src/swap/swap_globals.c
index 2f4f56f..0cda290 100644
--- a/src/swap/swap_globals.c
+++ b/src/swap/swap_globals.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_SWAP
+
#include "swap_globals.h"
swap_globals_t G_swap_state;
+
+#endif /* HAVE_SWAP */
diff --git a/src/swap/swap_globals.h b/src/swap/swap_globals.h
index a9f0b06..b8aeefb 100644
--- a/src/swap/swap_globals.h
+++ b/src/swap/swap_globals.h
@@ -1,5 +1,7 @@
#pragma once
+#ifdef HAVE_SWAP
+
#include <stdint.h>
enum {
@@ -18,3 +20,5 @@ typedef struct swap_globals_s {
} swap_globals_t;
extern swap_globals_t G_swap_state;
+
+#endif /* HAVE_SWAP */
Why this scored 26/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.