Pin buffer for NtQuerySystemInformation (dotnet/corefx#35991)
authorJan Kotas <jkotas@microsoft.com>
Tue, 12 Mar 2019 21:03:55 +0000 (14:03 -0700)
committerGitHub <noreply@github.com>
Tue, 12 Mar 2019 21:03:55 +0000 (14:03 -0700)
Fixes dotnet/corefx#35987

Commit migrated from https://github.com/dotnet/corefx/commit/704a9669e69ef5faae55ca438e9850b8aa0e9ec5

src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs

index 392f585..a9c4f59 100644 (file)
@@ -262,7 +262,7 @@ namespace System.Diagnostics
 
             try
             {
-                do
+                while (true)
                 {
                     if (buffer == null)
                     {
@@ -277,6 +277,8 @@ namespace System.Diagnostics
 
                     unsafe
                     {
+                        // Note that the buffer will contain pointers to itself and it needs to be pinned while it is being processed 
+                        // by GetProcessInfos below
                         fixed (long* bufferPtr = buffer)
                         {
                             status = Interop.NtDll.NtQuerySystemInformation(
@@ -284,23 +286,25 @@ namespace System.Diagnostics
                                 bufferPtr,
                                 bufferSize,
                                 out requiredSize);
-                        }
-                    }
 
-                    if (unchecked((uint)status) == Interop.NtDll.STATUS_INFO_LENGTH_MISMATCH)
-                    {
-                        buffer = null;
-                        bufferSize = GetNewBufferSize(bufferSize, requiredSize);
+                            if (unchecked((uint)status) != Interop.NtDll.STATUS_INFO_LENGTH_MISMATCH)
+                            {
+                                // see definition of NT_SUCCESS(Status) in SDK
+                                if (status < 0)
+                                {
+                                    throw new InvalidOperationException(SR.CouldntGetProcessInfos, new Win32Exception(status));
+                                }
+
+                                // Parse the data block to get process information
+                                processInfos = GetProcessInfos(MemoryMarshal.AsBytes<long>(buffer), processIdFilter);
+                                break;
+                            }
+                        }
                     }
-                } while (unchecked((uint)status) == Interop.NtDll.STATUS_INFO_LENGTH_MISMATCH);
 
-                if (status < 0)
-                { // see definition of NT_SUCCESS(Status) in SDK
-                    throw new InvalidOperationException(SR.CouldntGetProcessInfos, new Win32Exception(status));
+                    buffer = null;
+                    bufferSize = GetNewBufferSize(bufferSize, requiredSize);
                 }
-
-                // Parse the data block to get process information
-                processInfos = GetProcessInfos(MemoryMarshal.AsBytes<long>(buffer), processIdFilter);
             }
             finally
             {