Skip to content

Commit 06b2539

Browse files
authored
fix on merge #66 (#67)
* fix: Responding to bogus frames #61 as per @IanAber prevent sending STATUS_ILLEGAL_FUNCTION on a bogus frame: - `validateRequest()`: move CRC and validate address to start of procedure Some extras for extra snappy performance optimalisations: - `relevantAddress()`: keep the check it local in , since we provide the `unitAddress` to check for broadcast. - `validateRequest()`: keep is_Broadcast check local , it's all here i.s.o. calling isBroadcast() => `calling readUnitAddress()` : inline with `createResponse()` - `executeCallback`: remove bool `isbroadcast` and avoid thus extra branch check and memory usage * fix on merge #66 for issue #61 Better fix #61 : Move CRC check back to the end of checking in `Modbus::validateRequest()` and use a variable for the `reportException(STATUS_ILLEGAL_FUNCTION);` so the report can be done after the CRC check. * fix it
1 parent 4c1cb6b commit 06b2539

File tree

1 file changed

+58
-49
lines changed

1 file changed

+58
-49
lines changed

src/ModbusSlave.cpp

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -614,65 +614,60 @@ bool Modbus::relevantAddress(uint8_t unitAddress)
614614
*/
615615
bool Modbus::validateRequest()
616616
{
617-
// Check the crc, and if it isn't correct ignore the request.
618-
uint16_t crc = readCRC(_requestBuffer, _requestBufferLength);
619-
if (Modbus::calculateCRC(_requestBuffer, _requestBufferLength - MODBUS_CRC_LENGTH) != crc)
620-
{
621-
return false;
622-
}
617+
623618
// Check that the message was addressed to us
624619
if (!Modbus::relevantAddress(_requestBuffer[MODBUS_ADDRESS_INDEX]))
625620
{
626621
return false;
627622
}
628623
// The minimum buffer size (1 x Address, 1 x Function, n x Data, 2 x CRC).
629624
uint16_t expected_requestBufferSize = MODBUS_FRAME_SIZE;
630-
625+
bool report_illegal_function=false;
626+
631627
// Check the validity of the data based on the function code.
632628
switch (_requestBuffer[MODBUS_FUNCTION_CODE_INDEX])
633629
{
634-
case FC_READ_EXCEPTION_STATUS:
635-
// Broadcast is not supported, so ignore this request.
636-
if (_requestBuffer[MODBUS_ADDRESS_INDEX] == MODBUS_BROADCAST_ADDRESS)
637-
{
638-
return false;
639-
}
640-
break;
641-
642-
case FC_READ_COILS: // Read coils (digital read).
643-
case FC_READ_DISCRETE_INPUT: // Read input state (digital read).
644-
case FC_READ_HOLDING_REGISTERS: // Read holding registers (analog read).
645-
case FC_READ_INPUT_REGISTERS: // Read input registers (analog read).
646-
// Broadcast is not supported, so ignore this request.
647-
if (_requestBuffer[MODBUS_ADDRESS_INDEX] == MODBUS_BROADCAST_ADDRESS)
648-
{
649-
return false;
650-
}
651-
// Add bytes to expected request size (2 x Index, 2 x Count).
652-
expected_requestBufferSize += 4;
653-
break;
654-
655-
case FC_WRITE_COIL: // Write coils (digital write).
656-
case FC_WRITE_REGISTER: // Write regosters (digital write).
657-
// Add bytes to expected request size (2 x Index, 2 x Count).
658-
expected_requestBufferSize += 4;
659-
break;
660-
661-
case FC_WRITE_MULTIPLE_COILS:
662-
case FC_WRITE_MULTIPLE_REGISTERS:
663-
// Add bytes to expected request size (2 x Index, 2 x Count, 1 x Bytes).
664-
expected_requestBufferSize += 5;
665-
if (_requestBufferLength >= expected_requestBufferSize)
666-
{
667-
// Add bytes to expected request size (n x Bytes).
668-
expected_requestBufferSize += _requestBuffer[6];
669-
}
670-
break;
630+
case FC_READ_EXCEPTION_STATUS:
631+
// Broadcast is not supported, so ignore this request.
632+
if (_requestBuffer[MODBUS_ADDRESS_INDEX] == MODBUS_BROADCAST_ADDRESS)
633+
{
634+
return false;
635+
}
636+
break;
637+
638+
case FC_READ_COILS: // Read coils (digital read).
639+
case FC_READ_DISCRETE_INPUT: // Read input state (digital read).
640+
case FC_READ_HOLDING_REGISTERS: // Read holding registers (analog read).
641+
case FC_READ_INPUT_REGISTERS: // Read input registers (analog read).
642+
// Broadcast is not supported, so ignore this request.
643+
if (_requestBuffer[MODBUS_ADDRESS_INDEX] == MODBUS_BROADCAST_ADDRESS)
644+
{
645+
return false;
646+
}
647+
// Add bytes to expected request size (2 x Index, 2 x Count).
648+
expected_requestBufferSize += 4;
649+
break;
650+
651+
case FC_WRITE_COIL: // Write coils (digital write).
652+
case FC_WRITE_REGISTER: // Write regosters (digital write).
653+
// Add bytes to expected request size (2 x Index, 2 x Count).
654+
expected_requestBufferSize += 4;
655+
break;
656+
657+
case FC_WRITE_MULTIPLE_COILS:
658+
case FC_WRITE_MULTIPLE_REGISTERS:
659+
// Add bytes to expected request size (2 x Index, 2 x Count, 1 x Bytes).
660+
expected_requestBufferSize += 5;
661+
if (_requestBufferLength >= expected_requestBufferSize)
662+
{
663+
// Add bytes to expected request size (n x Bytes).
664+
expected_requestBufferSize += _requestBuffer[6];
665+
}
666+
break;
671667

672-
default:
673-
// Unknown function code.
674-
Modbus::reportException(STATUS_ILLEGAL_FUNCTION);
675-
return false;
668+
default:
669+
// Unknown function code.
670+
report_illegal_function=true;
676671
}
677672

678673
// If the received data is smaller than what we expect, ignore this request.
@@ -681,9 +676,23 @@ bool Modbus::validateRequest()
681676
return false;
682677
}
683678

679+
// Check the crc, and if it isn't correct ignore the request.
680+
uint16_t crc = readCRC(_requestBuffer, _requestBufferLength);
681+
if (Modbus::calculateCRC(_requestBuffer, _requestBufferLength - MODBUS_CRC_LENGTH) != crc)
682+
{
683+
return false;
684+
}
685+
686+
// report_illegal_function after the CRC check, cheaper
687+
if (report_illegal_function)
688+
{
689+
Modbus::reportException(STATUS_ILLEGAL_FUNCTION);
690+
return false;
691+
}
692+
684693
// Set the length to be read from the request to the calculated expected length.
685694
_requestBufferLength = expected_requestBufferSize;
686-
695+
687696
return true;
688697
}
689698

0 commit comments

Comments
 (0)