libimobiledevice-win32/imobiledevice-net

PlistHandle Dispose System.System.AccessViolationException

karthikeyan1241997 opened this issue · 1 comments

I am getting AccessViolationException When GC finializes PlistHandle or when i call plistHandle.Dispose(). Issue occurred in Windows 10(64 bit) running latest version. Targeting .NET framework 4.6.2

Here is the Statcktrace:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at iMobileDevice.Plist.PlistNativeMethods.plist_free(IntPtr plist)
   at iMobileDevice.Plist.PlistApi.plist_free(IntPtr plist)
   at iMobileDevice.Plist.PlistHandle.ReleaseHandle()
   at System.Runtime.InteropServices.SafeHandle.InternalFinalize()
   at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
   at System.Runtime.InteropServices.SafeHandle.Finalize()

Code Causing this Exception:

 lockdownError = Lockdown.lockdownd_get_value(lockdownClientHandle, null, null, out PlistHandle valuePlist);
 if(lockdownError != LockdownError.Success)
 {
       Debug.WriteLine("Failed. Error:" + lockdownError);
       continue;
 }
 Plist.plist_get_string_val(Plist.plist_dict_get_item(valuePlist, "DeviceName"), out string deviceName);
 Plist.plist_get_string_val(Plist.plist_dict_get_item(valuePlist, "BuildVersion"), out string buildVersion);
 Plist.plist_get_string_val(Plist.plist_dict_get_item(valuePlist, "SerialNumber"), out string serialNumber);
 Plist.plist_get_string_val(Plist.plist_dict_get_item(valuePlist, "ProductType"), out string productType);
 Plist.plist_get_string_val(Plist.plist_dict_get_item(valuePlist, "DeviceClass"), out string deviceClass);

Seems issue is due to ValuePlist is disposed first before disposing the inner values handles. Exception can be avoided by manually disposing the inner plist data handles.

Updated sample:

PlistHandle deviceNameHandle = Plist.plist_dict_get_item(valuePlist, "DeviceName");
Plist.plist_get_string_val(deviceNameHandle, out string deviceName);
PlistHandle buildVersionHandle = Plist.plist_dict_get_item(valuePlist, "BuildVersion");
Plist.plist_get_string_val(buildVersionHandle, out string buildVersion);
PlistHandle serialNumberHandle = Plist.plist_dict_get_item(valuePlist, "SerialNumber");
Plist.plist_get_string_val(serialNumberHandle, out string serialNumber);
PlistHandle productTypeHandle = Plist.plist_dict_get_item(valuePlist, "ProductType");
Plist.plist_get_string_val(productTypeHandle, out string productType);
PlistHandle deviceClassHandle = Plist.plist_dict_get_item(valuePlist, "DeviceClass");
Plist.plist_get_string_val(deviceClassHandle, out string deviceClass);
           
 // Dispose inner Plist handles before Releasing ValuePlist Handle so that
 // System.AccessViolationException is avoided.
deviceNameHandle.Dispose();
buildVersionHandle.Dispose();
serialNumberHandle.Dispose();
productTypeHandle.Dispose();
deviceClassHandle.Dispose();