diff --git a/apdu_runner.c b/apdu_runner.c index 0281018..82618bc 100644 --- a/apdu_runner.c +++ b/apdu_runner.c @@ -8,7 +8,7 @@ #define TAG "APDU_Runner" // Max length of firmware upgrade: 731 bytes -#define SEADER_APDU_MAX_LEN 732 +#define SEADER_APDU_MAX_LEN 732 #define SEADER_APDU_RUNNER_HEX_LOG_MAX_BYTES 32U void seader_apdu_runner_cleanup(Seader* seader, SeaderWorkerEvent event) { diff --git a/ccid.c b/ccid.c index 2235762..bd73213 100644 --- a/ccid.c +++ b/ccid.c @@ -1,7 +1,7 @@ #include "seader_i.h" #include "ccid_logic.h" -#define TAG "SeaderCCID" +#define TAG "SeaderCCID" #define SEADER_CCID_HEX_LOG_MAX_BYTES 32U const uint8_t SAM_ATR[] = {0x3b, 0x95, 0x96, 0x80, 0xb1, 0xfe, 0x55, 0x1f, 0xc7, 0x47, 0x72, 0x61, 0x63, 0x65, 0x13}; @@ -44,8 +44,8 @@ static void seader_ccid_log_hex(const char* prefix, const uint8_t* data, size_t return; } - const size_t display_len = len > SEADER_CCID_HEX_LOG_MAX_BYTES ? SEADER_CCID_HEX_LOG_MAX_BYTES : - len; + const size_t display_len = + len > SEADER_CCID_HEX_LOG_MAX_BYTES ? SEADER_CCID_HEX_LOG_MAX_BYTES : len; char hex[(SEADER_CCID_HEX_LOG_MAX_BYTES * 2U) + 1U]; for(size_t i = 0; i < display_len; i++) { diff --git a/hf_interface_fal/hf.c b/hf_interface_fal/hf.c index 317284b..5cfe60f 100644 --- a/hf_interface_fal/hf.c +++ b/hf_interface_fal/hf.c @@ -247,7 +247,7 @@ static void plugin_hf_iso14443a_transmit( return; } - BitBuffer* tx_buffer = bit_buffer_alloc(len + 1); + BitBuffer* tx_buffer = bit_buffer_alloc(len + 1U); BitBuffer* rx_buffer = bit_buffer_alloc(HF_PLUGIN_POLLER_MAX_BUFFER_SIZE); if(!tx_buffer || !rx_buffer) { FURI_LOG_E(TAG, "Failed to allocate 14A buffers"); diff --git a/lib/host_tests/t_1_host_env.h b/lib/host_tests/t_1_host_env.h index 3602afa..52ef0d6 100644 --- a/lib/host_tests/t_1_host_env.h +++ b/lib/host_tests/t_1_host_env.h @@ -12,7 +12,7 @@ #include "t_1_logic.h" /* Keep the host harness aligned with the production UART scratchpad size. */ -#define SEADER_UART_RX_BUF_SIZE (300) +#define SEADER_UART_RX_BUF_SIZE (272) #define FURI_LOG_W(tag, fmt, ...) ((void)0) #define furi_check(expr) \ do { \ diff --git a/sam_api.c b/sam_api.c index ff42cca..8287e25 100644 --- a/sam_api.c +++ b/sam_api.c @@ -355,8 +355,14 @@ PicopassError seader_worker_fake_epurse_update(BitBuffer* tx_buffer, BitBuffer* void seader_virtual_picopass_state_machine(Seader* seader, uint8_t* buffer, size_t len) { BitBuffer* tx_buffer = bit_buffer_alloc(len); - bit_buffer_append_bytes(tx_buffer, buffer, len); BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE); + if(!tx_buffer || !rx_buffer) { + FURI_LOG_E(TAG, "Failed to allocate virtual Picopass buffers"); + if(tx_buffer) bit_buffer_free(tx_buffer); + if(rx_buffer) bit_buffer_free(rx_buffer); + return; + } + bit_buffer_append_bytes(tx_buffer, buffer, len); uint8_t config[PICOPASS_BLOCK_LEN] = {0x12, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0xff, 0x3c}; uint8_t sr_aia[PICOPASS_BLOCK_LEN] = {0xFF, 0xff, 0xff, 0xff, 0xFF, 0xFf, 0xff, 0xFF}; @@ -1208,9 +1214,18 @@ void seader_iso15693_transmit( BitBuffer* tx_buffer = bit_buffer_alloc(len); BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE); - PicopassError error = PicopassErrorNone; + if(!tx_buffer || !rx_buffer) { + FURI_LOG_E(TAG, "Failed to allocate Picopass tx/rx buffers"); + if(tx_buffer) bit_buffer_free(tx_buffer); + if(rx_buffer) bit_buffer_free(rx_buffer); + if(seader_worker) { + seader_worker->stage = SeaderPollerEventTypeFail; + } + return; + } + do { bit_buffer_append_bytes(tx_buffer, buffer, len); @@ -1238,7 +1253,6 @@ void seader_iso15693_transmit( bit_buffer_get_size_bytes(rx_buffer)); } while(false); - bit_buffer_free(tx_buffer); bit_buffer_free(rx_buffer); } diff --git a/scenes/seader_scene_credential_info.c b/scenes/seader_scene_credential_info.c index 6961c89..b766aee 100644 --- a/scenes/seader_scene_credential_info.c +++ b/scenes/seader_scene_credential_info.c @@ -4,6 +4,46 @@ #define TAG "SeaderCredentialInfoScene" +static void seader_scene_credential_info_alloc_strings(Seader* seader) { + furi_check(seader); + if(!seader->temp_string1) { + seader->temp_string1 = furi_string_alloc(); + furi_check(seader->temp_string1); + } + if(!seader->temp_string2) { + seader->temp_string2 = furi_string_alloc(); + furi_check(seader->temp_string2); + } + if(!seader->temp_string3) { + seader->temp_string3 = furi_string_alloc(); + furi_check(seader->temp_string3); + } + if(!seader->temp_string4) { + seader->temp_string4 = furi_string_alloc(); + furi_check(seader->temp_string4); + } +} + +static void seader_scene_credential_info_free_strings(Seader* seader) { + furi_check(seader); + if(seader->temp_string1) { + furi_string_free(seader->temp_string1); + seader->temp_string1 = NULL; + } + if(seader->temp_string2) { + furi_string_free(seader->temp_string2); + seader->temp_string2 = NULL; + } + if(seader->temp_string3) { + furi_string_free(seader->temp_string3); + seader->temp_string3 = NULL; + } + if(seader->temp_string4) { + furi_string_free(seader->temp_string4); + seader->temp_string4 = NULL; + } +} + static bool seader_credential_is_picopass_sio_context(const SeaderCredential* credential) { return credential && (credential->type == SeaderCredentialTypePicopass || (credential->has_pacs_media_type && @@ -26,7 +66,7 @@ void seader_scene_credential_info_on_enter(void* context) { seader_wiegand_plugin_acquire(seader); Widget* widget = seader->widget; - // Use reusable strings instead of allocating new ones + seader_scene_credential_info_alloc_strings(seader); FuriString* type_str = seader->temp_string1; FuriString* bitlength_str = seader->temp_string2; FuriString* credential_str = seader->temp_string3; @@ -119,5 +159,6 @@ void seader_scene_credential_info_on_exit(void* context) { // Clear views widget_reset(seader->widget); + seader_scene_credential_info_free_strings(seader); seader_wiegand_plugin_release(seader); } diff --git a/scenes/seader_scene_formats.c b/scenes/seader_scene_formats.c index 7b0dbf3..66f4e44 100644 --- a/scenes/seader_scene_formats.c +++ b/scenes/seader_scene_formats.c @@ -1,11 +1,24 @@ #include "../seader_i.h" #include +static void seader_scene_formats_alloc_strings(Seader* seader) { + furi_check(seader); + if(!seader->text_box_store) { + seader->text_box_store = furi_string_alloc(); + furi_check(seader->text_box_store); + } + if(!seader->temp_string1) { + seader->temp_string1 = furi_string_alloc(); + furi_check(seader->temp_string1); + } +} + void seader_scene_formats_on_enter(void* context) { Seader* seader = context; PluginWiegand* plugin = seader_wiegand_plugin_acquire(seader) ? seader->plugin_wiegand : NULL; SeaderCredential* credential = seader->credential; + seader_scene_formats_alloc_strings(seader); FuriString* str = seader->text_box_store; furi_string_reset(str); @@ -51,5 +64,13 @@ void seader_scene_formats_on_exit(void* context) { // Clear views text_box_reset(seader->text_box); + if(seader->text_box_store) { + furi_string_free(seader->text_box_store); + seader->text_box_store = NULL; + } + if(seader->temp_string1) { + furi_string_free(seader->temp_string1); + seader->temp_string1 = NULL; + } seader_wiegand_plugin_release(seader); } diff --git a/scenes/seader_scene_read_card_success.c b/scenes/seader_scene_read_card_success.c index 124e568..4944186 100644 --- a/scenes/seader_scene_read_card_success.c +++ b/scenes/seader_scene_read_card_success.c @@ -4,6 +4,46 @@ #define TAG "SeaderSceneReadCardSuccess" +static void seader_scene_read_card_success_alloc_strings(Seader* seader) { + furi_check(seader); + if(!seader->temp_string1) { + seader->temp_string1 = furi_string_alloc(); + furi_check(seader->temp_string1); + } + if(!seader->temp_string2) { + seader->temp_string2 = furi_string_alloc(); + furi_check(seader->temp_string2); + } + if(!seader->temp_string3) { + seader->temp_string3 = furi_string_alloc(); + furi_check(seader->temp_string3); + } + if(!seader->temp_string4) { + seader->temp_string4 = furi_string_alloc(); + furi_check(seader->temp_string4); + } +} + +static void seader_scene_read_card_success_free_strings(Seader* seader) { + furi_check(seader); + if(seader->temp_string1) { + furi_string_free(seader->temp_string1); + seader->temp_string1 = NULL; + } + if(seader->temp_string2) { + furi_string_free(seader->temp_string2); + seader->temp_string2 = NULL; + } + if(seader->temp_string3) { + furi_string_free(seader->temp_string3); + seader->temp_string3 = NULL; + } + if(seader->temp_string4) { + furi_string_free(seader->temp_string4); + seader->temp_string4 = NULL; + } +} + static bool seader_credential_is_picopass_sio_context(const SeaderCredential* credential) { return credential && (credential->type == SeaderCredentialTypePicopass || (credential->has_pacs_media_type && @@ -28,7 +68,7 @@ void seader_scene_read_card_success_on_enter(void* context) { PluginWiegand* plugin = seader_wiegand_plugin_acquire(seader) ? seader->plugin_wiegand : NULL; Widget* widget = seader->widget; - // Use reusable strings instead of allocating new ones + seader_scene_read_card_success_alloc_strings(seader); FuriString* type_str = seader->temp_string1; FuriString* bitlength_str = seader->temp_string2; FuriString* credential_str = seader->temp_string3; @@ -166,5 +206,6 @@ void seader_scene_read_card_success_on_exit(void* context) { // Clear view widget_reset(seader->widget); + seader_scene_read_card_success_free_strings(seader); seader_wiegand_plugin_release(seader); } diff --git a/scenes/seader_scene_sam_info.c b/scenes/seader_scene_sam_info.c index 6b14dcc..e4dbc36 100644 --- a/scenes/seader_scene_sam_info.c +++ b/scenes/seader_scene_sam_info.c @@ -3,6 +3,38 @@ #define TAG "SeaderSamInfoScene" +static void seader_scene_sam_info_alloc_strings(Seader* seader) { + furi_check(seader); + if(!seader->temp_string1) { + seader->temp_string1 = furi_string_alloc(); + furi_check(seader->temp_string1); + } + if(!seader->temp_string2) { + seader->temp_string2 = furi_string_alloc(); + furi_check(seader->temp_string2); + } + if(!seader->temp_string3) { + seader->temp_string3 = furi_string_alloc(); + furi_check(seader->temp_string3); + } +} + +static void seader_scene_sam_info_free_strings(Seader* seader) { + furi_check(seader); + if(seader->temp_string1) { + furi_string_free(seader->temp_string1); + seader->temp_string1 = NULL; + } + if(seader->temp_string2) { + furi_string_free(seader->temp_string2); + seader->temp_string2 = NULL; + } + if(seader->temp_string3) { + furi_string_free(seader->temp_string3); + seader->temp_string3 = NULL; + } +} + void seader_scene_sam_info_widget_callback(GuiButtonType result, InputType type, void* context) { Seader* seader = context; if(type == InputTypeShort) { @@ -14,7 +46,7 @@ void seader_scene_sam_info_on_enter(void* context) { Seader* seader = context; Widget* widget = seader->widget; - // Use reusable string instead of allocating new one + seader_scene_sam_info_alloc_strings(seader); FuriString* fw_str = seader->temp_string1; FuriString* info_str = seader->temp_string2; FuriString* uhf_str = seader->temp_string3; @@ -66,4 +98,5 @@ void seader_scene_sam_info_on_exit(void* context) { // Clear views widget_reset(seader->widget); + seader_scene_sam_info_free_strings(seader); } diff --git a/scenes/seader_scene_save_name.c b/scenes/seader_scene_save_name.c index 25a93ce..b7dcbe9 100644 --- a/scenes/seader_scene_save_name.c +++ b/scenes/seader_scene_save_name.c @@ -21,10 +21,7 @@ void seader_scene_save_name_on_enter(void* context) { name_generator_make_random(seader->save_name_buf, sizeof(seader->save_name_buf)); cred_name_empty = true; } else { - strlcpy( - seader->save_name_buf, - seader->credential->name, - sizeof(seader->save_name_buf)); + strlcpy(seader->save_name_buf, seader->credential->name, sizeof(seader->save_name_buf)); } text_input_set_header_text(text_input, "Name the credential"); text_input_set_result_callback( @@ -35,8 +32,8 @@ void seader_scene_save_name_on_enter(void* context) { SEADER_CRED_NAME_MAX_LEN, cred_name_empty); - // Use reusable string instead of allocating new one - FuriString* folder_path = seader->temp_string1; + FuriString* folder_path = furi_string_alloc(); + furi_check(folder_path); if(furi_string_end_with(seader->credential->load_path, SEADER_APP_EXTENSION)) { path_extract_dirname(furi_string_get_cstr(seader->credential->load_path), folder_path); } else { @@ -48,8 +45,7 @@ void seader_scene_save_name_on_enter(void* context) { text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewTextInput); - - // No need to free folder_path as it's reused from seader struct + furi_string_free(folder_path); } bool seader_scene_save_name_on_event(void* context, SceneManagerEvent event) { @@ -64,9 +60,7 @@ bool seader_scene_save_name_on_event(void* context, SceneManagerEvent event) { seader_credential_delete(seader->credential, true); } strlcpy( - seader->credential->name, - seader->save_name_buf, - sizeof(seader->credential->name)); + seader->credential->name, seader->save_name_buf, sizeof(seader->credential->name)); if(seader_credential_save(seader->credential, seader->save_name_buf)) { scene_manager_next_scene(seader->scene_manager, SeaderSceneSaveSuccess); consumed = true; diff --git a/seader.c b/seader.c index 69e031e..b12ef54 100644 --- a/seader.c +++ b/seader.c @@ -533,18 +533,18 @@ Seader* seader_alloc() { seader->text_box = text_box_alloc(); view_dispatcher_add_view( seader->view_dispatcher, SeaderViewTextBox, text_box_get_view(seader->text_box)); - seader->text_box_store = furi_string_alloc(); + seader->text_box_store = NULL; // Custom Widget seader->widget = widget_alloc(); view_dispatcher_add_view( seader->view_dispatcher, SeaderViewWidget, widget_get_view(seader->widget)); - // Allocate reusable strings for scene optimization - seader->temp_string1 = furi_string_alloc(); - seader->temp_string2 = furi_string_alloc(); - seader->temp_string3 = furi_string_alloc(); - seader->temp_string4 = furi_string_alloc(); + // Scene strings are allocated lazily by the scenes that need them. + seader->temp_string1 = NULL; + seader->temp_string2 = NULL; + seader->temp_string3 = NULL; + seader->temp_string4 = NULL; seader->plugin_manager = NULL; seader->plugin_wiegand = NULL; @@ -618,17 +618,19 @@ void seader_free(Seader* seader) { // TextBox view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewTextBox); text_box_free(seader->text_box); - furi_string_free(seader->text_box_store); + if(seader->text_box_store) { + furi_string_free(seader->text_box_store); + } // Custom Widget view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewWidget); widget_free(seader->widget); // Free reusable strings - furi_string_free(seader->temp_string1); - furi_string_free(seader->temp_string2); - furi_string_free(seader->temp_string3); - furi_string_free(seader->temp_string4); + if(seader->temp_string1) furi_string_free(seader->temp_string1); + if(seader->temp_string2) furi_string_free(seader->temp_string2); + if(seader->temp_string3) furi_string_free(seader->temp_string3); + if(seader->temp_string4) furi_string_free(seader->temp_string4); // View Dispatcher view_dispatcher_free(seader->view_dispatcher); diff --git a/seader_bridge.h b/seader_bridge.h index 7d4afec..ec0e669 100644 --- a/seader_bridge.h +++ b/seader_bridge.h @@ -12,7 +12,7 @@ #include "t_1_logic.h" // https://ww1.microchip.com/downloads/en/DeviceDoc/00001561C.pdf -#define SEADER_UART_RX_BUF_SIZE (300) +#define SEADER_UART_RX_BUF_SIZE (272) #define SEADER_CCID_SLOT_COUNT (2U) typedef struct BitBuffer BitBuffer; diff --git a/seader_hf_read_plan.c b/seader_hf_read_plan.c index 6e9dd69..4228ae5 100644 --- a/seader_hf_read_plan.c +++ b/seader_hf_read_plan.c @@ -2,9 +2,7 @@ #define SEADER_HF_READ_PLAN_MAX_TYPES 3U -static void seader_hf_read_plan_add_type( - SeaderHfReadPlan* plan, - SeaderCredentialType type) { +static void seader_hf_read_plan_add_type(SeaderHfReadPlan* plan, SeaderCredentialType type) { if(type == SeaderCredentialTypeNone) { return; } diff --git a/seader_worker.c b/seader_worker.c index e17ec46..bdc64bf 100644 --- a/seader_worker.c +++ b/seader_worker.c @@ -7,8 +7,8 @@ #define TAG "SeaderWorker" -#define APDU_HEADER_LEN 5 -#define ASN1_PREFIX 6 +#define APDU_HEADER_LEN 5 +#define ASN1_PREFIX 6 #define SEADER_HEX_LOG_MAX_BYTES 32U // #define ASN1_DEBUG true @@ -69,10 +69,8 @@ static void seader_worker_release_apdu_slot(SeaderWorker* seader_worker, uint8_t } } -static bool seader_worker_dequeue_apdu( - SeaderWorker* seader_worker, - uint8_t* slot_index, - FuriWait timeout) { +static bool + seader_worker_dequeue_apdu(SeaderWorker* seader_worker, uint8_t* slot_index, FuriWait timeout) { furi_assert(seader_worker); furi_assert(slot_index); return furi_message_queue_get(seader_worker->messages, slot_index, timeout) == FuriStatusOk; @@ -250,10 +248,22 @@ SeaderWorker* seader_worker_alloc() { // Worker thread attributes seader_worker->thread = - furi_thread_alloc_ex("SeaderWorker", 6144, seader_worker_task, seader_worker); + furi_thread_alloc_ex("SeaderWorker", 5120, seader_worker_task, seader_worker); seader_worker->messages = furi_message_queue_alloc(2, sizeof(uint8_t)); seader_worker->apdu_slots = calloc(SEADER_WORKER_APDU_SLOT_COUNT, sizeof(SeaderAPDU)); + if(!seader_worker->thread || !seader_worker->messages || !seader_worker->apdu_slots) { + if(seader_worker->thread) { + furi_thread_free(seader_worker->thread); + } + if(seader_worker->messages) { + furi_message_queue_free(seader_worker->messages); + } + free(seader_worker->apdu_slots); + free(seader_worker); + return NULL; + } + seader_worker->callback = NULL; seader_worker->context = NULL; seader_worker->storage = furi_record_open(RECORD_STORAGE); @@ -559,14 +569,9 @@ void seader_worker_reading(Seader* seader) { SeaderWorker* seader_worker = seader->worker; FURI_LOG_I(TAG, "Reading loop started"); - if(!seader_hf_plugin_acquire(seader) || !seader->plugin_hf || !seader->hf_plugin_ctx) { - FURI_LOG_E(TAG, "HF plugin unavailable"); - strlcpy(seader->read_error, "HF plugin unavailable", sizeof(seader->read_error)); - if(seader_worker->callback) { - seader_worker->callback(SeaderWorkerEventFail, seader_worker->context); - } - return; - } + furi_check(seader_hf_plugin_acquire(seader)); + furi_check(seader->plugin_hf); + furi_check(seader->hf_plugin_ctx); while(seader_worker->state == SeaderWorkerStateReading) { bool detected = false; @@ -595,8 +600,8 @@ void seader_worker_reading(Seader* seader) { break; } else if(read_plan.decision == SeaderHfReadDecisionStartRead) { FURI_LOG_I(TAG, "HF start read for type=%d", read_plan.type_to_read); - detected = - seader->plugin_hf->start_read_for_type(seader->hf_plugin_ctx, read_plan.type_to_read); + detected = seader->plugin_hf->start_read_for_type( + seader->hf_plugin_ctx, read_plan.type_to_read); if(detected) { seader->hf_session_state = SeaderHfSessionStateActive; } diff --git a/t_1.c b/t_1.c index dad6d7f..be46805 100644 --- a/t_1.c +++ b/t_1.c @@ -6,7 +6,7 @@ #include "t_1_logic.h" -#define TAG "Seader:T=1" +#define TAG "Seader:T=1" #define SEADER_T1_MAX_FRAME_LEN (3U + SEADER_T1_IFS_MAX + 1U) static SeaderT1State* seader_t1_state(SeaderUartBridge* seader_uart) {