From dfcc0934e59d0e7066c2c89884b7bb475963eae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bartmi=C5=84ski?= Date: Thu, 26 Nov 2020 13:43:14 +0000 Subject: [PATCH] [C#] Fix repeated group buffer overflow On a repeated group in the WrapForEncode, the parentMessage.Limit has two purposes: 1. It is used as a buffer offset for the _dimensions helper Wrap method 2. The assignment to it has a side effect of checking that we do not exceed the underlying DirectBuffer's capacity However notice that currently this assignment happens after writing to the _dimensions helper properties BlockLength and NumInGroup, i.e. the writes are done *before* we check for buffer overflow. Underneath these are direct writes to the byte* managed by the DirectBuffer, resulting in an unchecked, unsafe buffer overflow. To fix this the Limit has to be increased right after the call to the _dimensions.Wrap, before writes to BlockLength and NumInGroup The same occurs in the Decode method, only reading unsafe, invalid memory instead of writing to it. Also fixed _actingVersion was being used before it's assigned in the Encode --- .../real_logic/sbe/generation/csharp/CSharpGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 1a45d845c0..1249ceab93 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -207,11 +207,11 @@ private void generateGroupClassHeader( indent + INDENT + INDENT + "_parentMessage = parentMessage;\n" + indent + INDENT + INDENT + "_buffer = buffer;\n" + indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, actingVersion);\n" + + indent + INDENT + INDENT + "_parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + INDENT + "_blockLength = _dimensions.BlockLength;\n" + indent + INDENT + INDENT + "_count = (int) _dimensions.NumInGroup;\n" + // cast safety checked above indent + INDENT + INDENT + "_actingVersion = actingVersion;\n" + indent + INDENT + INDENT + "_index = 0;\n" + - indent + INDENT + INDENT + "_parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + "}\n", parentMessageClassName)); @@ -232,14 +232,14 @@ private void generateGroupClassHeader( indent + INDENT + INDENT + "}\n\n" + indent + INDENT + INDENT + "_parentMessage = parentMessage;\n" + indent + INDENT + INDENT + "_buffer = buffer;\n" + - indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, _actingVersion);\n" + + indent + INDENT + INDENT + "_dimensions.Wrap(buffer, parentMessage.Limit, SchemaVersion);\n" + + indent + INDENT + INDENT + "parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + INDENT + "_dimensions.BlockLength = SbeBlockLength;\n" + indent + INDENT + INDENT + "_dimensions.NumInGroup = (%5$s) count;\n" + indent + INDENT + INDENT + "_index = 0;\n" + indent + INDENT + INDENT + "_count = count;\n" + indent + INDENT + INDENT + "_blockLength = SbeBlockLength;\n" + indent + INDENT + INDENT + "_actingVersion = SchemaVersion;\n" + - indent + INDENT + INDENT + "parentMessage.Limit = parentMessage.Limit + SbeHeaderSize;\n" + indent + INDENT + "}\n", parentMessageClassName, numInGroupToken.encoding().applicableMinValue().longValue(),