From d4eb26c84e3b3557baa504b12ad5a65d32ffa4f4 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Sat, 3 May 2025 11:28:03 +0200 Subject: [PATCH 1/3] Make RelativePath.Parse throw SRE if NamespaceIndexes cannot be found. Add Tests to verify functionality --- Stack/Opc.Ua.Core/Types/Utils/RelativePath.cs | 12 +++++ .../Types/Utils/UtilsTests.cs | 46 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Stack/Opc.Ua.Core/Types/Utils/RelativePath.cs b/Stack/Opc.Ua.Core/Types/Utils/RelativePath.cs index 6c02f169de..cf1e55ad86 100644 --- a/Stack/Opc.Ua.Core/Types/Utils/RelativePath.cs +++ b/Stack/Opc.Ua.Core/Types/Utils/RelativePath.cs @@ -354,6 +354,12 @@ public void TranslateNamespaceIndexes(NamespaceTable currentTable, NamespaceTabl { element.ReferenceTypeName = new QualifiedName(qname.Name, (ushort)mappings[qname.NamespaceIndex]); } + else + { + throw new ServiceResultException( + StatusCodes.BadIndexRangeInvalid, + Utils.Format("Cannot translate namespace index '{0}' to target namespace table.", qname.NamespaceIndex)); + } } qname = element.TargetName; @@ -364,6 +370,12 @@ public void TranslateNamespaceIndexes(NamespaceTable currentTable, NamespaceTabl { element.TargetName = new QualifiedName(qname.Name, (ushort)mappings[qname.NamespaceIndex]); } + else + { + throw new ServiceResultException( + StatusCodes.BadIndexRangeInvalid, + Utils.Format("Cannot translate namespace index '{0}' to target namespace table.", qname.NamespaceIndex)); + } } } } diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs index 0fd8f272a6..dd07fb62d3 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs @@ -298,6 +298,52 @@ public void RelativePathParseAlphanumericWithNamespaceIndexStringPath() Assert.AreEqual(str, RelativePath.Parse(str, typeTable).Format(typeTable)); } + /// + /// Parse deep path string containing two Namespaces, translate indexes + /// + [Test] + public void RelativePathParseTranslateNamespaceIndex() + { + var currentTable = new NamespaceTable(new List() { Namespaces.OpcUa, "1", Namespaces.OpcUaGds }); + var targetTable = new NamespaceTable(new List() { Namespaces.OpcUa, "1", "2", Namespaces.OpcUaGds }); + + TypeTable typeTable = new TypeTable(new NamespaceTable()); + string str = "/1:abc/2:def"; + string result = "/1:abc/3:def"; + Assert.AreEqual(result, RelativePath.Parse(str, typeTable, currentTable, targetTable).Format(typeTable)); + } + + /// + /// Parse deep path string containing two Namespaces, with targetTable missing the right namespace + /// + [Test] + public void RelativePathParseInvalidNamespaceIndex() + { + var currentTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }); + var targetTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", "3" }); + + TypeTable typeTable = new TypeTable(new NamespaceTable()); + string str = "/1:abc/2:def"; + var sre = Assert.Throws(() => RelativePath.Parse(str, typeTable, currentTable, targetTable).Format(typeTable)); + Assert.AreEqual((StatusCode)StatusCodes.BadIndexRangeInvalid, (StatusCode)sre.StatusCode); + } + + /// + /// Parse deep path string containing two Namespaces, with currentTable missing the right namespace + /// + [Test] + public void RelativePathParseInvalidNamespaceIndexCurrentTable() + { + var currentTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }); + var targetTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", "3", "4", "5" }); + + TypeTable typeTable = new TypeTable(new NamespaceTable()); + string str = "/1:abc/4:def"; + var sre = Assert.Throws(() => RelativePath.Parse(str, typeTable, currentTable, targetTable).Format(typeTable)); + Assert.AreEqual((StatusCode)StatusCodes.BadIndexRangeInvalid, (StatusCode)sre.StatusCode); + } + + /// /// Validate that XmlDocument DtdProcessing is protected against /// exponential entity expansion in this version of .NET. From dab555ec840ab933467e21b6dc32faedaca438a5 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Sun, 4 May 2025 18:33:39 +0200 Subject: [PATCH 2/3] Extend test coverage --- .../Types/Utils/UtilsTests.cs | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs index dd07fb62d3..98615c1572 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs @@ -299,47 +299,45 @@ public void RelativePathParseAlphanumericWithNamespaceIndexStringPath() } /// - /// Parse deep path string containing two Namespaces, translate indexes + /// Parse path string containing two Namespaces, translate indexes /// - [Test] - public void RelativePathParseTranslateNamespaceIndex() + [Theory] + [TestCase("<#2:HasChild>", "<#3:HasChild>")] + [TestCase("", "")] + [TestCase(".2:NodeVersion", ".3:NodeVersion")] + [TestCase("/1:abc/2:def", "/1:abc/3:def")] + public void RelativePathParseTranslateNamespaceIndexReferenceType(string input, string output) { var currentTable = new NamespaceTable(new List() { Namespaces.OpcUa, "1", Namespaces.OpcUaGds }); var targetTable = new NamespaceTable(new List() { Namespaces.OpcUa, "1", "2", Namespaces.OpcUaGds }); TypeTable typeTable = new TypeTable(new NamespaceTable()); - string str = "/1:abc/2:def"; - string result = "/1:abc/3:def"; - Assert.AreEqual(result, RelativePath.Parse(str, typeTable, currentTable, targetTable).Format(typeTable)); + typeTable.AddReferenceSubtype(Opc.Ua.ReferenceTypeIds.HasChild, NodeId.Null, new QualifiedName("HasChild", 3)); + Assert.AreEqual(output, RelativePath.Parse(input, typeTable, currentTable, targetTable).Format(typeTable)); } - /// - /// Parse deep path string containing two Namespaces, with targetTable missing the right namespace - /// - [Test] - public void RelativePathParseInvalidNamespaceIndex() - { - var currentTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }); - var targetTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", "3" }); - - TypeTable typeTable = new TypeTable(new NamespaceTable()); - string str = "/1:abc/2:def"; - var sre = Assert.Throws(() => RelativePath.Parse(str, typeTable, currentTable, targetTable).Format(typeTable)); - Assert.AreEqual((StatusCode)StatusCodes.BadIndexRangeInvalid, (StatusCode)sre.StatusCode); - } /// - /// Parse deep path string containing two Namespaces, with currentTable missing the right namespace + /// Parse path string containing two Namespaces with missing namespace indexes in either currentTable or targetTable. /// - [Test] - public void RelativePathParseInvalidNamespaceIndexCurrentTable() + [Theory] + [TestCase( + new string[] { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }, + new string[] { Namespaces.OpcUa, "2", "3" }, + "/1:abc/2:def" + )] + [TestCase( + new string[] { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }, + new string[] { Namespaces.OpcUa, "2", "3", "4", "5" }, + "/1:abc/4:def" + )] + public void RelativePathParseInvalidNamespaceIndex(string[] currentNamespaces, string[] targetNamespaces, string path) { - var currentTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }); - var targetTable = new NamespaceTable(new List() { Namespaces.OpcUa, "2", "3", "4", "5" }); + var currentTable = new NamespaceTable(new List(currentNamespaces)); + var targetTable = new NamespaceTable(new List(targetNamespaces)); TypeTable typeTable = new TypeTable(new NamespaceTable()); - string str = "/1:abc/4:def"; - var sre = Assert.Throws(() => RelativePath.Parse(str, typeTable, currentTable, targetTable).Format(typeTable)); + var sre = Assert.Throws(() => RelativePath.Parse(path, typeTable, currentTable, targetTable).Format(typeTable)); Assert.AreEqual((StatusCode)StatusCodes.BadIndexRangeInvalid, (StatusCode)sre.StatusCode); } From a10b9efe0d8ee1dcc825f7fcc73f67654aecad4d Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Sun, 4 May 2025 18:34:53 +0200 Subject: [PATCH 3/3] Add Test Case --- Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs index 98615c1572..2ba538b993 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs @@ -326,6 +326,11 @@ public void RelativePathParseTranslateNamespaceIndexReferenceType(string input, new string[] { Namespaces.OpcUa, "2", "3" }, "/1:abc/2:def" )] + [TestCase( + new string[] { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }, + new string[] { Namespaces.OpcUa, "2", "3" }, + "<#2:HasChild>" + )] [TestCase( new string[] { Namespaces.OpcUa, "2", Namespaces.OpcUaGds }, new string[] { Namespaces.OpcUa, "2", "3", "4", "5" },