Implemented checks in ModbusWriteBits that the upper bound of process image is not exceeded.
This commit is contained in:
		
							parent
							
								
									752f282c3a
								
							
						
					
					
						commit
						608ec48e47
					
				
					 1 changed files with 26 additions and 19 deletions
				
			
		| 
						 | 
					@ -435,38 +435,55 @@ void ModbusWriteBits(word address, long count, byte values[])
 | 
				
			||||||
	enum ModbusFuncCode funcCode = WriteBits;
 | 
						enum ModbusFuncCode funcCode = WriteBits;
 | 
				
			||||||
	byte buffer[maxLength];
 | 
						byte buffer[maxLength];
 | 
				
			||||||
	struct ModbusReqWriteBits mbreq;
 | 
						struct ModbusReqWriteBits mbreq;
 | 
				
			||||||
	word curCount;
 | 
						word overallLength, curCount, addressO;
 | 
				
			||||||
	byte dataLength;
 | 
						byte dataLength;
 | 
				
			||||||
	word overallLength;
 | 
					 | 
				
			||||||
	word i;
 | 
						word i;
 | 
				
			||||||
	long offset;
 | 
						long offset;
 | 
				
			||||||
 | 
						word devStartAddr, devEndAddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devStartAddr = funcCode == thisDev.Addr.Write.OutputBits;		// The start address of the bits
 | 
				
			||||||
 | 
						devEndAddr = devStartAddr + thisDev.MaxBitCount;				// The address behind the last bit
 | 
				
			||||||
 | 
						if (address < devStartAddr)										// Oh, reading at the wrong address?
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							writeDbg(MbError, "ModbusWriteBits: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr);
 | 
				
			||||||
 | 
							OnModbusClientPanics(AddressFailure);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FC15: Write Multiple Bits (DOs)
 | 
						// FC15: Write Multiple Bits (DOs)
 | 
				
			||||||
	offset = 0;
 | 
						offset = 0;
 | 
				
			||||||
	while (count > 0)
 | 
						while (count > 0 && (address + offset) < devEndAddr)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (count > gMaxBitsPerWrite)
 | 
							addressO = address + offset;
 | 
				
			||||||
 | 
							if (count > gMaxBitsPerWrite)										// divide packets that are too large
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			curCount = gMaxBitsPerWrite;
 | 
								curCount = gMaxBitsPerWrite;
 | 
				
			||||||
			dataLength = gMaxBitsPerWrite/8;
 | 
								dataLength = gMaxBitsPerWrite/8;
 | 
				
			||||||
			overallLength = maxLength;
 | 
								overallLength = maxLength;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else																// Bits fit in one packet
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			curCount = count;
 | 
								curCount = count;
 | 
				
			||||||
			dataLength = _ceil(curCount / 8.0);
 | 
								dataLength = _ceil(curCount / 8.0);
 | 
				
			||||||
			overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength;
 | 
								overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (addressO + curCount > devEndAddr)								// upper bound in process image
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								writeDbg(MbWarning, "ModbusWriteBits: Impossible to write %d bits at 0x%04X. Changed count to %d.", curCount, addressO, devEndAddr - addressO);
 | 
				
			||||||
 | 
								curCount = devEndAddr - addressO;
 | 
				
			||||||
 | 
								dataLength = _ceil(curCount / 8.0);
 | 
				
			||||||
 | 
								overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_ModbusMakeHeader(mbreq.Header, overallLength, funcCode);
 | 
							_ModbusMakeHeader(mbreq.Header, overallLength, funcCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mbreq.Address = address+offset;			// [2] Output address
 | 
							mbreq.Address = addressO;				// [2] Output address
 | 
				
			||||||
		mbreq.Count = curCount;					// [2] Number of items; 1:max 1968=0x7B0
 | 
							mbreq.Count = curCount;					// [2] Number of items; 1:max 1968=0x7B0
 | 
				
			||||||
		mbreq.ByteCount = dataLength;			// [1] Number of bytes; = ceil(count/8)
 | 
							mbreq.ByteCount = dataLength;			// [1] Number of bytes; = ceil(count/8)
 | 
				
			||||||
		for (i = 0; i < dataLength; i++)		// [264] Byte status, 8 per byte
 | 
							for (i = 0; i < dataLength; i++)		// [264] Byte status, 8 per byte
 | 
				
			||||||
			mbreq.Data[i] = values[i + offset/8];
 | 
								mbreq.Data[i] = values[i + offset/8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address+offset, curCount);
 | 
							writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, addressO, curCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memcpy_h2n(buffer, mbreq);
 | 
							memcpy_h2n(buffer, mbreq);
 | 
				
			||||||
		_ModbusSend(buffer, overallLength, mbreq.Header.TxID);
 | 
							_ModbusSend(buffer, overallLength, mbreq.Header.TxID);
 | 
				
			||||||
| 
						 | 
					@ -877,10 +894,6 @@ void _OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap)
 | 
				
			||||||
		case 0x80+ReadWriteRegisters:
 | 
							case 0x80+ReadWriteRegisters:
 | 
				
			||||||
			_OnModbusReceiveConfirmRegistersException(mbap, ex);
 | 
								_OnModbusReceiveConfirmRegistersException(mbap, ex);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			writeDbg(MbError, "_OnModbusReceive2Exceptions: Got incorrect exception function code 0x%02X!", mbap.FuncCode);
 | 
					 | 
				
			||||||
			OnModbusClientPanics(FuncCodeIncorrect);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -923,9 +936,7 @@ void _OnModbusReceive2Success(byte buffer[], struct ModbusApHeader mbap, int off
 | 
				
			||||||
			_OnModbusReceiveConfirmRegisters(mbuffer);
 | 
								_OnModbusReceiveConfirmRegisters(mbuffer);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			writeDbg(MbError, "_OnModbusReceive2Success: Received unexpected function code 0x%02X!", mbap.FuncCode);
 | 
								writeDbg(MbError, "OnModbusReceive2Success: We received funcCode 0x%X!?", mbap.FuncCode);
 | 
				
			||||||
			OnModbusClientPanics(FuncCodeIncorrect);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1058,9 +1069,5 @@ void _ModbusSendTimerError(byte buffer[], enum ModbusRequestError reqError)
 | 
				
			||||||
		case ReadWriteRegisters:
 | 
							case ReadWriteRegisters:
 | 
				
			||||||
			OnModbusReadWriteRegistersFailed(reqError, None, mbap);
 | 
								OnModbusReadWriteRegistersFailed(reqError, None, mbap);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			writeDbg(MbError, "_ModbusSendTimerError: Unexpected function code 0x%02X!", mbap.FuncCode);
 | 
					 | 
				
			||||||
			OnModbusClientPanics(FuncCodeIncorrect);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in a new issue