Skip to content

Commit

Permalink
Release native memory in a deterministic way
Browse files Browse the repository at this point in the history
When functions fail with an exception, they should release
any SafeHandle they have used, since they don't return any
meaningful value.
  • Loading branch information
rpaquay committed Feb 17, 2020
1 parent ca8e2f5 commit fff36a1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 14 deletions.
15 changes: 10 additions & 5 deletions src/Core/Win32/Files/NativeFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,18 @@ private static SafeHeapBlockHandle ReadFileWorker(FullPath path, long fileSize,
}
var len = (int)Math.Min(maxLen, fileSize);
var heap = HeapAllocStatic.Alloc(len + trailingByteCount);
var bytesRead = new int[1];
try {
var bytesRead = new int[1];

if (!NativeMethods.ReadFile(fileHandle, heap.Pointer, len, bytesRead, null))
throw new Win32Exception();
if (!NativeMethods.ReadFile(fileHandle, heap.Pointer, len, bytesRead, null))
throw new Win32Exception();

if (bytesRead[0] != len)
throw new Exception("File read operation didn't read the whole file");
if (bytesRead[0] != len)
throw new Exception("File read operation didn't read the whole file");
} catch (Exception) {
heap.Dispose();
throw;
}

return heap;
}
Expand Down
28 changes: 19 additions & 9 deletions src/Core/Win32/Strings/Conversion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@ public static unsafe SafeHeapBlockHandle Utf8ToUtf16(byte* start, byte* end) {
var decoder = Encoding.UTF8.GetDecoder();
var charCount = decoder.GetCharCount(start, byteLength, true);
var newBlock = HeapAllocStatic.Alloc(charCount * sizeof(char));
var result = decoder.GetChars(start, byteLength, (char*)newBlock.Pointer.ToPointer(),
charCount, true);
if (result != charCount) {
throw new Exception("Error converting UTF8 string to UTF16 string.");
try {
var result = decoder.GetChars(start, byteLength, (char*)newBlock.Pointer.ToPointer(),
charCount, true);
if (result != charCount) {
throw new Exception("Error converting UTF8 string to UTF16 string.");
}
} catch (Exception) {
newBlock.Dispose();
throw;
}
return newBlock;
}
Expand All @@ -45,10 +50,15 @@ public static unsafe SafeHeapBlockHandle Utf16ToUtf8(char* start, char* end) {
var encoder = Encoding.UTF8.GetEncoder();
var byteCount = encoder.GetByteCount(start, (int)charCount, true);
var newBlock = HeapAllocStatic.Alloc(byteCount);
var result = encoder.GetBytes(start, (int)charCount, (byte*)newBlock.Pointer.ToPointer(),
byteCount, true);
if (result != byteCount) {
throw new Exception("Error converting string from UTF16 to UTF8.");
try {
var result = encoder.GetBytes(start, (int)charCount, (byte*)newBlock.Pointer.ToPointer(),
byteCount, true);
if (result != byteCount) {
throw new Exception("Error converting string from UTF16 to UTF8.");
}
} catch (Exception) {
newBlock.Dispose();
throw;
}
return newBlock;
}
Expand All @@ -57,7 +67,7 @@ public static unsafe SafeHeapBlockHandle StringToUtf8(string value) {
if (value == null)
throw new ArgumentException();

fixed(char* start = value) {
fixed (char* start = value) {
var block = Utf16ToUtf8(start, start + value.Length);
return block;
}
Expand Down

0 comments on commit fff36a1

Please sign in to comment.