Skip to content

Commit 427aa37

Browse files
[Client encryption]: Adds new tests for StreamProcessor (#5370)
# Pull Request Template #4678 ## Description Introduces tests for Decrypt and Encrypt paths of the StreamProcessor. --------- Co-authored-by: Kiran Kumar Kolli <kirankk@microsoft.com>
1 parent 7960241 commit 427aa37

5 files changed

Lines changed: 1463 additions & 13 deletions

File tree

Microsoft.Azure.Cosmos.Encryption.Custom/src/Transformation/StreamProcessor.Decryptor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ long TransformDecryptBuffer(ReadOnlySpan<byte> buffer)
140140
decryptPropertyName = null;
141141
writer.WriteRawValue(reader.ValueSpan);
142142
break;
143-
case JsonTokenType.None:
143+
case JsonTokenType.None: // Unreachable: pre-first-Read state
144144
decryptPropertyName = null;
145145
break;
146146
case JsonTokenType.StartObject:
@@ -177,7 +177,7 @@ long TransformDecryptBuffer(ReadOnlySpan<byte> buffer)
177177

178178
writer.WritePropertyName(reader.ValueSpan);
179179
break;
180-
case JsonTokenType.Comment:
180+
case JsonTokenType.Comment: // Skipped via reader options
181181
break;
182182
case JsonTokenType.True:
183183
decryptPropertyName = null;
@@ -213,7 +213,7 @@ void TransformDecryptProperty(ref Utf8JsonReader reader)
213213

214214
(byte[] bytes, int processedBytes) = this.Encryptor.Decrypt(encryptionKey, cipherTextWithTypeMarker, cipherTextLength, arrayPoolManager);
215215

216-
if (containsCompressed && properties.CompressedEncryptedPaths?.TryGetValue(decryptPropertyName, out int decompressedSize) == true)
216+
if (containsCompressed && properties.CompressedEncryptedPaths.TryGetValue(decryptPropertyName, out int decompressedSize))
217217
{
218218
BrotliCompressor decompressor = new ();
219219
byte[] buffer = arrayPoolManager.Rent(decompressedSize);
@@ -237,7 +237,7 @@ void TransformDecryptProperty(ref Utf8JsonReader reader)
237237
case TypeMarker.Boolean:
238238
writer.WriteBooleanValue(SqlBoolSerializer.Deserialize(bytesToWrite));
239239
break;
240-
case TypeMarker.Null:
240+
case TypeMarker.Null: // Produced only if ciphertext was forged or future versions choose to encrypt nulls; current encryptor skips nulls.
241241
writer.WriteNullValue();
242242
break;
243243
default:

Microsoft.Azure.Cosmos.Encryption.Custom/src/Transformation/StreamProcessor.Encryptor.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ long TransformEncryptBuffer(ReadOnlySpan<byte> buffer)
107107

108108
switch (tokenType)
109109
{
110-
case JsonTokenType.None:
110+
case JsonTokenType.None: // Unreachable after first Read()
111111
break;
112112
case JsonTokenType.StartObject:
113113
if (encryptPropertyName != null && encryptionPayloadWriter == null)
@@ -187,7 +187,7 @@ long TransformEncryptBuffer(ReadOnlySpan<byte> buffer)
187187

188188
currentWriter.WritePropertyName(reader.ValueSpan);
189189
break;
190-
case JsonTokenType.Comment:
190+
case JsonTokenType.Comment: // Skipped via reader options
191191
currentWriter.WriteCommentValue(reader.ValueSpan);
192192
break;
193193
case JsonTokenType.String:
@@ -249,6 +249,7 @@ long TransformEncryptBuffer(ReadOnlySpan<byte> buffer)
249249
break;
250250
case JsonTokenType.Null:
251251
currentWriter.WriteNullValue();
252+
encryptPropertyName = null;
252253
break;
253254
}
254255
}
@@ -287,18 +288,21 @@ private static (byte[] buffer, int length) Serialize(bool value, ArrayPoolManage
287288

288289
private static (TypeMarker typeMarker, byte[] buffer, int length) SerializeNumber(ReadOnlySpan<byte> utf8bytes, ArrayPoolManager arrayPoolManager)
289290
{
290-
if (long.TryParse(utf8bytes, out long longValue))
291+
if (System.Buffers.Text.Utf8Parser.TryParse(utf8bytes, out long longValue, out int consumedLong) && consumedLong == utf8bytes.Length)
291292
{
292293
return Serialize(longValue, arrayPoolManager);
293294
}
294-
else if (double.TryParse(utf8bytes, out double doubleValue))
295-
{
296-
return Serialize(doubleValue, arrayPoolManager);
297-
}
298-
else
295+
296+
if (System.Buffers.Text.Utf8Parser.TryParse(utf8bytes, out double doubleValue, out int consumedDouble) && consumedDouble == utf8bytes.Length)
299297
{
300-
throw new InvalidOperationException("Unsupported Number type");
298+
// Reject non-finite numbers to keep JSON contract compatibility
299+
if (double.IsFinite(doubleValue))
300+
{
301+
return Serialize(doubleValue, arrayPoolManager);
302+
}
301303
}
304+
305+
throw new InvalidOperationException("Unsupported Number type");
302306
}
303307

304308
private static (TypeMarker typeMarker, byte[] buffer, int length) Serialize(long value, ArrayPoolManager arrayPoolManager)

Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
2323
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
2424
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
25+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
26+
<PackageReference Include="coverlet.msbuild" Version="6.0.0" />
2527
</ItemGroup>
2628

2729
<ItemGroup>

0 commit comments

Comments
 (0)