Exemple #1
0
        /// <summary>
        /// Convert each Oid's value to an ASCII string, then create an unmanaged array of "numOids" LPSTR pointers, one for each Oid.
        /// "numOids" is the number of LPSTR pointers. This is normally the same as oids.Count, except in the case where a malicious caller
        /// appends to the OidCollection while this method is in progress. In such a case, this method guarantees only that this won't create
        /// an unmanaged buffer overflow condition.
        /// </summary>
        public static SafeHandle ToLpstrArray(this OidCollection?oids, out int numOids)
        {
            if (oids == null || oids.Count == 0)
            {
                numOids = 0;
                return(SafeLocalAllocHandle.InvalidHandle);
            }

            // Copy the oid strings to a local array to prevent a security race condition where
            // the OidCollection or individual oids can be modified by another thread and
            // potentially cause a buffer overflow
            var oidStrings = new string[oids.Count];

            for (int i = 0; i < oidStrings.Length; i++)
            {
                oidStrings[i] = oids[i].Value !;
            }

            unsafe
            {
                int allocationSize = checked (oidStrings.Length * sizeof(void *));
                foreach (string oidString in oidStrings)
                {
                    checked
                    {
                        allocationSize += oidString.Length + 1; // Encoding.ASCII doesn't have a fallback, so it's fine to use String.Length
                    }
                }

                SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.Create(allocationSize);
                byte **pOidPointers = (byte **)(safeLocalAllocHandle.DangerousGetHandle());
                byte * pOidContents = (byte *)(pOidPointers + oidStrings.Length);

                for (int i = 0; i < oidStrings.Length; i++)
                {
                    string oidString = oidStrings[i];

                    pOidPointers[i] = pOidContents;

                    int bytesWritten = Encoding.ASCII.GetBytes(oidString, new Span <byte>(pOidContents, oidString.Length));
                    Debug.Assert(bytesWritten == oidString.Length);

                    pOidContents[oidString.Length] = 0;
                    pOidContents += oidString.Length + 1;
                }

                numOids = oidStrings.Length;
                return(safeLocalAllocHandle);
            }
        }
Exemple #2
0
        /// <summary>
        /// Convert each Oid's value to an ASCII string, then create an unmanaged array of "numOids" LPSTR pointers, one for each Oid.
        /// "numOids" is the number of LPSTR pointers. This is normally the same as oids.Count, except in the case where a malicious caller
        /// appends to the OidCollection while this method is in progress. In such a case, this method guarantees only that this won't create
        /// an unmanaged buffer overflow condition.
        /// </summary>
        public static SafeHandle ToLpstrArray(this OidCollection oids, out int numOids)
        {
            if (oids == null || oids.Count == 0)
            {
                numOids = 0;
                return(SafeLocalAllocHandle.InvalidHandle);
            }

            // Copy the oid strings to a local list to prevent a security race condition where
            // the OidCollection or individual oids can be modified by another thread and
            // potentially cause a buffer overflow
            List <byte[]> oidStrings = new List <byte[]>();

            foreach (Oid oid in oids)
            {
                byte[] oidString = oid.ValueAsAscii();
                oidStrings.Add(oidString);
            }

            numOids = oidStrings.Count;
            unsafe
            {
                int allocationSize = checked (numOids * sizeof(void *));
                foreach (byte[] oidString in oidStrings)
                {
                    checked
                    {
                        allocationSize += oidString.Length + 1;
                    }
                }

                SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.Create(allocationSize);
                byte **pOidPointers = (byte **)(safeLocalAllocHandle.DangerousGetHandle());
                byte * pOidContents = (byte *)(pOidPointers + numOids);

                for (int i = 0; i < numOids; i++)
                {
                    pOidPointers[i] = pOidContents;
                    byte[] oidString = oidStrings[i];
                    Marshal.Copy(oidString, 0, new IntPtr(pOidContents), oidString.Length);
                    pOidContents[oidString.Length] = 0;
                    pOidContents += oidString.Length + 1;
                }

                return(safeLocalAllocHandle);
            }
        }