Skip to content

Commit 1cdea26

Browse files
committed
fix: prevent reallocation loops when buffer larger than returnLength
1 parent 36eceb1 commit 1cdea26

File tree

3 files changed

+13
-14
lines changed

3 files changed

+13
-14
lines changed

deadlock-dotnet-sdk/Domain/ProcessInfo.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ 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-
if (returnLength < bufferCmdLine.ByteLength)
255+
if (returnLength is 0)
256256
bufferCmdLine.Reallocate(numBytes: (nuint)(bufferCmdLine.ByteLength * 2));
257257
else bufferCmdLine.Reallocate(numBytes: returnLength);
258258
// none of these helped debug that internal error...
@@ -282,7 +282,7 @@ ref returnLength
282282
{
283283
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)
284284
{
285-
if (returnLength < bufferPBI.ByteLength)
285+
if (returnLength is 0)
286286
bufferPBI.Reallocate(numBytes: (nuint)(bufferPBI.ByteLength * 2));
287287
else bufferPBI.Reallocate(numBytes: returnLength);
288288
}
@@ -294,11 +294,10 @@ ref returnLength
294294
}
295295
else
296296
{
297-
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)
297+
while ((status = NtQueryInformationProcess(ProcessHandle.v, PROCESSINFOCLASS.ProcessBasicInformation, (void*)bufferPBI.DangerousGetHandle(), (uint)bufferPBI.ByteLength, ref returnLength)).Code
298+
is Code.STATUS_INFO_LENGTH_MISMATCH or Code.STATUS_BUFFER_TOO_SMALL or Code.STATUS_BUFFER_OVERFLOW)
298299
{
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);
300+
bufferPBI.Reallocate(returnLength is 0 ? returnLength = (uint)(bufferPBI.ByteLength * 2) : returnLength);
302301
}
303302

304303
if (status.Code is not Code.STATUS_SUCCESS)

deadlock-dotnet-sdk/Domain/SafeHandleEx.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,25 +151,25 @@ public unsafe (string? v, Exception? ex) ObjectName
151151
else if (v.Value.Type is PS_PROTECTION.PS_PROTECTED_TYPE.PsProtectedTypeProtected)
152152
return objectName = (null, new UnauthorizedAccessException(errUnableMsg + "The process's protection type prohibits access."));
153153

154-
uint bufferLength = 1024u;
155-
using SafeBuffer<OBJECT_NAME_INFORMATION> buffer = new(numBytes: bufferLength);
154+
uint returnLength = 1024u;
155+
using SafeBuffer<OBJECT_NAME_INFORMATION> buffer = new(numBytes: returnLength);
156156
NTSTATUS status = default;
157157

158158
while ((status = NtQueryObject(this,
159159
OBJECT_INFORMATION_CLASS.ObjectNameInformation,
160160
(OBJECT_NAME_INFORMATION*)buffer.DangerousGetHandle(),
161-
bufferLength,
162-
&bufferLength)).Code
161+
returnLength,
162+
&returnLength)).Code
163163
is Code.STATUS_BUFFER_OVERFLOW or Code.STATUS_INFO_LENGTH_MISMATCH or Code.STATUS_BUFFER_TOO_SMALL)
164164
{
165-
if (bufferLength < buffer.ByteLength)
165+
if (returnLength is 0)
166166
buffer.Reallocate((uint)(buffer.ByteLength * 2));
167-
else buffer.Reallocate(bufferLength);
167+
else buffer.Reallocate(returnLength);
168168
}
169169

170170
OBJECT_NAME_INFORMATION oni = buffer.Read<OBJECT_NAME_INFORMATION>(0);
171171
if (oni.Name.Buffer.Value is null)
172-
return objectName = (null, new NullReferenceException(errFailedMsg + "Bad data was copied to the buffer. The string pointer is null."));
172+
return objectName = (null, new NullReferenceException(errFailedMsg + "The object is unnamed -OR- bad data was copied to the buffer. The string pointer is null."));
173173

174174
return status.IsSuccessful
175175
? objectName = (oni.NameAsString, null)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public unsafe string GetHandleObjectType()
7171
while ((status = NtQueryObject(h, OBJECT_INFORMATION_CLASS.ObjectTypeInformation, (void*)buffer.DangerousGetHandle(), (uint)buffer.ByteLength, &returnLength))
7272
.Code is STATUS_BUFFER_OVERFLOW or STATUS_INFO_LENGTH_MISMATCH or STATUS_BUFFER_TOO_SMALL)
7373
{
74-
if (returnLength < buffer.ByteLength)
74+
if (returnLength is 0)
7575
buffer.Reallocate((nuint)(2 * buffer.ByteLength));
7676
else buffer.Reallocate(returnLength);
7777
}

0 commit comments

Comments
 (0)