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..2ba538b993 100644
--- a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs
+++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs
@@ -298,6 +298,55 @@ public void RelativePathParseAlphanumericWithNamespaceIndexStringPath()
Assert.AreEqual(str, RelativePath.Parse(str, typeTable).Format(typeTable));
}
+ ///
+ /// Parse path string containing two Namespaces, translate indexes
+ ///
+ [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());
+ typeTable.AddReferenceSubtype(Opc.Ua.ReferenceTypeIds.HasChild, NodeId.Null, new QualifiedName("HasChild", 3));
+ Assert.AreEqual(output, RelativePath.Parse(input, typeTable, currentTable, targetTable).Format(typeTable));
+ }
+
+
+ ///
+ /// Parse path string containing two Namespaces with missing namespace indexes in either currentTable or targetTable.
+ ///
+ [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" },
+ "<#2:HasChild>"
+ )]
+ [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(currentNamespaces));
+ var targetTable = new NamespaceTable(new List(targetNamespaces));
+
+ TypeTable typeTable = new TypeTable(new NamespaceTable());
+ var sre = Assert.Throws(() => RelativePath.Parse(path, 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.