Skip to content

[Bug]: Modbus: Reading single discrete-input throws ArrayIndexOutOfBoundsException #2054

@IsmoLeszczynski

Description

@IsmoLeszczynski

What happened?

I'm trying out the Modbus driver with a simulator and things were going well while reading, for example, INT from holding registers, but when I tried to read a single BOOL from discrete inputs, the ModbusOptimizer throws an exception when handling the response. With a quick glance at the decompiled sources, I'm guessing this happens because BOOL is defined with a dataTypeLength of 2:

public enum ModbusDataType { BOOL((short)1, (short)2), ... }

Is this correct? I'd expect BOOL to be defined with a length of 1, but I'm not sure if there is some technical reason for this deeper down.

The tag address I tested: discrete-input:1:BOOL

2025-04-08 20:52:05,056 ERROR [nioEventLoopGroup-3-1] org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer - Error processing response: java.lang.ArrayIndexOutOfBoundsException: arraycopy: last source index 2 out of bounds for byte[1] at java.base/java.lang.System.arraycopy(Native Method) at org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer$Response.getResponseDataForTag(ModbusOptimizer.java:410) at org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer.processReadResponses(ModbusOptimizer.java:232) at org.apache.plc4x.java.spi.optimizer.BaseOptimizer.lambda$1(BaseOptimizer.java:112) at org.apache.plc4x.java.spi.optimizer.BaseOptimizer.lambda$8(BaseOptimizer.java:205) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) at org.apache.plc4x.java.modbus.tcp.protocol.ModbusTcpProtocolLogic.lambda$11(ModbusTcpProtocolLogic.java:163) at java.base/java.util.function.Consumer.lambda$andThen$0(Consumer.java:65) at org.apache.plc4x.java.spi.Plc4xNettyWrapper.decode(Plc4xNettyWrapper.java:194) at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88) at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1407) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:1583) 2025-04-08 20:52:05,068 ERROR [nioEventLoopGroup-3-1] org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer - Original Request: <PlcReadRequest> <PlcTagRequest> <tags isList="true"> <ModbusTagDiscreteInput {address=0, quantity=1, dataType=BOOL, unitId=null }> <PlcTagItem> <tag> <ModbusTagDiscreteInput> <address dataType="uint" bitLength="16">0</address> <numberOfElements dataType="uint" bitLength="16">1</numberOfElements> <dataType dataType="string" bitLength="32" encoding="UTF-8">BOOL</dataType> </ModbusTagDiscreteInput> </tag> </PlcTagItem> </ModbusTagDiscreteInput {address=0, quantity=1, dataType=BOOL, unitId=null }> </tags> </PlcTagRequest> </PlcReadRequest> java.lang.ArrayIndexOutOfBoundsException: arraycopy: last source index 2 out of bounds for byte[1] at java.base/java.lang.System.arraycopy(Native Method) at org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer$Response.getResponseDataForTag(ModbusOptimizer.java:410) at org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer.processReadResponses(ModbusOptimizer.java:232) at org.apache.plc4x.java.spi.optimizer.BaseOptimizer.lambda$1(BaseOptimizer.java:112) at org.apache.plc4x.java.spi.optimizer.BaseOptimizer.lambda$8(BaseOptimizer.java:205) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) at org.apache.plc4x.java.modbus.tcp.protocol.ModbusTcpProtocolLogic.lambda$11(ModbusTcpProtocolLogic.java:163) at java.base/java.util.function.Consumer.lambda$andThen$0(Consumer.java:65) at org.apache.plc4x.java.spi.Plc4xNettyWrapper.decode(Plc4xNettyWrapper.java:194) at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88) at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1407) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:1583) 2025-04-08 20:52:05,078 ERROR [nioEventLoopGroup-3-1] org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer - Sub Request: <PlcReadRequest> <PlcTagRequest> <tags isList="true"> <registers0> <PlcTagItem> <tag> <ModbusTagDiscreteInput> <address dataType="uint" bitLength="16">0</address> <numberOfElements dataType="uint" bitLength="16">1</numberOfElements> <dataType dataType="string" bitLength="32" encoding="UTF-8">WORD</dataType> </ModbusTagDiscreteInput> </tag> </PlcTagItem> </registers0> </tags> </PlcTagRequest> </PlcReadRequest> 2025-04-08 20:52:05,086 ERROR [nioEventLoopGroup-3-1] org.apache.plc4x.java.modbus.base.optimizer.ModbusOptimizer - Sub Response (Success): <PlcReadResponse> <request> <PlcReadRequest> <PlcTagRequest> <tags isList="true"> <registers0> <PlcTagItem> <tag> <ModbusTagDiscreteInput> <address dataType="uint" bitLength="16">0</address> <numberOfElements dataType="uint" bitLength="16">1</numberOfElements> <dataType dataType="string" bitLength="32" encoding="UTF-8">WORD</dataType> </ModbusTagDiscreteInput> </tag> </PlcTagItem> </registers0> </tags> </PlcTagRequest> </PlcReadRequest> </request> <values isList="true"> <registers0> <PlcResponseItem> <code dataType="string" bitLength="16" encoding="UTF-8">OK</code> <value> <PlcRawByteArray dataType="byte" bitLength="8">0x00</PlcRawByteArray> </value> </PlcResponseItem> </registers0> </values> </PlcReadResponse>

Version

v0.13.0-SNAPSHOT

Programming Languages

  • plc4c
  • plc4go
  • plc4j
  • plc4net
  • plc4py

Protocols

  • AB-Ethernet
  • ADS /AMS
  • BACnet/IP
  • C-Bus
  • CANopen
  • EtherNet/IP
  • Firmata
  • IEC-69870
  • KNXnet/IP
  • Modbus
  • OPC-UA
  • Profinet
  • S7
  • S7-light

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions