Skip to content

Assimp GetMaterialString binding can cause AccessViolationException #1989

@Georgiks

Description

@Georgiks

Summary

For certain overload of the Assimp.GetMaterialString, there is a code that copies managed string to global memory and passes the pointer to native method. However when it returns, it attempts to convert to string (SilkMarshal.PtrToString) which is useless since the resulting string is not use anywhere.

The aforementioned PtrToString (or rather Utf8PtrToString used for the used LPUTF8Str encoding) then can cause AccessViolationException because the way it is implemented is it scans for null-terminator in Span<byte>(ptr, int.MaxValue) which can use vectorization instructions and "look ahead". However when the pointer is near the edge of accessible memory, this can fail.

So technically there are two issues: unnecessary pointer to string conversion, and Access Violation risk when using Utf8PtrToString

Steps to reproduce

  • Platform: Desktop
  • Framework Version: .NET 8
  • Tested Nuget Versions: 2.13.0, 2.20.0

I wasn't able to create easy repro, but the bug was encountered after using Silk.NET.Assimp like this:

string GetMaterialName(Material* material)
{
    AssimpString materialName = new AssimpString();
    _assimp.GetMaterialString(material, Assimp.MaterialNameBase, 0, 0, ref materialName);
...
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
    at System.SpanHelpers.NonPackedIndexOfValueType[[System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.SpanHelpers+DontNegate`1[[System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Byte ByRef, Byte, Int32)
    at System.MemoryExtensions.IndexOf[[System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Span`1<Byte>, Byte)
    at Silk.NET.Core.Native.SilkMarshal.Utf8PtrToString(IntPtr)
    at Silk.NET.Core.Native.SilkMarshal.PtrToString(IntPtr, Silk.NET.Core.Native.NativeStringEncoding)
    at Silk.NET.Assimp.Assimp.GetMaterialString(Silk.NET.Assimp.Material*, System.String, UInt32, UInt32, Silk.NET.Assimp.AssimpString ByRef)

Comments

In the following image, the highlighted code shouldn't be necessary at all.
image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions