public unsafe void WriteChars_VeryLargeArray_DoesNotOverflow()
        {
            const nuint INT32_OVERFLOW_SIZE = (nuint)int.MaxValue + 3;

            SafeBuffer unmanagedBuffer = null;

            try
            {
                try
                {
                    unmanagedBuffer = SafeBufferUtil.CreateSafeBuffer(INT32_OVERFLOW_SIZE * sizeof(byte));
                }
                catch (OutOfMemoryException)
                {
                    throw new SkipTestException($"Unable to execute {nameof(WriteChars_VeryLargeArray_DoesNotOverflow)} due to OOM"); // skip test in low-mem conditions
                }

                Assert.True((long)unmanagedBuffer.ByteLength > int.MaxValue);

                // reuse same memory for input and output to avoid allocating more memory and OOMs
                Span <char> span = new Span <char>((char *)unmanagedBuffer.DangerousGetHandle(), (int)(INT32_OVERFLOW_SIZE / sizeof(char)));
                span.Fill('\u0224'); // LATIN CAPITAL LETTER Z WITH HOOK
                Stream       outStream = new UnmanagedMemoryStream(unmanagedBuffer, 0, (long)unmanagedBuffer.ByteLength, FileAccess.ReadWrite);
                BinaryWriter writer    = new BinaryWriter(outStream);

                writer.Write(span); // will write slightly more than int.MaxValue bytes to the output

                Assert.Equal((long)INT32_OVERFLOW_SIZE, outStream.Position);
            }
            finally
            {
                unmanagedBuffer?.Dispose();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a view of an existing safe buffer.
        /// </summary>
        /// <param name="buffer">The buffer to create a view on.</param>
        /// <param name="offset">The offset from the start of the buffer.</param>
        /// <param name="length">The length of the view.</param>
        /// <param name="writable">True to make the view writable, false for read-only.</param>
        /// <returns>The buffer view.</returns>
        /// <remarks>Note that the returned buffer doesn't own the memory, therefore the original buffer
        /// must be maintained for the lifetime of this buffer.</remarks>
        public static SafeBufferGeneric CreateBufferView(SafeBuffer buffer, long offset, long length, bool writable)
        {
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset), "Offset less than 0.");
            }

            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), "Length less than 0.");
            }

            long total_length = checked ((long)buffer.ByteLength);

            if (length > total_length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), "Length is greater than the buffer's length.");
            }

            if (checked (offset + length) > total_length)
            {
                throw new ArgumentOutOfRangeException("Offset and length is larger than the existing buffer");
            }

            long base_address = buffer.DangerousGetHandle().ToInt64();

            base_address += offset;

            return(new SafeBufferView(new IntPtr(base_address), length, writable));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a view of an existing safe buffer.
        /// </summary>
        /// <param name="buffer">The buffer to create a view on.</param>
        /// <param name="offset">The offset from the start of the buffer.</param>
        /// <param name="length">The length of the view.</param>
        /// <returns>The buffer view.</returns>
        /// <remarks>Note that the returned buffer doesn't own the memory, therefore the original buffer
        /// must be maintained for the lifetime of this buffer.</remarks>
        public static SafeBuffer CreateBufferView(SafeBuffer buffer, int offset, int length)
        {
            long total_length = (long)buffer.ByteLength;

            if (offset + length > total_length)
            {
                throw new ArgumentException("Offset and length is larger than the existing buffer");
            }

            return(new SafeHGlobalBuffer(buffer.DangerousGetHandle() + offset, length, false));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Get a structure buffer at a specific offset.
        /// </summary>
        /// <typeparam name="T">The type of structure.</typeparam>
        /// <param name="buffer">The buffer to map.</param>
        /// <param name="offset">The offset into the buffer.</param>
        /// <returns>The structure buffer.</returns>
        /// <remarks>The returned buffer is not owned, therefore you need to maintain the original buffer while operating on this buffer.</remarks>
        public static SafeStructureInOutBuffer <T> GetStructAtOffset <T>(SafeBuffer buffer, int offset) where T : new()
        {
            int length_left = (int)buffer.ByteLength - offset;
            int struct_size = Marshal.SizeOf(typeof(T));

            if (length_left < struct_size)
            {
                throw new ArgumentException("Invalid length for structure");
            }

            return(new SafeStructureInOutBuffer <T>(buffer.DangerousGetHandle() + offset, length_left, false));
        }
Ejemplo n.º 5
0
        private unsafe Span <char> AcquireSpan(ref SafeBuffer?bufferToRelease)
        {
            SafeBuffer buffer = _buffer !;

            bool ignore = false;

            buffer.DangerousAddRef(ref ignore);

            bufferToRelease = buffer;

            return(new Span <char>((byte *)buffer.DangerousGetHandle(), (int)(buffer.ByteLength / 2)));
        }
Ejemplo n.º 6
0
        private IReadOnlyCollection <FontFace> CreateFontFaces()
        {
            var first     = MediaResourceManager.Current.CreateFontFaceFromMemory(_buffer.DangerousGetHandle(), _buffer.ByteLength, 0);
            var faceCount = first.FaceCount;
            var faces     = new List <FontFace>((int)faceCount)
            {
                new FontFace(this, first)
            };

            for (uint i = 1; i < faceCount; i++)
            {
                faces.Add(new FontFace(this, MediaResourceManager.Current.CreateFontFaceFromMemory(_buffer.DangerousGetHandle(), _buffer.ByteLength, i)));
            }
            return(faces);
        }
        /// <summary>
        /// Compare two buffers for equality.
        /// </summary>
        /// <param name="left">The left buffer.</param>
        /// <param name="left_offset">The offset into the left buffer.</param>
        /// <param name="right">The right buffer.</param>
        /// <param name="right_offset">The offset into the right buffer.</param>
        /// <param name="length">The length to compare.</param>
        /// <returns>True if the buffers are equal.</returns>
        public static bool EqualBuffer(this SafeBuffer left, int left_offset, SafeBuffer right, int right_offset, int length)
        {
            if (length == 0)
            {
                return(true);
            }

            long left_length  = left.GetLength();
            long right_length = right.GetLength();

            if (left_length < (left_offset + length) ||
                right_length < (right_offset + length))
            {
                return(false);
            }

            IntPtr compare_length = new IntPtr(length);

            return(NtRtl.RtlCompareMemory(left.DangerousGetHandle() + left_offset, right.DangerousGetHandle() + right_offset, compare_length) == compare_length);
        }
Ejemplo n.º 8
0
        private void NativeFlush()
        {
            NativeBinding nb;

            GetCurrentNativeBinding(out nb);

            if (!IsDirty && nb.IsValid)
            {
                return;
            }

            ScratchBuffer.Write <T>(0, _ValueContainer.Current);

            var pScratch = ScratchBuffer.DangerousGetHandle();
            var pUpload  = UploadBuffer.DangerousGetHandle();

            // Fix-up matrices because the in-memory order is transposed :|
            foreach (var fixup in nb.Fixups)
            {
                var pSource = (pScratch + fixup.FromOffset);
                var pDest   = (pUpload + fixup.ToOffset);

                if (fixup.TransposeMatrix)
                {
                    InPlaceTranspose((float *)pSource);
                }

                Buffer.MemoryCopy(
                    pSource.ToPointer(),
                    pDest.ToPointer(),
                    fixup.DataSize, fixup.DataSize
                    );
            }

            // HACK: Bypass the COM wrapper and invoke directly from the vtable.
            var hr = nb.pSetRawValue(nb.pUnboxedEffect, nb.hParameter, pUpload.ToPointer(), 0, nb.UploadSize);

            Marshal.ThrowExceptionForHR(hr);
            // pEffect.SetRawValue(hParameter, pUpload.ToPointer(), 0, UploadSize);
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Zero an entire buffer.
 /// </summary>
 /// <param name="buffer">The buffer to zero.</param>
 public static void ZeroBuffer(SafeBuffer buffer)
 {
     NtRtl.RtlZeroMemory(buffer.DangerousGetHandle(), new IntPtr(buffer.GetLength()));
 }
Ejemplo n.º 10
0
        private static string ReadSecurityDescriptorFromAddress(SafeProcessHandle process, IntPtr address)
        {
            SecurityDescriptorHeader header = process.ReadStruct <SecurityDescriptorHeader>(address);

            if (header.Revision != 1)
            {
                return(String.Empty);
            }

            ISecurityDescriptor sd = null;

            if (header.HasFlag(SecurityDescriptorControl.SelfRelative))
            {
                sd = process.ReadStruct <SecurityDescriptorRelative>(address);
            }
            else if (process.Is64Bit)
            {
                sd = process.ReadStruct <SecurityDescriptorAbsolute>(address);
            }
            else
            {
                sd = process.ReadStruct <SecurityDescriptorAbsolute32>(address);
            }

            SecurityDescriptorAbsolute new_sd = new SecurityDescriptorAbsolute();

            new_sd.Header         = header;
            new_sd.Header.Control = header.Control & ~SecurityDescriptorControl.SelfRelative;
            List <SafeBuffer> buffers = new List <SafeBuffer>();

            try
            {
                if (!header.HasFlag(SecurityDescriptorControl.OwnerDefaulted))
                {
                    SafeBuffer buf = ReadSid(process, sd.GetOwner(address));
                    if (buf != null)
                    {
                        buffers.Add(buf);
                        new_sd.Owner = buf.DangerousGetHandle();
                    }
                }
                if (!header.HasFlag(SecurityDescriptorControl.OwnerDefaulted))
                {
                    SafeBuffer buf = ReadSid(process, sd.GetGroup(address));
                    if (buf != null)
                    {
                        buffers.Add(buf);
                        new_sd.Group = buf.DangerousGetHandle();
                    }
                }
                if (header.HasFlag(SecurityDescriptorControl.DaclPresent))
                {
                    SafeBuffer buf = ReadAcl(process, sd.GetDacl(address));
                    if (buf != null)
                    {
                        buffers.Add(buf);
                        new_sd.Dacl = buf.DangerousGetHandle();
                    }
                }
                if (header.HasFlag(SecurityDescriptorControl.SaclPresent))
                {
                    SafeBuffer buf = ReadAcl(process, sd.GetSacl(address));
                    if (buf != null)
                    {
                        buffers.Add(buf);
                        new_sd.Sacl = buf.DangerousGetHandle();
                    }
                }

                IntPtr str;
                int    length;
                if (ConvertSecurityDescriptorToStringSecurityDescriptor(ref new_sd, SDDL_REVISION_1,
                                                                        SecurityInformation.All, out str, out length))
                {
                    string ret = Marshal.PtrToStringUni(str);
                    LocalFree(str);
                    return(ret);
                }
            }
            finally
            {
                foreach (SafeBuffer buf in buffers)
                {
                    buf.Close();
                }
            }

            return(String.Empty);
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Split an allocated address into a list of pages. This can be used to pass to
 /// ReadScatter or WriteGather file APIs.
 /// </summary>
 /// <param name="buffer">The allocated buffer to split. The address should be page aligned.</param>
 /// <remarks>The buffer will be split up based on its length. Note that the length will be rounded up.</remarks>
 /// <returns>The list of pages.</returns>
 public static IEnumerable <long> SplitAddressToPages(SafeBuffer buffer)
 {
     return(SplitAddressToPages(buffer.DangerousGetHandle().ToInt64(), buffer.GetLength()));
 }
Ejemplo n.º 12
0
 public override unsafe MemoryHandle Pin(int byteOffset = 0) => new MemoryHandle(this, (byte *)_buffer.DangerousGetHandle() + _offset);
 internal static T ReadStruct <T>(this SafeBuffer buffer)
 {
     return(ReadStruct <T>(buffer.DangerousGetHandle()));
 }
 /// <summary>
 /// Extracts strings from a safe buffer.
 /// </summary>
 /// <param name="buffer">Safe buffer to extract the value from.</param>
 /// <param name="minimum_length">The minimum string length.</param>
 /// <param name="type">The type of strings to search for.</param>
 /// <param name="count">The length of the data to search.</param>
 /// <param name="offset">The offset into the data to search.</param>
 /// <returns>The list of extracted strings.</returns>
 public static IEnumerable <ExtractedString> Extract(SafeBuffer buffer, int offset, int count, int minimum_length, ExtractedStringType type)
 {
     return(Extract(new UnmanagedMemoryStream(buffer, offset, count), buffer.DangerousGetHandle().ToInt64() + offset,
                    minimum_length, type, string.Empty));
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Fill an entire buffer with a specific byte value.
 /// </summary>
 /// <param name="buffer">The buffer to full.</param>
 /// <param name="fill">The fill value.</param>
 public static void FillBuffer(SafeBuffer buffer, byte fill)
 {
     NtRtl.RtlFillMemory(buffer.DangerousGetHandle(), new IntPtr(buffer.GetLength()), fill);
 }
        static string GetNameFromSymbolInfo(SafeBuffer buffer)
        {
            IntPtr ofs = Marshal.OffsetOf(typeof(SYMBOL_INFO), "Name");

            return(Marshal.PtrToStringUni(buffer.DangerousGetHandle() + ofs.ToInt32()));
        }
 /// <summary>
 /// Constructor from an unmanged buffer.
 /// </summary>
 /// <param name="sid">A safe buffer containing a valid SID.</param>
 /// <exception cref="NtException">Thrown if the buffer is not valid.</exception>
 public Sid(SafeBuffer sid)
     : this(sid.DangerousGetHandle())
 {
 }
Ejemplo n.º 18
0
 static IntPtr GetSafePointer(SafeBuffer buffer)
 {
     return(buffer != null?buffer.DangerousGetHandle() : IntPtr.Zero);
 }
Ejemplo n.º 19
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="buffer">The safe buffer to print.</param>
 /// <param name="length">The length to display.</param>
 /// <param name="offset">The offset into the buffer to display.</param>
 /// <param name="print_header">Print a header.</param>
 /// <param name="print_address">Print the address.</param>
 /// <param name="print_ascii">Print the ASCII text.</param>
 /// <param name="hide_repeating">Hide repeating lines.</param>
 public HexDumpBuilder(SafeBuffer buffer, long offset, long length, bool print_header, bool print_address, bool print_ascii, bool hide_repeating)
     : this(new UnmanagedMemoryStream(buffer, offset, length == 0 ? (long)buffer.ByteLength : length),
            print_header, print_address, print_ascii, hide_repeating, buffer.DangerousGetHandle().ToInt64())
 {
     _address_offset = buffer.DangerousGetHandle().ToInt64();
 }
Ejemplo n.º 20
0
 public static unsafe Span <byte> AsSpan(this SafeBuffer buffer)
 {
     return(new Span <byte>(
                (void *)buffer.DangerousGetHandle(),
                (int)buffer.ByteLength));
 }