mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2026-02-11 18:26:20 +08:00
fix(work): 修复指针 Double Free 问题
This commit is contained in:
@@ -32,8 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||
public static extern void FreeSlice([In] IntPtr slice);
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
|
||||
public static extern string GetContentFromSlice([In] IntPtr slice);
|
||||
public static extern IntPtr GetContentFromSlice([In] IntPtr slice);
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int GetSliceLen([In] IntPtr slice);
|
||||
@@ -45,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||
public static extern void FreeMediaData([In] IntPtr mediaData);
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern string GetOutIndexBuf([In] IntPtr mediaData);
|
||||
public static extern IntPtr GetOutIndexBuf([In] IntPtr mediaData);
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetData([In] IntPtr mediaData);
|
||||
|
||||
@@ -42,8 +42,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
|
||||
public static extern string GetContentFromSlice([In] IntPtr slice);
|
||||
public static extern IntPtr GetContentFromSlice([In] IntPtr slice);
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
@@ -59,7 +58,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern string GetOutIndexBuf([In] IntPtr mediaData);
|
||||
public static extern IntPtr GetOutIndexBuf([In] IntPtr mediaData);
|
||||
|
||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||
{
|
||||
internal static class MarshalerHelper
|
||||
{
|
||||
public static string PtrToStringAnsi(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return default!;
|
||||
|
||||
return Marshal.PtrToStringAnsi(ptr)!;
|
||||
}
|
||||
|
||||
public static string PtrToStringUTF8(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return default!;
|
||||
|
||||
#if NETCOREAPP || NET5_0_OR_GREATER
|
||||
return Marshal.PtrToStringUTF8(ptr)!;
|
||||
#else
|
||||
byte b;
|
||||
int offset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
b = Marshal.ReadByte(ptr, offset);
|
||||
offset++;
|
||||
}
|
||||
while (b != 0);
|
||||
|
||||
byte[] bytes = new byte[offset - 1];
|
||||
Marshal.Copy(ptr, bytes, 0, bytes.Length);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||
{
|
||||
internal sealed class UTF8Marshaler : ICustomMarshaler
|
||||
{
|
||||
private static readonly Lazy<UTF8Marshaler> _instance = new Lazy<UTF8Marshaler>(() => new UTF8Marshaler());
|
||||
|
||||
public static ICustomMarshaler GetInstance(string pstrCookie)
|
||||
{
|
||||
return _instance.Value;
|
||||
}
|
||||
|
||||
public static string? PtrToStringUTF8(IntPtr pNativeData)
|
||||
{
|
||||
return _instance.Value.MarshalNativeToManaged(pNativeData) as string;
|
||||
}
|
||||
|
||||
public IntPtr MarshalManagedToNative(object managedObj)
|
||||
{
|
||||
if (managedObj is null)
|
||||
return IntPtr.Zero;
|
||||
if (!(managedObj is string))
|
||||
throw new InvalidOperationException();
|
||||
|
||||
byte[] bytes = Encoding.UTF8.GetBytes((string)managedObj);
|
||||
IntPtr pNativeData = Marshal.AllocHGlobal(bytes.Length + 1);
|
||||
Marshal.Copy(bytes, 0, pNativeData, bytes.Length);
|
||||
Marshal.WriteByte(pNativeData, bytes.Length, 0);
|
||||
return pNativeData;
|
||||
}
|
||||
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero)
|
||||
return default!;
|
||||
|
||||
#if NETCOREAPP || NET5_0_OR_GREATER
|
||||
return Marshal.PtrToStringUTF8(pNativeData)!;
|
||||
#else
|
||||
byte b;
|
||||
int offset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
b = Marshal.ReadByte(pNativeData, offset);
|
||||
offset++;
|
||||
}
|
||||
while (b != 0);
|
||||
|
||||
byte[] bytes = new byte[offset - 1];
|
||||
Marshal.Copy(pNativeData, bytes, 0, bytes.Length);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void CleanUpManagedData(object managedObj)
|
||||
{
|
||||
}
|
||||
|
||||
public void CleanUpNativeData(IntPtr pNativeData)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTICE:
|
||||
* 这里释放内存会导致外部 P/Invoke 调用 FreeSlice() 方法时抛出异常
|
||||
* 因此请注释下面的代码
|
||||
*/
|
||||
// Marshal.FreeHGlobal(pNativeData);
|
||||
}
|
||||
|
||||
public int GetNativeDataSize()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,10 +129,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
||||
// IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) :
|
||||
// IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) :
|
||||
// throw new PlatformNotSupportedException();
|
||||
string dataContent = /* 获取聊天记录数据内容 */
|
||||
IntPtr dataContentPtr = /* 获取聊天记录数据内容 */
|
||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) :
|
||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) :
|
||||
throw new PlatformNotSupportedException();
|
||||
string dataContent = MarshalerHelper.PtrToStringUTF8(dataContentPtr);
|
||||
|
||||
response = JsonSerializer.Deserialize<Models.GetChatRecordsResponse>(dataContent);
|
||||
response.RawBytes = Encoding.UTF8.GetBytes(dataContent);
|
||||
@@ -220,10 +221,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
||||
// IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) :
|
||||
// IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) :
|
||||
// throw new PlatformNotSupportedException();
|
||||
string dataContent = /* 获取聊天记录数据内容 */
|
||||
IntPtr dataContentPtr = /* 获取聊天记录数据内容 */
|
||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) :
|
||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) :
|
||||
throw new PlatformNotSupportedException();
|
||||
string dataContent = MarshalerHelper.PtrToStringUTF8(dataContentPtr);
|
||||
|
||||
response = JsonSerializer.Deserialize<Models.DecryptChatRecordResponse>(dataContent);
|
||||
response.RawBytes = Encoding.UTF8.GetBytes(dataContent);
|
||||
@@ -293,7 +295,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetData(dataPtr) :
|
||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetData(dataPtr) :
|
||||
throw new PlatformNotSupportedException();
|
||||
string dataNextBufferIndex = /* 获取媒体文件数据内容缓冲标识 */
|
||||
IntPtr dataNextBufferIndex = /* 获取媒体文件数据内容缓冲标识 */
|
||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetOutIndexBuf(dataPtr) :
|
||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetOutIndexBuf(dataPtr) :
|
||||
throw new PlatformNotSupportedException();
|
||||
@@ -304,10 +306,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
||||
|
||||
byte[] bytes = new byte[dataSize];
|
||||
Marshal.Copy(dataContentPtr, bytes, 0, bytes.Length);
|
||||
Marshal.FreeHGlobal(dataContentPtr);
|
||||
|
||||
response.FileBufferBytes = bytes;
|
||||
response.NextBufferIndex = dataNextBufferIndex;
|
||||
response.NextBufferIndex = MarshalerHelper.PtrToStringAnsi(dataNextBufferIndex);
|
||||
response.IsFinished = dataIsFinishFlag != 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user