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(); } }
/// <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)); }
/// <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)); }
/// <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)); }
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))); }
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); }
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); }
/// <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())); }
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); }
/// <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())); }
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)); }
/// <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()) { }
static IntPtr GetSafePointer(SafeBuffer buffer) { return(buffer != null?buffer.DangerousGetHandle() : IntPtr.Zero); }
/// <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(); }
public static unsafe Span <byte> AsSpan(this SafeBuffer buffer) { return(new Span <byte>( (void *)buffer.DangerousGetHandle(), (int)buffer.ByteLength)); }