implement CborReader indefinte-length conformance
authorEirik Tsarpalis <eirik.tsarpalis@gmail.com>
Thu, 23 Apr 2020 13:04:30 +0000 (14:04 +0100)
committerEirik Tsarpalis <eirik.tsarpalis@gmail.com>
Wed, 29 Apr 2020 14:30:09 +0000 (15:30 +0100)
src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.Array.cs
src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.Map.cs
src/libraries/System.Security.Cryptography.Encoding/tests/Cbor.Tests/CborReaderTests.String.cs
src/libraries/System.Security.Cryptography.Encoding/tests/Cbor/CborReader.Array.cs
src/libraries/System.Security.Cryptography.Encoding/tests/Cbor/CborReader.Map.cs
src/libraries/System.Security.Cryptography.Encoding/tests/Cbor/CborReader.String.cs

index de25fbf..e7bf061 100644 (file)
@@ -94,6 +94,28 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
         }
 
         [Theory]
+        [InlineData(CborConformanceLevel.Lax, "9fff")]
+        [InlineData(CborConformanceLevel.Strict, "9fff")]
+        internal static void ReadArray_IndefiniteLength_SupportedConformanceLevel_ShouldSucceed(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            uint? length = reader.ReadStartArray();
+            Assert.Null(length);
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, "9fff")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, "9fff")]
+        internal static void ReadArray_IndefiniteLength_UnSupportedConformanceLevel_ShouldThrowFormatException(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            Assert.Throws<FormatException>(() => reader.ReadStartArray());
+            Assert.Equal(0, reader.BytesRead);
+        }
+
+        [Theory]
         [InlineData("80", 0)]
         [InlineData("8101", 1)]
         [InlineData("83010203", 3)]
index 99595ad..23c4eab 100644 (file)
@@ -69,6 +69,28 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
         }
 
         [Theory]
+        [InlineData(CborConformanceLevel.Lax, "bfff")]
+        [InlineData(CborConformanceLevel.Strict, "bfff")]
+        internal static void ReadMap_IndefiniteLength_SupportedConformanceLevel_ShouldSucceed(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            uint? length = reader.ReadStartMap();
+            Assert.Null(length);
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, "bfff")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, "bfff")]
+        internal static void ReadMap_IndefiniteLength_UnSupportedConformanceLevel_ShouldThrowFormatException(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            Assert.Throws<FormatException>(() => reader.ReadStartMap());
+            Assert.Equal(0, reader.BytesRead);
+        }
+
+        [Theory]
         [InlineData(CborConformanceLevel.Lax, "b800")]
         [InlineData(CborConformanceLevel.Lax, "b90000")]
         [InlineData(CborConformanceLevel.Lax, "ba00000000")]
@@ -110,10 +132,10 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
         [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, 1, 1, 2, 2, 3, 3 }, "a3010102020303")]
         [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 1, 1, 2, 2, 3, 3 }, "a3010102020303")]
         // indefinite length string payload
-        [InlineData(CborConformanceLevel.Lax, new object[] { Map, "b", 0, 2, 0, "a", 0, new string[] { "c", "" }, 0, 1, 0 }, "a561620002006161007f616360ff000100")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { Map, "b", 0, 2, 0, "a", 0, new string[] { "c", "" }, 0, 1, 0 }, "a561620002006161007f616360ff000100")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, 1, 0, 2, 0, "a", 0, "b", 0, new string[] { "c", "" }, 0 }, "a5010002006161006162007f616360ff00")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 1, 0, 2, 0, "a", 0, "b", 0, new string[] { "c", "" }, 0 }, "a5010002006161006162007f616360ff00")]
+        [InlineData(CborConformanceLevel.Lax, new object[] { Map, "b", 0, 2, 0, "a", 0, new object[] { "c", "" }, 0, 1, 0 }, "a5616200020061610082616360000100")]
+        [InlineData(CborConformanceLevel.Strict, new object[] { Map, "b", 0, 2, 0, "a", 0, new object[] { "c", "" }, 0, 1, 0 }, "a5616200020061610082616360000100")]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, 1, 0, 2, 0, "a", 0, "b", 0, new object[] { "c", "" }, 0 }, "a5010002006161006162008261636000")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 1, 0, 2, 0, "a", 0, "b", 0, new object[] { "c", "" }, 0 }, "a5010002006161006162008261636000")]
         // CBOR sorting rules do not match canonical string sorting
         [InlineData(CborConformanceLevel.Lax, new object[] { Map, "aa", 0, "z", 0 }, "a262616100617a00")]
         [InlineData(CborConformanceLevel.Strict, new object[] { Map, "aa", 0, "z", 0 }, "a262616100617a00")]
@@ -144,45 +166,6 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
         }
 
         [Theory]
-        [InlineData(CborConformanceLevel.Lax, new object[] { Map, 3, 3, 2, 2, 1, 1 }, "bf030302020101ff")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { Map, 3, 3, 2, 2, 1, 1 }, "bf030302020101ff")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, 1, 1, 2, 2, 3, 3 }, "bf010102020303ff")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 1, 1, 2, 2, 3, 3 }, "bf010102020303ff")]
-        // indefinite length string payload
-        [InlineData(CborConformanceLevel.Lax, new object[] { Map, "b", 0, 2, 0, "a", 0, new string[] { "c", "" }, 0, 1, 0 }, "bf61620002006161007f616360ff000100ff")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { Map, "b", 0, 2, 0, "a", 0, new string[] { "c", "" }, 0, 1, 0 }, "bf61620002006161007f616360ff000100ff")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, 1, 0, 2, 0, "a", 0, "b", 0, new string[] { "c", "" }, 0 }, "bf010002006161006162007f616360ff00ff")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 1, 0, 2, 0, "a", 0, "b", 0, new string[] { "c", "" }, 0 }, "bf010002006161006162007f616360ff00ff")]
-        // CBOR sorting rules do not match canonical string sorting
-        [InlineData(CborConformanceLevel.Lax, new object[] { Map, "aa", 0, "z", 0 }, "bf62616100617a00ff")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { Map, "aa", 0, "z", 0 }, "bf62616100617a00ff")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, "z", 0, "aa", 0 }, "bf617a0062616100ff")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, "z", 0, "aa", 0 }, "bf617a0062616100ff")]
-        // Test case distinguishing between RFC7049 and CTAP2 sorting rules
-        [InlineData(CborConformanceLevel.Lax, new object[] { Map, "", 0, 255, 0 }, "bf600018ff00ff")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { Map, "", 0, 255, 0 }, "bf600018ff00ff")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, "", 0, 255, 0 }, "bf600018ff00ff")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 255, 0, "", 0 }, "bf18ff006000ff")]
-        internal static void ReadMap_SimpleValues_IndefiniteLength_ShouldAcceptKeysSortedAccordingToConformanceLevel(CborConformanceLevel level, object expectedValue, string hexEncoding)
-        {
-            byte[] encoding = hexEncoding.HexToByteArray();
-            var reader = new CborReader(encoding, level);
-            Helpers.VerifyValue(reader, expectedValue, expectDefiniteLengthCollections: false);
-        }
-
-        [Theory]
-        [InlineData(CborConformanceLevel.Lax, new object[] { Map, -1, 0, new object[] { Map, 3, 3, 2, 2, 1, 1 }, 0, "a", 0, 256, 0 }, "bf2000bf030302020101ff0061610019010000ff")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { Map, -1, 0, new object[] { Map, 3, 3, 2, 2, 1, 1 }, 0, "a", 0, 256, 0 }, "bf2000bf030302020101ff0061610019010000ff")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { Map, -1, 0, "a", 0, 256, 0, new object[] { Map, 1, 1, 2, 2, 3, 3 }, 0 }, "bf200061610019010000bf010102020303ff00ff")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { Map, 256, 0, -1, 0, "a", 0, new object[] { Map, 1, 1, 2, 2, 3, 3 }, 0 }, "bf190100002000616100bf010102020303ff00ff")]
-        internal static void ReadMap_NestedValues_IndefiniteLength_ShouldAcceptKeysSortedAccordingToConformanceLevel(CborConformanceLevel level, object expectedValue, string hexEncoding)
-        {
-            byte[] encoding = hexEncoding.HexToByteArray();
-            var reader = new CborReader(encoding, level);
-            Helpers.VerifyValue(reader, expectedValue, expectDefiniteLengthCollections: false);
-        }
-
-        [Theory]
         [InlineData(new object[] { Map, "a", 1, "a", 2 }, "a2616101616102")]
         public static void ReadMap_DuplicateKeys_ShouldSucceed(object[] values, string hexEncoding)
         {
@@ -199,9 +182,9 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
         [InlineData(CborConformanceLevel.Strict, "foobar", "a266666f6f6261720166666f6f62617202")]
         [InlineData(CborConformanceLevel.Rfc7049Canonical, "foobar", "a266666f6f6261720166666f6f62617202")]
         [InlineData(CborConformanceLevel.Ctap2Canonical, "foobar", "a266666f6f6261720166666f6f62617202")]
-        [InlineData(CborConformanceLevel.Strict, new object[] { new string[] { "x", "y" } }, "a2817f61786179ff01817f61786179ff02")]
-        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { new string[] { "x", "y" } }, "a2817f61786179ff01817f61786179ff02")]
-        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { new string[] { "x", "y" } }, "a2817f61786179ff01817f61786179ff02")]
+        [InlineData(CborConformanceLevel.Strict, new object[] { new object[] { "x", "y" } }, "a28182617861790181826178617902")]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, new object[] { new object[] { "x", "y" } }, "a28182617861790181826178617902")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, new object[] { new object[] { "x", "y" } }, "a28182617861790181826178617902")]
         internal static void ReadMap_DuplicateKeys_StrictConformance_ShouldThrowFormatException(CborConformanceLevel level, object dupeKey, string hexEncoding)
         {
             var reader = new CborReader(hexEncoding.HexToByteArray(), level);
index 65dcbc7..1f4d49b 100644 (file)
@@ -366,6 +366,94 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
         }
 
         [Theory]
+        [InlineData(CborConformanceLevel.Lax, "5f40ff")]
+        [InlineData(CborConformanceLevel.Strict, "5f40ff")]
+        internal static void ReadByteString_IndefiniteLength_SupportedConformanceLevel_ShouldSucceed(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            reader.ReadStartByteStringIndefiniteLength();
+            reader.ReadByteString();
+            reader.ReadEndByteStringIndefiniteLength();
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Lax, "5f40ff")]
+        [InlineData(CborConformanceLevel.Strict, "5f40ff")]
+        internal static void ReadByteString_IndefiniteLength_AsSingleItem_SupportedConformanceLevel_ShouldSucceed(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            reader.ReadByteString();
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, "5f40ff")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, "5f40ff")]
+        internal static void ReadByteString_IndefiniteLength_UnSupportedConformanceLevel_ShouldThrowFormatExceptoin(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            Assert.Throws<FormatException>(() => reader.ReadStartByteStringIndefiniteLength());
+            Assert.Equal(0, reader.BytesRead);
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, "5f40ff")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, "5f40ff")]
+        internal static void ReadByteString_IndefiniteLength_AsSingleItem_UnSupportedConformanceLevel_ShouldThrowFormatException(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            Assert.Throws<FormatException>(() => reader.ReadByteString());
+            Assert.Equal(0, reader.BytesRead);
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Lax, "7f60ff")]
+        [InlineData(CborConformanceLevel.Strict, "7f60ff")]
+        internal static void ReadTextString_IndefiniteLength_SupportedConformanceLevel_ShouldSucceed(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            reader.ReadStartTextStringIndefiniteLength();
+            reader.ReadTextString();
+            reader.ReadEndTextStringIndefiniteLength();
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Lax, "7f60ff")]
+        [InlineData(CborConformanceLevel.Strict, "7f60ff")]
+        internal static void ReadTextString_IndefiniteLength_AsSingleItem_SupportedConformanceLevel_ShouldSucceed(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            reader.ReadTextString();
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, "7f60ff")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, "7f60ff")]
+        internal static void ReadTextString_IndefiniteLength_UnSupportedConformanceLevel_ShouldThrowFormatExceptoin(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            Assert.Throws<FormatException>(() => reader.ReadStartTextStringIndefiniteLength());
+            Assert.Equal(0, reader.BytesRead);
+        }
+
+        [Theory]
+        [InlineData(CborConformanceLevel.Rfc7049Canonical, "7f60ff")]
+        [InlineData(CborConformanceLevel.Ctap2Canonical, "7f60ff")]
+        internal static void ReadTextString_IndefiniteLength_AsSingleItem_UnSupportedConformanceLevel_ShouldThrowFormatException(CborConformanceLevel level, string hexEncoding)
+        {
+            byte[] encoding = hexEncoding.HexToByteArray();
+            var reader = new CborReader(encoding, level);
+            Assert.Throws<FormatException>(() => reader.ReadTextString());
+            Assert.Equal(0, reader.BytesRead);
+        }
+
+        [Theory]
         [InlineData("00")] // 0
         [InlineData("20")] // -1
         [InlineData("60")] // empty text string
index 25060af..f391e3c 100644 (file)
@@ -15,6 +15,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
 
             if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
             {
+                if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+                {
+                    throw new FormatException("Indefinite-length items not support under the current conformance level.");
+                }
+
                 AdvanceBuffer(1);
                 PushDataItem(CborMajorType.Array, null);
                 return null;
index eff9a71..cc6068b 100644 (file)
@@ -18,6 +18,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
 
             if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
             {
+                if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+                {
+                    throw new FormatException("Indefinite-length items not support under the current conformance level.");
+                }
+
                 AdvanceBuffer(1);
                 PushDataItem(CborMajorType.Map, null);
                 return null;
index bb40977..70dac01 100644 (file)
@@ -20,6 +20,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
 
             if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
             {
+                if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+                {
+                    throw new FormatException("Indefinite-length items not support under the current conformance level.");
+                }
+
                 return ReadChunkedByteStringConcatenated();
             }
 
@@ -38,6 +43,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
 
             if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
             {
+                if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+                {
+                    throw new FormatException("Indefinite-length items not support under the current conformance level.");
+                }
+
                 return TryReadChunkedByteStringConcatenated(destination, out bytesWritten);
             }
 
@@ -65,6 +75,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
 
             if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
             {
+                if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+                {
+                    throw new FormatException("Indefinite-length items not support under the current conformance level.");
+                }
+
                 return ReadChunkedTextStringConcatenated();
             }
 
@@ -93,6 +108,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
 
             if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
             {
+                if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+                {
+                    throw new FormatException("Indefinite-length items not support under the current conformance level.");
+                }
+
                 return TryReadChunkedTextStringConcatenated(destination, out charsWritten);
             }
 
@@ -125,6 +145,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
                 throw new InvalidOperationException("CBOR text string is not of indefinite length.");
             }
 
+            if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+            {
+                throw new FormatException("Indefinite-length items not support under the current conformance level.");
+            }
+
             AdvanceBuffer(1);
             PushDataItem(CborMajorType.TextString, expectedNestedItems: null);
         }
@@ -146,6 +171,11 @@ namespace System.Security.Cryptography.Encoding.Tests.Cbor
                 throw new InvalidOperationException("CBOR text string is not of indefinite length.");
             }
 
+            if (CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
+            {
+                throw new FormatException("Indefinite-length items not support under the current conformance level.");
+            }
+
             AdvanceBuffer(1);
             PushDataItem(CborMajorType.ByteString, expectedNestedItems: null);
         }