diff --git a/App/app/aircopy.c b/App/app/aircopy.c index b9790346..e0a4e356 100644 --- a/App/app/aircopy.c +++ b/App/app/aircopy.c @@ -88,13 +88,14 @@ DECLARE_AIRCOPY_BANK(1) // For settings only static const AIRCOPY_Segment_t AIRCOPY_Segments_Settings[] = { - { 0xA000, 0xA170, AIRCOPY_WRITE_BYTES }, - { 0x880E, 0x886E, AIRCOPY_WRITE_BYTES }, - { 0x9000, 0x90E5, AIRCOPY_WRITE_BYTES }, // VFO area (full 14 VFOs 0x9000..0x90E0) + - // Fox Hunt settings tail 0x90E0..0x90E5 + // Ends are rounded to full Aircopy blocks. The extra bytes are unmapped + // EEPROM-compat holes (0x90E0..0x90E6 is the complete Fox Hunt tail). + { 0xA000, 0xA180, AIRCOPY_WRITE_BYTES }, + { 0x880E, 0x888E, AIRCOPY_WRITE_BYTES }, + { 0x9000, 0x9100, AIRCOPY_WRITE_BYTES }, }; -// total_blocks = ceil(0x170/64) + ceil(0x60/64) + ceil(0xE5/64) = 6 + 2 + 4 = 12 +// total_blocks = 0x180/64 + 0x80/64 + 0x100/64 = 6 + 2 + 4 = 12 static const AIRCOPY_TransferMap_t AIRCOPY_Map_Settings = { .segments = AIRCOPY_Segments_Settings, .num_segments = 3, @@ -154,7 +155,8 @@ static inline const AIRCOPY_Segment_t *AIRCOPY_FindSegmentForOffset(uint16_t off { const AIRCOPY_Segment_t *seg = &map->segments[i]; - if (off >= seg->start_offset && off < seg->end_offset) + if (off >= seg->start_offset && off < seg->end_offset && + ((off - seg->start_offset) & (AIRCOPY_BLOCK_SIZE - 1u)) == 0u) return seg; } @@ -426,4 +428,4 @@ void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) gRequestDisplayScreen = DISPLAY_AIRCOPY; } -#endif \ No newline at end of file +#endif diff --git a/App/app/beam.c b/App/app/beam.c index 0f024757..fab2923d 100644 --- a/App/app/beam.c +++ b/App/app/beam.c @@ -174,7 +174,6 @@ static void BEAM_SavePayloadToFirstFreeChannel(const BEAM_Payload_t *payload) VFO_Info_t vfo; RADIO_InitInfo(&vfo, channel, payload->rx_frequency); - // CRC + magic + version already validate the payload — no need to clamp fields. vfo.TX_OFFSET_FREQUENCY = payload->tx_offset_frequency; vfo.freq_config_RX.Code = payload->rx_code; vfo.freq_config_TX.Code = payload->tx_code; @@ -191,10 +190,9 @@ static void BEAM_SavePayloadToFirstFreeChannel(const BEAM_Payload_t *payload) #ifdef ENABLE_DTMF_CALLING vfo.DTMF_DECODING_ENABLE = payload->dtmf_decoding_enable; #endif - vfo.STEP_SETTING = payload->step_setting; + vfo.STEP_SETTING = payload->step_setting < STEP_N_ELEM ? payload->step_setting : STEP_12_5kHz; vfo.StepFrequency = gStepFrequencyTable[vfo.STEP_SETTING]; vfo.SCRAMBLING_TYPE = payload->scrambling_type; - vfo.Band = payload->band; vfo.SCANLIST_PARTICIPATION = payload->scanlist; vfo.Compander = payload->compander; diff --git a/App/app/uart.c b/App/app/uart.c index 54eb91b0..a298cefb 100644 --- a/App/app/uart.c +++ b/App/app/uart.c @@ -298,9 +298,10 @@ static void SendVersion(uint32_t Port) { REPLY_0514_t Reply; + Reply.Data.Padding[0] = Reply.Data.Padding[1] = 0; Reply.Header.ID = 0x0515; Reply.Header.Size = sizeof(Reply.Data); - strcpy(Reply.Data.Version, Version); + strncpy(Reply.Data.Version, Version, sizeof(Reply.Data.Version)); Reply.Data.bHasCustomAesKey = bHasCustomAesKey; Reply.Data.bIsInLockScreen = bIsInLockScreen; Reply.Data.Challenge[0] = gChallenge[0]; @@ -434,6 +435,9 @@ static void CMD_051D(uint32_t Port, const uint8_t *pBuffer) uint32_t Timestamp = 0; + if ((pCmd->Size & 7u) || pCmd->Header.Size < 8u + pCmd->Size) + return; + if(0) {} #if defined(ENABLE_UART) else if (Port == UART_PORT_UART) @@ -560,6 +564,7 @@ static void CMD_052D(uint32_t Port, const uint8_t *pBuffer) gIsLocked = bIsLocked; Reply.Data.bIsLocked = bIsLocked; + Reply.Data.Padding[0] = Reply.Data.Padding[1] = Reply.Data.Padding[2] = 0; SendReply(Port, &Reply, sizeof(Reply)); } @@ -796,7 +801,9 @@ bool UART_IsCommandAvailable(uint32_t Port) Crc = pUART_Command->Buffer[Size] | (pUART_Command->Buffer[Size + 1] << 8); - return CRC_Calculate(pUART_Command->Buffer, Size) == Crc; + return Size >= sizeof(Header_t) && + pUART_Command->Header.Size <= Size - sizeof(Header_t) && + CRC_Calculate(pUART_Command->Buffer, Size) == Crc; } #ifdef ENABLE_FEAT_F4HWN_MULTIBOOT @@ -936,6 +943,8 @@ void UART_HandleCommand(uint32_t Port) case 0x0724: // slot write: program bytes at slot+offset (slot pre-erased) { + if (pUART_Command->Header.Size < 12u) + break; gSerialConfigCountDown_500ms = 12; // keep serial mode alive (6 s) uint8_t slot = pUART_Command->Data[0]; uint32_t offset = (uint32_t)pUART_Command->Data[2] @@ -951,7 +960,7 @@ void UART_HandleCommand(uint32_t Port) uint8_t status; if (ts != mb_port_timestamp(Port)) status = MB_ERR_AUTH; - else if (len > 240u) // 12-byte prefix + data must fit Data[252] + else if (len > pUART_Command->Header.Size - 12u) status = MB_ERR_SIZE; else status = MB_SlotWrite(slot, offset, &pUART_Command->Data[12], len); diff --git a/App/ui/welcome.c b/App/ui/welcome.c index 659079e7..37e288a8 100644 --- a/App/ui/welcome.c +++ b/App/ui/welcome.c @@ -255,15 +255,17 @@ void UI_DisplayWelcome(void) } #endif else { - char WelcomeString0[16]; - char WelcomeString1[16]; + char WelcomeString0[17]; + char WelcomeString1[17]; char WelcomeString2[16]; char WelcomeString3[32]; // 0x0EB0 PY25Q16_ReadBuffer(0x00A0C8, WelcomeString0, 16); + WelcomeString0[16] = '\0'; // 0x0EC0 PY25Q16_ReadBuffer(0x00A0D8, WelcomeString1, 16); + WelcomeString1[16] = '\0'; sprintf(WelcomeString2, "%u.%02uV %u%%", gBatteryVoltageAverage / 100,