Skip to content

Commit 1ddff98

Browse files
committed
fix: if buffer too small and returnLength is less than buffer length, double buffer length instead of assigning returnLength
1 parent 7ad0787 commit 1ddff98

File tree

4 files changed

+23
-11
lines changed

4 files changed

+23
-11
lines changed

deadlock-dotnet-sdk/Domain/NativeMethods.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ ref returnLength
256256
);
257257
}
258258

259-
if (status != Code.STATUS_SUCCESS)
259+
if (status.Code is not Code.STATUS_SUCCESS)
260260
{
261261
// Fall back to using the previous code that we've used since Windows XP (dmex)
262262
systemInformationLength = 0x10000;
@@ -268,7 +268,7 @@ ref returnLength
268268
SystemInformation: pSysInfoBuffer,
269269
SystemInformationLength: systemInformationLength,
270270
ReturnLength: ref returnLength
271-
)) == Code.STATUS_INFO_LENGTH_MISMATCH)
271+
)).Code is Code.STATUS_INFO_LENGTH_MISMATCH)
272272
{
273273
Marshal.FreeHGlobal((IntPtr)pSysInfoBuffer);
274274
systemInformationLength *= 2;

deadlock-dotnet-sdk/Domain/ProcessInfo.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ ref returnLength
252252
#endif
253253
// !WARNING may throw OutOfMemoryException; ReAllocHGlobal received a null pointer, but didn't check the error code
254254
// the native call to LocalReAlloc (via Marshal.ReAllocHGlobal) sometimes returns a null pointer. This is a Legacy function. Why does .NET not use malloc/realloc?
255-
bufferCmdLine.Reallocate(numBytes: returnLength);
255+
if (returnLength < bufferCmdLine.ByteLength)
256+
bufferCmdLine.Reallocate(numBytes: (nuint)(bufferCmdLine.ByteLength * 2));
257+
else bufferCmdLine.Reallocate(numBytes: returnLength);
256258
// none of these helped debug that internal error...
257259
//var pinerr = Marshal.GetLastPInvokeError();
258260
//var syserr = Marshal.GetLastSystemError();
@@ -279,7 +281,11 @@ ref returnLength
279281
if (Env.Is64BitOperatingSystem && !Env.Is64BitProcess && Is32BitEmulatedProcess.v is false) // yes
280282
{
281283
while ((status = NtWow64QueryInformationProcess64(ProcessHandle.v, PROCESSINFOCLASS.ProcessBasicInformation, (void*)bufferPBI.DangerousGetHandle(), (uint)bufferPBI.ByteLength, &returnLength)).Code is Code.STATUS_INFO_LENGTH_MISMATCH or Code.STATUS_BUFFER_TOO_SMALL or Code.STATUS_BUFFER_OVERFLOW)
282-
bufferPBI.Reallocate(numBytes: returnLength);
284+
{
285+
if (returnLength < bufferPBI.ByteLength)
286+
bufferPBI.Reallocate(numBytes: (nuint)(bufferPBI.ByteLength * 2));
287+
else bufferPBI.Reallocate(numBytes: returnLength);
288+
}
283289

284290
if (status.Code is not Code.STATUS_SUCCESS)
285291
throw new NTStatusException(status, "NtWow64QueryInformationProcess64 failed to query a process's basic information; " + status.Message);
@@ -289,7 +295,11 @@ ref returnLength
289295
else
290296
{
291297
while ((status = NtQueryInformationProcess(ProcessHandle.v, PROCESSINFOCLASS.ProcessBasicInformation, (void*)bufferPBI.DangerousGetHandle(), (uint)bufferPBI.ByteLength, ref returnLength)).Code is Code.STATUS_INFO_LENGTH_MISMATCH or Code.STATUS_BUFFER_TOO_SMALL or Code.STATUS_BUFFER_OVERFLOW)
292-
bufferPBI.Reallocate(returnLength + (uint)IntPtr.Size);
298+
{
299+
if (returnLength < bufferPBI.ByteLength)
300+
bufferPBI.Reallocate((nuint)(bufferPBI.ByteLength * 2));
301+
else bufferPBI.Reallocate((returnLength is 0 ? returnLength = (uint)(Marshal.SizeOf<PROCESS_BASIC_INFORMATION64>() * 2) : returnLength) + (uint)IntPtr.Size);
302+
}
293303

294304
if (status.Code is not Code.STATUS_SUCCESS)
295305
throw new NTStatusException(status, "NtQueryInformationProcess failed to query a process's basic information; " + status.Message);

deadlock-dotnet-sdk/Domain/SafeHandleEx.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ public unsafe (string? v, Exception? ex) ObjectName
162162
&bufferLength)).Code
163163
is Code.STATUS_BUFFER_OVERFLOW or Code.STATUS_INFO_LENGTH_MISMATCH or Code.STATUS_BUFFER_TOO_SMALL)
164164
{
165-
buffer.Reallocate(bufferLength);
165+
if (bufferLength < buffer.ByteLength)
166+
buffer.Reallocate((uint)(buffer.ByteLength * 2));
167+
else buffer.Reallocate(bufferLength);
166168
}
167169

168170
OBJECT_NAME_INFORMATION oni = buffer.Read<OBJECT_NAME_INFORMATION>(0);

deadlock-dotnet-sdk/Windows.Win32/SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ public unsafe string GetHandleObjectType()
6767
uint returnLength;
6868
using var h = new SafeObjectHandle(HandleValue, false);
6969

70-
status = NtQueryObject(h, OBJECT_INFORMATION_CLASS.ObjectTypeInformation, (void*)buffer.DangerousGetHandle(), (uint)buffer.ByteLength, &returnLength);
71-
7270
// Something's off. Marshal.SizeOf() returns 0x68 (104) but returnLength is 0x78 (120) or sometimes 0x80 (128). Is Win32Metadata's type definition wrong?
73-
while (status.Code is STATUS_BUFFER_OVERFLOW or STATUS_INFO_LENGTH_MISMATCH or STATUS_BUFFER_TOO_SMALL)
71+
while ((status = NtQueryObject(h, OBJECT_INFORMATION_CLASS.ObjectTypeInformation, (void*)buffer.DangerousGetHandle(), (uint)buffer.ByteLength, &returnLength))
72+
.Code is STATUS_BUFFER_OVERFLOW or STATUS_INFO_LENGTH_MISMATCH or STATUS_BUFFER_TOO_SMALL)
7473
{
75-
buffer.Reallocate(returnLength);
76-
status = NtQueryObject(h, OBJECT_INFORMATION_CLASS.ObjectTypeInformation, (void*)buffer.DangerousGetHandle(), (uint)buffer.ByteLength, &returnLength);
74+
if (returnLength < buffer.ByteLength)
75+
buffer.Reallocate((nuint)(2 * buffer.ByteLength));
76+
else buffer.Reallocate(returnLength);
7777
}
7878

7979
return status.IsSuccessful

0 commit comments

Comments
 (0)