From b97218d18382535bf600274e0e1361b5a6337a39 Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 13:47:40 +0800 Subject: [PATCH 01/12] fix: NetworkReader.ReadArray: remove misleading 'length > reader.Remaining' check since not all arrays are byte arrays --- Assets/Mirror/Core/NetworkReaderExtensions.cs | 12 +++--------- .../Editor/NetworkReaderWriter/NetworkWriterTest.cs | 4 +--- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index d2196d4b2dc..3953f0df622 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -283,15 +283,9 @@ public static T[] ReadArray(this NetworkReader reader) // 'null' is encoded as '-1' if (length < 0) return null; - // todo throw an exception for other negative values (we never write them, likely to be attacker) - - // this assumes that a reader for T reads at least 1 bytes - // we can't know the exact size of T because it could have a user created reader - // NOTE: don't add to length as it could overflow if value is int.max - if (length > reader.Remaining) - { - throw new EndOfStreamException($"Received array that is too large: {length}"); - } + // we can't check if reader.Remaining < length, + // because we don't know sizeof(T) since it's a managed type. + // if (length > reader.Remaining) throw new EndOfStreamException($"Received array that is too large: {length}"); T[] result = new T[length]; for (int i = 0; i < length; i++) diff --git a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs index bf52a1cfcfe..476779f5257 100644 --- a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs @@ -1388,13 +1388,11 @@ void WriteBadArray() } [Test] - [Description("ReadArray should throw if it is trying to read more than length of segment, this is to stop allocation attacks")] [TestCase(testArraySize * sizeof(int) + 1, Description = "min read count is 1 byte, 16 array bytes are writen so 17 should throw error")] [TestCase(20_000)] [TestCase(int.MaxValue)] [TestCase(int.MaxValue - 1)] - // todo add fuzzy testing to check more values - public void TestArrayThrowsIfLengthIsTooBig(int badLength) + public void TestReadArray_LengthIsTooBig(int badLength) { NetworkWriter writer = new NetworkWriter(); WriteBadArray(); From 330ed5ffa3e9c99dac0b32d113da00c0d8eb859c Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 12:20:41 +0800 Subject: [PATCH 02/12] fix: NetworkReader AllocationLimit to prevent ClientToServer [SyncVar] allocation attacks [credit: James] --- Assets/Mirror/Core/NetworkReader.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Assets/Mirror/Core/NetworkReader.cs b/Assets/Mirror/Core/NetworkReader.cs index d6f79c6c6fd..477a8c08d10 100644 --- a/Assets/Mirror/Core/NetworkReader.cs +++ b/Assets/Mirror/Core/NetworkReader.cs @@ -45,6 +45,16 @@ public class NetworkReader // this is safer. see test: ReadString_InvalidUTF8(). internal readonly UTF8Encoding encoding = new UTF8Encoding(false, true); + // while allocation free ReadArraySegment is encouraged, + // some functions can allocate a new byte[], List, Texture, etc. + // we should keep a reasonable allocation size limit: + // -> server won't accidentally allocate 2GB on a mobile device + // -> client won't allocate 2GB on server for ClientToServer [SyncVar]s + // -> unlike 64 KB max string length, we need a larger limit here. + // users may send large textures, etc. + // 16 MB adds allocation safety while not breaking extreme projects. + public const int AllocationLimit = 1024 * 1024 * 16; // 16 MB + public NetworkReader(ArraySegment segment) { buffer = segment; From 39924cbb0a2440b2fdfc79639dbb3167438aa185 Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 12:28:57 +0800 Subject: [PATCH 03/12] ReadBytes: check allocation limit --- Assets/Mirror/Core/NetworkReaderExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index 3953f0df622..45135257f2e 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -90,6 +90,17 @@ public static byte[] ReadBytesAndSize(this NetworkReader reader) public static byte[] ReadBytes(this NetworkReader reader, int count) { + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + // log an error and return default. + // we don't want attackers to be able to trigger exceptions. + if (count > NetworkReader.AllocationLimit) + { + Debug.LogWarning($"NetworkReader attempted to allocate {count} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + return null; + } + byte[] bytes = new byte[count]; reader.ReadBytes(bytes, count); return bytes; From ca51c378fef7a09ab1085f8c40fca492a48dc71b Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 12:30:52 +0800 Subject: [PATCH 04/12] ReadList: check allocation limit --- Assets/Mirror/Core/NetworkReaderExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index 45135257f2e..3f447e58cf4 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -259,6 +259,17 @@ public static List ReadList(this NetworkReader reader) // 'null' is encoded as '-1' if (length < 0) return null; + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + // log an error and return default. + // we don't want attackers to be able to trigger exceptions. + if (length > NetworkReader.AllocationLimit) + { + Debug.LogWarning($"NetworkReader attempted to allocate {length} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + return null; + } + List result = new List(length); for (int i = 0; i < length; i++) { From cb43ca03e49a069b07f0c1fb25060a70bc1ea075 Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 12:33:38 +0800 Subject: [PATCH 05/12] ReadArray: check allocation limit --- Assets/Mirror/Core/NetworkReaderExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index 3f447e58cf4..5b7915c0240 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -304,6 +304,17 @@ public static T[] ReadArray(this NetworkReader reader) // 'null' is encoded as '-1' if (length < 0) return null; + + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + // log an error and return default. + // we don't want attackers to be able to trigger exceptions. + if (length > NetworkReader.AllocationLimit) + { + Debug.LogWarning($"NetworkReader attempted to allocate {length} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + return null; + } // we can't check if reader.Remaining < length, // because we don't know sizeof(T) since it's a managed type. From 5bcd2a454fd6408a74ed11333e0b337efe3f054c Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 12:36:14 +0800 Subject: [PATCH 06/12] ReadTexture2D: check allocation limit --- Assets/Mirror/Core/NetworkReaderExtensions.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index 5b7915c0240..8acb256a9d7 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -336,9 +336,6 @@ public static Uri ReadUri(this NetworkReader reader) public static Texture2D ReadTexture2D(this NetworkReader reader) { - // TODO allocation protection when sending textures to server. - // currently can allocate 32k x 32k x 4 byte = 3.8 GB - // support 'null' textures for [SyncVar]s etc. // https://github.com/vis2k/Mirror/issues/3144 short width = reader.ReadShort(); @@ -346,6 +343,19 @@ public static Texture2D ReadTexture2D(this NetworkReader reader) // read height short height = reader.ReadShort(); + + // prevent allocation attacks with a reasonable limit. + // server shouldn't allocate too much on client devices. + // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. + // log an error and return default. + // we don't want attackers to be able to trigger exceptions. + int totalSize = width * height; + if (totalSize > NetworkReader.AllocationLimit) + { + Debug.LogWarning($"NetworkReader attempted to allocate {totalSize} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + return null; + } + Texture2D texture2D = new Texture2D(width, height); // read pixel content From d61f849d8b3f8a7d8084ed042d442a77988220fb Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 12:57:40 +0800 Subject: [PATCH 07/12] limit as count --- Assets/Mirror/Core/NetworkReader.cs | 10 ++++++---- Assets/Mirror/Core/NetworkReaderExtensions.cs | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Assets/Mirror/Core/NetworkReader.cs b/Assets/Mirror/Core/NetworkReader.cs index 477a8c08d10..82fb7cd4a88 100644 --- a/Assets/Mirror/Core/NetworkReader.cs +++ b/Assets/Mirror/Core/NetworkReader.cs @@ -50,10 +50,12 @@ public class NetworkReader // we should keep a reasonable allocation size limit: // -> server won't accidentally allocate 2GB on a mobile device // -> client won't allocate 2GB on server for ClientToServer [SyncVar]s - // -> unlike 64 KB max string length, we need a larger limit here. - // users may send large textures, etc. - // 16 MB adds allocation safety while not breaking extreme projects. - public const int AllocationLimit = 1024 * 1024 * 16; // 16 MB + // -> unlike max string length of 64 KB, we need a larger limit here. + // large enough to not break existing projects, + // small enough to reasonably limit allocation attacks. + // -> we don't know the exact size of ReadList etc. because is + // managed. instead, this is considered a 'collection length' limit. + public const int AllocationLimit = 1024 * 1024 * 16; // 16 MB * sizeof(T) public NetworkReader(ArraySegment segment) { diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index 8acb256a9d7..69dc4a7377e 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -266,7 +266,7 @@ public static List ReadList(this NetworkReader reader) // we don't want attackers to be able to trigger exceptions. if (length > NetworkReader.AllocationLimit) { - Debug.LogWarning($"NetworkReader attempted to allocate {length} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + Debug.LogWarning($"NetworkReader attempted to allocate a List<{typeof(T)}> {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); return null; } @@ -312,7 +312,7 @@ public static T[] ReadArray(this NetworkReader reader) // we don't want attackers to be able to trigger exceptions. if (length > NetworkReader.AllocationLimit) { - Debug.LogWarning($"NetworkReader attempted to allocate {length} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + Debug.LogWarning($"NetworkReader attempted to allocate an Array<{typeof(T)}> with {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); return null; } @@ -352,7 +352,7 @@ public static Texture2D ReadTexture2D(this NetworkReader reader) int totalSize = width * height; if (totalSize > NetworkReader.AllocationLimit) { - Debug.LogWarning($"NetworkReader attempted to allocate {totalSize} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); + Debug.LogWarning($"NetworkReader attempted to allocate a Texture2D with total size (width * height) of {totalSize}, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); return null; } From 0de02d302df1b4201fc52b867a963e1bd6f2351b Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 13:36:40 +0800 Subject: [PATCH 08/12] writer checks --- Assets/Mirror/Core/NetworkWriterExtensions.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Assets/Mirror/Core/NetworkWriterExtensions.cs b/Assets/Mirror/Core/NetworkWriterExtensions.cs index 54ad5130e2c..c4de17cf950 100644 --- a/Assets/Mirror/Core/NetworkWriterExtensions.cs +++ b/Assets/Mirror/Core/NetworkWriterExtensions.cs @@ -307,6 +307,10 @@ public static void WriteList(this NetworkWriter writer, List list) return; } + // check if within max size, otherwise Reader can't read it. + if (list.Count > NetworkReader.AllocationLimit) + throw new IndexOutOfRangeException($"NetworkWriter.WriteList - List<{typeof(T)}> too big: {list.Count} elements. Limit: {NetworkReader.AllocationLimit}"); + writer.WriteInt(list.Count); for (int i = 0; i < list.Count; i++) writer.Write(list[i]); @@ -340,6 +344,10 @@ public static void WriteArray(this NetworkWriter writer, T[] array) return; } + // check if within max size, otherwise Reader can't read it. + if (array.Length > NetworkReader.AllocationLimit) + throw new IndexOutOfRangeException($"NetworkWriter.WriteArray - Array<{typeof(T)}> too big: {array.Length} elements. Limit: {NetworkReader.AllocationLimit}"); + writer.WriteInt(array.Length); for (int i = 0; i < array.Length; i++) writer.Write(array[i]); @@ -364,6 +372,11 @@ public static void WriteTexture2D(this NetworkWriter writer, Texture2D texture2D return; } + // check if within max size, otherwise Reader can't read it. + int totalSize = texture2D.width * texture2D.height; + if (totalSize > NetworkReader.AllocationLimit) + throw new IndexOutOfRangeException($"NetworkWriter.WriteTexture2D - Texture2D total size (width*height) too big: {totalSize}. Limit: {NetworkReader.AllocationLimit}"); + // write dimensions first so reader can create the texture with size // 32k x 32k short is more than enough writer.WriteShort((short)texture2D.width); From 2ce63f34eefdbe5a8601d671a93b74fc6f684be2 Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 13:50:19 +0800 Subject: [PATCH 09/12] test wip --- .../NetworkReaderWriter/NetworkWriterTest.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs index 476779f5257..5a632769297 100644 --- a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs @@ -1394,23 +1394,19 @@ void WriteBadArray() [TestCase(int.MaxValue - 1)] public void TestReadArray_LengthIsTooBig(int badLength) { + // write bad array NetworkWriter writer = new NetworkWriter(); - WriteBadArray(); + writer.WriteInt(badLength); + int[] array = new int[testArraySize] { 1, 2, 3, 4 }; + for (int i = 0; i < array.Length; i++) + writer.Write(array[i]); + // attempt to read it NetworkReader reader = new NetworkReader(writer.ToArray()); EndOfStreamException exception = Assert.Throws(() => { _ = reader.ReadArray(); }); - Assert.That(exception, Has.Message.EqualTo($"Received array that is too large: {badLength}")); - - void WriteBadArray() - { - writer.WriteInt(badLength); - int[] array = new int[testArraySize] { 1, 2, 3, 4 }; - for (int i = 0; i < array.Length; i++) - writer.Write(array[i]); - } } [Test] From 2e47d4630251defc2fb95cbdf2d1cefe2d59182a Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 13:52:07 +0800 Subject: [PATCH 10/12] throw --- Assets/Mirror/Core/NetworkReaderExtensions.cs | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Assets/Mirror/Core/NetworkReaderExtensions.cs b/Assets/Mirror/Core/NetworkReaderExtensions.cs index 69dc4a7377e..bb6ca31b246 100644 --- a/Assets/Mirror/Core/NetworkReaderExtensions.cs +++ b/Assets/Mirror/Core/NetworkReaderExtensions.cs @@ -93,12 +93,10 @@ public static byte[] ReadBytes(this NetworkReader reader, int count) // prevent allocation attacks with a reasonable limit. // server shouldn't allocate too much on client devices. // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. - // log an error and return default. - // we don't want attackers to be able to trigger exceptions. if (count > NetworkReader.AllocationLimit) { - Debug.LogWarning($"NetworkReader attempted to allocate {count} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); - return null; + // throw EndOfStream for consistency with ReadBlittable when out of data + throw new EndOfStreamException($"NetworkReader attempted to allocate {count} bytes, which is larger than the allowed limit of {NetworkReader.AllocationLimit} bytes."); } byte[] bytes = new byte[count]; @@ -262,12 +260,10 @@ public static List ReadList(this NetworkReader reader) // prevent allocation attacks with a reasonable limit. // server shouldn't allocate too much on client devices. // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. - // log an error and return default. - // we don't want attackers to be able to trigger exceptions. if (length > NetworkReader.AllocationLimit) { - Debug.LogWarning($"NetworkReader attempted to allocate a List<{typeof(T)}> {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); - return null; + // throw EndOfStream for consistency with ReadBlittable when out of data + throw new EndOfStreamException($"NetworkReader attempted to allocate a List<{typeof(T)}> {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); } List result = new List(length); @@ -304,16 +300,14 @@ public static T[] ReadArray(this NetworkReader reader) // 'null' is encoded as '-1' if (length < 0) return null; - + // prevent allocation attacks with a reasonable limit. // server shouldn't allocate too much on client devices. // client shouldn't allocate too much on server in ClientToServer [SyncVar]s. - // log an error and return default. - // we don't want attackers to be able to trigger exceptions. if (length > NetworkReader.AllocationLimit) { - Debug.LogWarning($"NetworkReader attempted to allocate an Array<{typeof(T)}> with {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); - return null; + // throw EndOfStream for consistency with ReadBlittable when out of data + throw new EndOfStreamException($"NetworkReader attempted to allocate an Array<{typeof(T)}> with {length} elements, which is larger than the allowed limit of {NetworkReader.AllocationLimit}."); } // we can't check if reader.Remaining < length, From 242650782f8160a7e2b1a126ec9488734aa5829f Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 13:55:09 +0800 Subject: [PATCH 11/12] add test --- .../NetworkReaderWriter/NetworkWriterTest.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs index 5a632769297..9dd92a3d295 100644 --- a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs @@ -1387,6 +1387,28 @@ void WriteBadArray() } } + [Test] + [TestCase(testArraySize * sizeof(int) + 1, Description = "min read count is 1 byte, 16 array bytes are writen so 17 should throw error")] + [TestCase(20_000)] + [TestCase(int.MaxValue)] + [TestCase(int.MaxValue - 1)] + public void TestReadList_LengthIsTooBig(int badLength) + { + // write bad array + NetworkWriter writer = new NetworkWriter(); + writer.WriteInt(badLength); + int[] array = new int[testArraySize] { 1, 2, 3, 4 }; + for (int i = 0; i < array.Length; i++) + writer.Write(array[i]); + + // attempt to read it + NetworkReader reader = new NetworkReader(writer.ToArray()); + EndOfStreamException exception = Assert.Throws(() => + { + _ = reader.ReadList(); + }); + } + [Test] [TestCase(testArraySize * sizeof(int) + 1, Description = "min read count is 1 byte, 16 array bytes are writen so 17 should throw error")] [TestCase(20_000)] From d67e01c5c41f0131825775b1942e0b50f00a59a4 Mon Sep 17 00:00:00 2001 From: mischa Date: Thu, 27 Jul 2023 13:57:10 +0800 Subject: [PATCH 12/12] test --- .../NetworkReaderWriter/NetworkWriterTest.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs index 9dd92a3d295..00fe0fbfb42 100644 --- a/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkReaderWriter/NetworkWriterTest.cs @@ -1387,6 +1387,27 @@ void WriteBadArray() } } + [Test] + [TestCase(20_000)] + [TestCase(int.MaxValue)] + [TestCase(int.MaxValue - 1)] + public void TestReadBytes_LengthIsTooBig(int badLength) + { + // write bad array + NetworkWriter writer = new NetworkWriter(); + writer.WriteInt(badLength); + int[] array = new int[testArraySize] { 1, 2, 3, 4 }; + for (int i = 0; i < array.Length; i++) + writer.Write(array[i]); + + // attempt to read it + NetworkReader reader = new NetworkReader(writer.ToArray()); + EndOfStreamException exception = Assert.Throws(() => + { + _ = reader.ReadBytes(badLength); + }); + } + [Test] [TestCase(testArraySize * sizeof(int) + 1, Description = "min read count is 1 byte, 16 array bytes are writen so 17 should throw error")] [TestCase(20_000)]