<commit_before>﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using AOT;
using UnityEngine;

namespace Bugsnag.Unity.Payload
{
  /// <summary>
  /// Represents the "app" key in the error report payload.
  /// </summary>
  class App : Dictionary<string, object>, IFilterable
  {
    internal App(IConfiguration configuration) : this(configuration.AppVersion, configuration.ReleaseStage, null)
    {

    }

    internal App(string version, string releaseStage, string type)
    {
      this.AddToPayload("version", version);
      this.AddToPayload("releaseStage", releaseStage);
      this.AddToPayload("type", type);
    }
  }

  class AndroidApp : App
  {
    internal AndroidApp(IConfiguration configuration, AndroidJavaObject client) : base(configuration)
    {
      using (var appData = client.Call<AndroidJavaObject>("getAppData"))
      using (var map = appData.Call<AndroidJavaObject>("getAppData"))
      {
        this.PopulateDictionaryFromAndroidData(map);
      }
    }
  }

  class MacOsApp : App
  {
    [DllImport("bugsnag-osx", EntryPoint = "retrieveAppData")]
    static extern void RetrieveAppData(IntPtr instance, Action<IntPtr, string, string> populate);

    internal MacOsApp(IConfiguration configuration) : base(configuration)
    {
      GCHandle handle;

      try
      {
        handle = GCHandle.Alloc(this);

        RetrieveAppData(GCHandle.ToIntPtr(handle), PopulateAppData);
      }
      finally
      {
        handle.Free();
      }
    }

    [MonoPInvokeCallback(typeof(Action<IntPtr, string, string>))]
    static void PopulateAppData(IntPtr instance, string key, string value)
    {
      var handle = GCHandle.FromIntPtr(instance);
      if (handle.Target is MacOsApp app)
      {
        app.AddToPayload(key, value);
      }
    }
  }

  class iOSApp : App
  {
    [DllImport("__Internal", EntryPoint = "retrieveAppData")]
    static extern void RetrieveAppData(IntPtr instance, Action<IntPtr, string, string> populate);

    internal iOSApp(IConfiguration configuration) : base(configuration)
    {
      GCHandle handle;

      try
      {
        handle = GCHandle.Alloc(this);

        RetrieveAppData(GCHandle.ToIntPtr(handle), PopulateAppData);
      }
      finally
      {
        handle.Free();
      }
    }

    [MonoPInvokeCallback(typeof(Action<IntPtr, string, string>))]
    static void PopulateAppData(IntPtr instance, string key, string value)
    {
      var handle = GCHandle.FromIntPtr(instance);
      if (handle.Target is iOSApp app)
      {
        app.AddToPayload(key, value);
      }
    }
  }
}<commit_msg>Fix issue with potential unallocated handle<commit_after>﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using AOT;
using UnityEngine;

namespace Bugsnag.Unity.Payload
{
  /// <summary>
  /// Represents the "app" key in the error report payload.
  /// </summary>
  class App : Dictionary<string, object>, IFilterable
  {
    internal App(IConfiguration configuration) : this(configuration.AppVersion, configuration.ReleaseStage, null)
    {

    }

    internal App(string version, string releaseStage, string type)
    {
      this.AddToPayload("version", version);
      this.AddToPayload("releaseStage", releaseStage);
      this.AddToPayload("type", type);
    }
  }

  class AndroidApp : App
  {
    internal AndroidApp(IConfiguration configuration, AndroidJavaObject client) : base(configuration)
    {
      using (var appData = client.Call<AndroidJavaObject>("getAppData"))
      using (var map = appData.Call<AndroidJavaObject>("getAppData"))
      {
        this.PopulateDictionaryFromAndroidData(map);
      }
    }
  }

  class MacOsApp : App
  {
    [DllImport("bugsnag-osx", EntryPoint = "retrieveAppData")]
    static extern void RetrieveAppData(IntPtr instance, Action<IntPtr, string, string> populate);

    internal MacOsApp(IConfiguration configuration) : base(configuration)
    {
      GCHandle handle = GCHandle.Alloc(this);

      try
      {
        RetrieveAppData(GCHandle.ToIntPtr(handle), PopulateAppData);
      }
      finally
      {
        if (handle != null)
        {
          handle.Free();
        }
      }
    }

    [MonoPInvokeCallback(typeof(Action<IntPtr, string, string>))]
    static void PopulateAppData(IntPtr instance, string key, string value)
    {
      var handle = GCHandle.FromIntPtr(instance);
      if (handle.Target is MacOsApp app)
      {
        app.AddToPayload(key, value);
      }
    }
  }

  class iOSApp : App
  {
    [DllImport("__Internal", EntryPoint = "retrieveAppData")]
    static extern void RetrieveAppData(IntPtr instance, Action<IntPtr, string, string> populate);

    internal iOSApp(IConfiguration configuration) : base(configuration)
    {
      GCHandle handle = GCHandle.Alloc(this);

      try
      {
        RetrieveAppData(GCHandle.ToIntPtr(handle), PopulateAppData);
      }
      finally
      {
        if (handle != null)
        {
          handle.Free();
        }
      }
    }

    [MonoPInvokeCallback(typeof(Action<IntPtr, string, string>))]
    static void PopulateAppData(IntPtr instance, string key, string value)
    {
      var handle = GCHandle.FromIntPtr(instance);
      if (handle.Target is iOSApp app)
      {
        app.AddToPayload(key, value);
      }
    }
  }
}
{'fraction_non_alphanumeric': 0.10585585585585586, 'fraction_numerical': 0.0, 'mean_word_length': 2.9183823529411765, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1986291', 'n_tokens_mistral': 1604, 'n_tokens_neox': 1582, 'n_words': 335}