Просмотр исходного кода

[FL-2431, FL-2419] SubGhz: bugfixes (#1098)

* [FL-2431] SubGhz: fix Restart with an error (HardFault), while maintaining the RAW signal.
* Stream: fix adding maximum string length to arguments
* [FL-2419] SubGhz: fix flipper hang/Fatal Error when running edited Sub-GHz file.
* SubGhz: remove replace strcpy with strncpy, smaller text buffer and canary
* SubGhz: log key loading before load happen, rollback only rx message handling

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Skorpionm 3 лет назад
Родитель
Сommit
02b9cf90d5

+ 3 - 1
applications/storage/storage.h

@@ -297,13 +297,15 @@ bool storage_simply_mkdir(Storage* storage, const char* path);
  * @param filename 
  * @param filename 
  * @param fileextension 
  * @param fileextension 
  * @param nextfilename return name
  * @param nextfilename return name
+ * @param max_len  max len name
  */
  */
 void storage_get_next_filename(
 void storage_get_next_filename(
     Storage* storage,
     Storage* storage,
     const char* dirname,
     const char* dirname,
     const char* filename,
     const char* filename,
     const char* fileextension,
     const char* fileextension,
-    string_t nextfilename);
+    string_t nextfilename,
+    uint8_t max_len);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 3 - 3
applications/storage/storage_external_api.c

@@ -556,7 +556,8 @@ void storage_get_next_filename(
     const char* dirname,
     const char* dirname,
     const char* filename,
     const char* filename,
     const char* fileextension,
     const char* fileextension,
-    string_t nextfilename) {
+    string_t nextfilename,
+    uint8_t max_len) {
     string_t temp_str;
     string_t temp_str;
     uint16_t num = 0;
     uint16_t num = 0;
 
 
@@ -566,8 +567,7 @@ void storage_get_next_filename(
         num++;
         num++;
         string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension);
         string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension);
     }
     }
-
-    if(num) {
+    if(num && (max_len > strlen(filename))) {
         string_printf(nextfilename, "%s%d", filename, num);
         string_printf(nextfilename, "%s%d", filename, num);
     } else {
     } else {
         string_printf(nextfilename, "%s", filename);
         string_printf(nextfilename, "%s", filename);

+ 1 - 1
applications/subghz/scenes/subghz_scene_delete.c

@@ -49,7 +49,7 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SubGhzCustomEventSceneDelete) {
         if(event.event == SubGhzCustomEventSceneDelete) {
-            strcpy(subghz->file_name_tmp, subghz->file_name);
+            strncpy(subghz->file_name_tmp, subghz->file_name, SUBGHZ_MAX_LEN_NAME);
             if(subghz_delete_file(subghz)) {
             if(subghz_delete_file(subghz)) {
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
             } else {
             } else {

+ 1 - 1
applications/subghz/scenes/subghz_scene_delete_raw.c

@@ -56,7 +56,7 @@ bool subghz_scene_delete_raw_on_event(void* context, SceneManagerEvent event) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SubGhzCustomEventSceneDeleteRAW) {
         if(event.event == SubGhzCustomEventSceneDeleteRAW) {
-            strcpy(subghz->file_name_tmp, subghz->file_name);
+            strncpy(subghz->file_name_tmp, subghz->file_name, SUBGHZ_MAX_LEN_NAME);
             if(subghz_delete_file(subghz)) {
             if(subghz_delete_file(subghz)) {
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
             } else {
             } else {

+ 1 - 1
applications/subghz/scenes/subghz_scene_read_raw.c

@@ -24,7 +24,7 @@ bool subghz_scene_read_raw_update_filename(SubGhz* subghz) {
         }
         }
 
 
         path_extract_filename_no_ext(string_get_cstr(temp_str), temp_str);
         path_extract_filename_no_ext(string_get_cstr(temp_str), temp_str);
-        strcpy(subghz->file_name, string_get_cstr(temp_str));
+        strncpy(subghz->file_name, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME);
 
 
         ret = true;
         ret = true;
     } while(false);
     } while(false);

+ 4 - 4
applications/subghz/scenes/subghz_scene_save_name.c

@@ -22,10 +22,10 @@ void subghz_scene_save_name_on_enter(void* context) {
         //highlighting the entire filename by default
         //highlighting the entire filename by default
         dev_name_empty = true;
         dev_name_empty = true;
     } else {
     } else {
-        strcpy(subghz->file_name_tmp, subghz->file_name);
+        strncpy(subghz->file_name_tmp, subghz->file_name, SUBGHZ_MAX_LEN_NAME);
         if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
         if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
            SubGhzCustomEventManagerNoSet) {
            SubGhzCustomEventManagerNoSet) {
-            subghz_get_next_name_file(subghz);
+            subghz_get_next_name_file(subghz, SUBGHZ_MAX_LEN_NAME);
             if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
             if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
                SubGhzCustomEventManagerSetRAW) {
                SubGhzCustomEventManagerSetRAW) {
                 dev_name_empty = true;
                 dev_name_empty = true;
@@ -39,7 +39,7 @@ void subghz_scene_save_name_on_enter(void* context) {
         subghz_scene_save_name_text_input_callback,
         subghz_scene_save_name_text_input_callback,
         subghz,
         subghz,
         subghz->file_name,
         subghz->file_name,
-        22, //Max len name
+        SUBGHZ_MAX_LEN_NAME + 1, // buffer size
         dev_name_empty);
         dev_name_empty);
 
 
     ValidatorIsFile* validator_is_file =
     ValidatorIsFile* validator_is_file =
@@ -52,7 +52,7 @@ void subghz_scene_save_name_on_enter(void* context) {
 bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
 bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
     if(event.type == SceneManagerEventTypeBack) {
     if(event.type == SceneManagerEventTypeBack) {
-        strcpy(subghz->file_name, subghz->file_name_tmp);
+        strncpy(subghz->file_name, subghz->file_name_tmp, SUBGHZ_MAX_LEN_NAME);
         scene_manager_previous_scene(subghz->scene_manager);
         scene_manager_previous_scene(subghz->scene_manager);
         return true;
         return true;
     } else if(event.type == SceneManagerEventTypeCustom) {
     } else if(event.type == SceneManagerEventTypeCustom) {

+ 5 - 1
applications/subghz/subghz.c

@@ -296,6 +296,10 @@ void subghz_free(SubGhz* subghz) {
     furi_record_close("notification");
     furi_record_close("notification");
     subghz->notifications = NULL;
     subghz->notifications = NULL;
 
 
+    // About birds
+    furi_assert(subghz->file_name[SUBGHZ_MAX_LEN_NAME] == 0);
+    furi_assert(subghz->file_name_tmp[SUBGHZ_MAX_LEN_NAME] == 0);
+
     // The rest
     // The rest
     free(subghz);
     free(subghz);
 }
 }
@@ -315,7 +319,7 @@ int32_t subghz_app(void* p) {
             string_init(filename);
             string_init(filename);
 
 
             path_extract_filename_no_ext(p, filename);
             path_extract_filename_no_ext(p, filename);
-            strcpy(subghz->file_name, string_get_cstr(filename));
+            strncpy(subghz->file_name, string_get_cstr(filename), SUBGHZ_MAX_LEN_NAME);
             string_clear(filename);
             string_clear(filename);
             if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) {
             if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) {
                 //Load Raw TX
                 //Load Raw TX

+ 16 - 8
applications/subghz/subghz_i.c

@@ -208,7 +208,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
     bool loaded = false;
     bool loaded = false;
     string_t temp_str;
     string_t temp_str;
     string_init(temp_str);
     string_init(temp_str);
-    uint32_t version;
+    uint32_t temp_data32;
 
 
     do {
     do {
         stream_clean(fff_data_stream);
         stream_clean(fff_data_stream);
@@ -217,25 +217,30 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
             break;
             break;
         }
         }
 
 
-        if(!flipper_format_read_header(fff_data_file, temp_str, &version)) {
+        if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
             FURI_LOG_E(TAG, "Missing or incorrect header");
             FURI_LOG_E(TAG, "Missing or incorrect header");
             break;
             break;
         }
         }
 
 
         if(((!strcmp(string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
         if(((!strcmp(string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
             (!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
             (!strcmp(string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
-           version == SUBGHZ_KEY_FILE_VERSION) {
+           temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
         } else {
         } else {
             FURI_LOG_E(TAG, "Type or version mismatch");
             FURI_LOG_E(TAG, "Type or version mismatch");
             break;
             break;
         }
         }
 
 
-        if(!flipper_format_read_uint32(
-               fff_data_file, "Frequency", (uint32_t*)&subghz->txrx->frequency, 1)) {
+        if(!flipper_format_read_uint32(fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) {
             FURI_LOG_E(TAG, "Missing Frequency");
             FURI_LOG_E(TAG, "Missing Frequency");
             break;
             break;
         }
         }
 
 
+        if(!furi_hal_subghz_is_frequency_valid(temp_data32)) {
+            FURI_LOG_E(TAG, "Frequency not supported");
+            break;
+        }
+        subghz->txrx->frequency = temp_data32;
+
         if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
         if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
             FURI_LOG_E(TAG, "Missing Preset");
             FURI_LOG_E(TAG, "Missing Preset");
             break;
             break;
@@ -267,6 +272,9 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
         if(subghz->txrx->decoder_result) {
         if(subghz->txrx->decoder_result) {
             subghz_protocol_decoder_base_deserialize(
             subghz_protocol_decoder_base_deserialize(
                 subghz->txrx->decoder_result, subghz->txrx->fff_data);
                 subghz->txrx->decoder_result, subghz->txrx->fff_data);
+        } else {
+            FURI_LOG_E(TAG, "Protocol not found");
+            break;
         }
         }
 
 
         loaded = true;
         loaded = true;
@@ -283,7 +291,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
     return loaded;
     return loaded;
 }
 }
 
 
-bool subghz_get_next_name_file(SubGhz* subghz) {
+bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) {
     furi_assert(subghz);
     furi_assert(subghz);
 
 
     Storage* storage = furi_record_open("storage");
     Storage* storage = furi_record_open("storage");
@@ -294,9 +302,9 @@ bool subghz_get_next_name_file(SubGhz* subghz) {
     if(strcmp(subghz->file_name, "")) {
     if(strcmp(subghz->file_name, "")) {
         //get the name of the next free file
         //get the name of the next free file
         storage_get_next_filename(
         storage_get_next_filename(
-            storage, SUBGHZ_RAW_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str);
+            storage, SUBGHZ_RAW_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str, max_len);
 
 
-        strcpy(subghz->file_name, string_get_cstr(temp_str));
+        strncpy(subghz->file_name, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME);
         res = true;
         res = true;
     }
     }
 
 

+ 4 - 4
applications/subghz/subghz_i.h

@@ -33,7 +33,7 @@
 
 
 #include <gui/modules/variable_item_list.h>
 #include <gui/modules/variable_item_list.h>
 
 
-#define SUBGHZ_TEXT_STORE_SIZE 40
+#define SUBGHZ_MAX_LEN_NAME 21
 
 
 extern const char* const subghz_frequencies_text[];
 extern const char* const subghz_frequencies_text[];
 extern const uint32_t subghz_frequencies[];
 extern const uint32_t subghz_frequencies[];
@@ -115,8 +115,8 @@ struct SubGhz {
     TextInput* text_input;
     TextInput* text_input;
     Widget* widget;
     Widget* widget;
     DialogsApp* dialogs;
     DialogsApp* dialogs;
-    char file_name[SUBGHZ_TEXT_STORE_SIZE + 1];
-    char file_name_tmp[SUBGHZ_TEXT_STORE_SIZE + 1];
+    char file_name[SUBGHZ_MAX_LEN_NAME + 1];
+    char file_name_tmp[SUBGHZ_MAX_LEN_NAME + 1];
     SubGhzNotificationState state_notifications;
     SubGhzNotificationState state_notifications;
 
 
     SubGhzViewReceiver* subghz_receiver;
     SubGhzViewReceiver* subghz_receiver;
@@ -156,7 +156,7 @@ void subghz_sleep(SubGhz* subghz);
 bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
 bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
 void subghz_tx_stop(SubGhz* subghz);
 void subghz_tx_stop(SubGhz* subghz);
 bool subghz_key_load(SubGhz* subghz, const char* file_path);
 bool subghz_key_load(SubGhz* subghz, const char* file_path);
-bool subghz_get_next_name_file(SubGhz* subghz);
+bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len);
 bool subghz_save_protocol_to_file(
 bool subghz_save_protocol_to_file(
     SubGhz* subghz,
     SubGhz* subghz,
     FlipperFormat* flipper_format,
     FlipperFormat* flipper_format,

+ 2 - 1
lib/subghz/subghz_keystore.c

@@ -187,6 +187,8 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) {
     string_t filetype;
     string_t filetype;
     string_init(filetype);
     string_init(filetype);
 
 
+    FURI_LOG_I(TAG, "Loading keystore %s", file_name);
+
     Storage* storage = furi_record_open("storage");
     Storage* storage = furi_record_open("storage");
 
 
     FlipperFormat* flipper_format = flipper_format_file_alloc(storage);
     FlipperFormat* flipper_format = flipper_format_file_alloc(storage);
@@ -224,7 +226,6 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) {
             FURI_LOG_E(TAG, "Unknown encryption");
             FURI_LOG_E(TAG, "Unknown encryption");
             break;
             break;
         }
         }
-        FURI_LOG_I(TAG, "Loading keystore %s", file_name);
     } while(0);
     } while(0);
     flipper_format_free(flipper_format);
     flipper_format_free(flipper_format);
 
 

+ 1 - 1
lib/toolbox/stream/file_stream.c

@@ -176,7 +176,7 @@ static bool file_stream_delete_and_insert(
     string_t scratch_name;
     string_t scratch_name;
     string_t tmp_name;
     string_t tmp_name;
     string_init(tmp_name);
     string_init(tmp_name);
-    storage_get_next_filename(_stream->storage, "/any", ".scratch", ".pad", tmp_name);
+    storage_get_next_filename(_stream->storage, "/any", ".scratch", ".pad", tmp_name, 255);
     string_init_printf(scratch_name, "/any/%s.pad", string_get_cstr(tmp_name));
     string_init_printf(scratch_name, "/any/%s.pad", string_get_cstr(tmp_name));
     string_clear(tmp_name);
     string_clear(tmp_name);