You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2026/08/25 06:40:57 UTC
(plc4x) 02/03: fix(plc4j): a count too wide to be a number is an invalid tag
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit c50a126cf9ef200fbb9f79b55166719cbcb58b7e
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Tue Aug 25 08:32:02 2026 +0200
fix(plc4j): a count too wide to be a number is an invalid tag
The modbus, profinet and profinet-ng address patterns matched any run of digits for a
count, an address or a slot, and handed whatever matched to Integer.parseInt. Eleven
digits therefore came back as a NumberFormatException - not the PlcInvalidTagException
these parsers promise for a bad address, and not something a caller handling bad
addresses would catch.
All three already bound the values themselves where it matters: modbus caps a quantity
at 125 and checks the address range, and does so correctly. But those checks run after
the number has been read, so nothing too wide to be read ever reached them. The digits
are capped in the patterns instead, at what each field can legitimately hold - nine for
a modbus address, since an extended register can name 655359999 - so an address wider
than that fails to match and is reported as the invalid address it is.
---
.../plc4x/java/modbus/base/tag/ModbusTag.java | 4 ++--
.../apache/plc4x/java/modbus/ModbusTagTest.java | 24 ++++++++++++++++++++++
.../plc4x/java/profinet/tag/ProfinetTag.java | 2 +-
.../plc4x/java/profinet/tag/ProfinetTagTest.java | 12 +++++++++++
.../plc4x/java/profinet/tag/ProfinetTag.java | 2 +-
.../plc4x/java/profinet/tag/ProfinetTagTest.java | 6 ++++++
6 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java
index 22f8ceeb73..61a3438ed2 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/tag/ModbusTag.java
@@ -39,8 +39,8 @@ public abstract class ModbusTag implements PlcTag, Serializable {
// STRING and WSTRING carry the length of one string in parentheses, the same way the S7 driver
// spells it: "holding-register:1:STRING(20)[3]" is three 20-character strings. The quantity in
// brackets keeps meaning "how many values", as it does for every other data type.
- public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<address>\\d+)(:(?<datatype>[a-zA-Z_]+)(\\((?<stringLength>\\d+)\\))?)?(\\[(?<quantity>\\d+)])?");
- public static final Pattern FIXED_DIGIT_MODBUS_PATTERN = Pattern.compile("(?<address>\\d{4,5})?(:(?<datatype>[a-zA-Z_]+)(\\((?<stringLength>\\d+)\\))?)?(\\[(?<quantity>\\d+)])?");
+ public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<address>\\d{1,9})(:(?<datatype>[a-zA-Z_]+)(\\((?<stringLength>\\d{1,5})\\))?)?(\\[(?<quantity>\\d{1,5})])?");
+ public static final Pattern FIXED_DIGIT_MODBUS_PATTERN = Pattern.compile("(?<address>\\d{4,5})?(:(?<datatype>[a-zA-Z_]+)(\\((?<stringLength>\\d{1,5})\\))?)?(\\[(?<quantity>\\d{1,5})])?");
public static final int PROTOCOL_ADDRESS_OFFSET = 1;
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusTagTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusTagTest.java
index bf94f28591..e32c26a73a 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusTagTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusTagTest.java
@@ -30,6 +30,7 @@ import static org.apache.plc4x.java.modbus.base.tag.ModbusTag.PROTOCOL_ADDRESS_O
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
class ModbusTagTest {
@@ -129,4 +130,27 @@ class ModbusTagTest {
);
}
+
+ /**
+ * The quantity is capped at 125 and the address range is checked, but both checks run after
+ * the number has been parsed - so a count too wide to be a number never reached them and left
+ * as a NumberFormatException instead of the invalid address it is.
+ */
+ @Test
+ void aCountTooWideToBeANumberIsAnInvalidTagNotANumberFormatError() {
+ assertThrows(PlcInvalidTagException.class,
+ () -> ModbusTagHoldingRegister.of("holding-register:1:INT[99999999999]"));
+ }
+
+ @Test
+ void anAddressTooWideToBeANumberIsAlsoAnInvalidTag() {
+ assertThrows(PlcInvalidTagException.class,
+ () -> ModbusTagHoldingRegister.of("holding-register:99999999999:INT"));
+ }
+
+ @Test
+ void aStringLengthTooWideToBeANumberIsAlsoAnInvalidTag() {
+ assertThrows(PlcInvalidTagException.class,
+ () -> ModbusTagHoldingRegister.of("holding-register:1:STRING(99999999999)"));
+ }
}
diff --git a/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java b/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java
index 17b3c10e77..e4f146479a 100644
--- a/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java
+++ b/plc4j/drivers/profinet-ng/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java
@@ -29,7 +29,7 @@ import java.util.regex.Pattern;
public class ProfinetTag implements PlcTag {
- public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<slot>\\d+).(?<subSlot>\\d+).(?<direction>INPUT|OUTPUT)(.(?<index>\\d+))?:(?<dataType>[a-zA-Z_]+)(\\[(?<numElements>\\d+)])?");
+ public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<slot>\\d{1,5}).(?<subSlot>\\d{1,5}).(?<direction>INPUT|OUTPUT)(.(?<index>\\d{1,5}))?:(?<dataType>[a-zA-Z_]+)(\\[(?<numElements>\\d{1,5})])?");
private final int slot;
private final int subSlot;
private final Direction direction;
diff --git a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java
index fdbe4f146e..2a2c584edc 100644
--- a/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java
+++ b/plc4j/drivers/profinet-ng/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java
@@ -71,4 +71,16 @@ class ProfinetTagTest {
assertThat(handler.parseTag("1.2.INPUT.3:INT")).isInstanceOf(ProfinetTag.class);
assertThat(handler.parseQuery("anything")).isNull();
}
+
+ @Test
+ void aCountTooWideToBeANumberIsAnInvalidTagNotANumberFormatError() {
+ assertThatThrownBy(() -> ProfinetTag.of("1.1.INPUT.1:BOOL[99999999999]"))
+ .isInstanceOf(PlcInvalidTagException.class);
+ }
+
+ @Test
+ void aSlotTooWideToBeANumberIsAlsoAnInvalidTag() {
+ assertThatThrownBy(() -> ProfinetTag.of("99999999999.1.INPUT.1:BOOL"))
+ .isInstanceOf(PlcInvalidTagException.class);
+ }
}
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java
index c7dd3f40ed..43e579c299 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/tag/ProfinetTag.java
@@ -29,7 +29,7 @@ import java.util.regex.Pattern;
public class ProfinetTag implements PlcTag {
- public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<address>[\\w\\-. ]+)(:(?<datatype>[a-zA-Z_]+)){1}(\\[(?<quantity>\\d+)])?");
+ public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<address>[\\w\\-. ]+)(:(?<datatype>[a-zA-Z_]+)){1}(\\[(?<quantity>\\d{1,5})])?");
private final String address;
private final int quantity;
private final PlcValueType dataType;
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java
index ffbae8caa0..e25854cd43 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java
+++ b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/tag/ProfinetTagTest.java
@@ -79,4 +79,10 @@ class ProfinetTagTest {
return new ProfinetTagWithExposedCtor(address, quantity, PlcValueType.INT);
}
}
+
+ @Test
+ void aCountTooWideToBeANumberIsAnInvalidTagNotANumberFormatError() {
+ assertThatThrownBy(() -> ProfinetTag.of("foo:BOOL[99999999999]"))
+ .isInstanceOf(PlcInvalidTagException.class);
+ }
}