clugg / sm-json

A pure SourcePawn JSON encoder/decoder.
GNU General Public License v3.0
82 stars 8 forks source link

[Bug] Error using json_cleanup_and_delete #29

Closed lechuga16 closed 1 year ago

lechuga16 commented 1 year ago

Description

[SM] Exception reported: Invalid Handle a8500748 (error 3) [SM] Blaming: matchmaking/match.smx [SM] Call stack trace: [SM] [0] StringMap.GetValue [SM] [1] Line 98, x:...\scripting\include\json\helpers\typedstringmap.inc::TypedStringMap.GetOptionalValue [SM] [2] Line 136, x:...\scripting\include\json\helpers\typedstringmap.inc::TypedStringMap.GetBool [SM] [3] Line 77, x:...\scripting\include\json\object.inc::JSON_Object.OrderedKeys.get [SM] [4] Line 109, x:...\scripting\include\json\object.inc::JSON_Object.Iterate [SM] [5] Line 770, x:...\scripting\include\json.inc::json_cleanup [SM] [6] Line 785, x:...\scripting\include\json.inc::json_cleanup [SM] [7] Line 785, x:...\scripting\include\json.inc::json_cleanup [SM] [8] Line 800, x:...\scripting\include\json.inc::json_cleanup_and_delete [SM] [9] Line 203, x:...\scripting\forsaken.sp::PlayersTest **

Reproduction

#include <json>

char
    g_sSteamIDTA[MAX_PLAYER_TEAM][STEAMID_LENGTH],
    g_sSteamIDTB[MAX_PLAYER_TEAM][STEAMID_LENGTH],
    g_sNameTA[MAX_PLAYER_TEAM][NAME_LENGTH],
    g_sNameTB[MAX_PLAYER_TEAM][NAME_LENGTH];

public Plugin myinfo =
{
    name        = "match",
    author      = "lechuga",
    description     = "error example",
    version     = "-",
    url     = "-"

}

public void OnPluginStart()
{
    RegConsoleCmd("sm_playersinfo", PlayersTest);
}

public Action PlayersTest(int iClient, int iArgs)
{
    char 
        sPatch[64];

    JSON_Object
        joMatch;

    JSON_Array
        jaTA,
        jaTB;

    BuildPath(Path_SM, sPatch, sizeof(sPatch), "logs/match.json");
    joMatch = json_read_from_file(sPatch);

    jaTA = view_as<JSON_Array>(joMatch.GetObject("team1"));
    jaTB = view_as<JSON_Array>(joMatch.GetObject("team2"));

    if(joMatch == null)
    {
        ReplyToCommand(iClient, "Error: JSON_Object joMatch == null");
        return Plugin_Handled;
    }

    for (int i = 0; i <= 3; i++)
    {
        JSON_Object joPlayerTA = jaTA.GetObject(i);
        JSON_Object joPlayerTB = jaTB.GetObject(i);

        joPlayerTA.GetString("steamid", g_sSteamIDTA[i], STEAMID_LENGTH);
        joPlayerTB.GetString("steamid", g_sSteamIDTB[i], STEAMID_LENGTH);

        ReplaceString(g_sSteamIDTA[i], STEAMID_LENGTH, "STEAM_0", "STEAM_1", false);
        ReplaceString(g_sSteamIDTB[i], STEAMID_LENGTH, "STEAM_0", "STEAM_1", false);

        joPlayerTA.GetString("personaname", g_sNameTA[i], NAME_LENGTH);
        joPlayerTB.GetString("personaname", g_sNameTB[i], NAME_LENGTH);

        json_cleanup_and_delete(joPlayerTA);
        json_cleanup_and_delete(joPlayerTB);
    }

    ReplyToCommand(iClient, "TeamA Name: %s %s %s %s", g_sNameTA[0], g_sNameTA[1], g_sNameTA[2], g_sNameTA[3]);
    ReplyToCommand(iClient, "TeamA Steamid: %s %s %s %s", g_sSteamIDTA[0], g_sSteamIDTA[1], g_sSteamIDTA[2], g_sSteamIDTA[3]);

    ReplyToCommand(iClient, "TeamB Name: %s %s %s %s", g_sNameTB[0], g_sNameTB[1], g_sNameTB[2], g_sNameTB[3]);
    ReplyToCommand(iClient, "TeamB Steamid: %s %s %s %s", g_sSteamIDTB[0], g_sSteamIDTB[1], g_sSteamIDTB[2], g_sSteamIDTB[3]);

    json_cleanup_and_delete(joMatch);
        json_cleanup_and_delete(jaTA);
        json_cleanup_and_delete(jaTB);
    return Plugin_Handled;
}

Versions

sm-json: v4.11

SourceMod Compiler: sourcemod-1.12.0-git6925

SourceMod Build: SourceMod Version Information: SourceMod Version: 1.11.0.6825 SourcePawn Engine: 1.11.0.6825, jit-x86 (build 1.11.0.6825) SourcePawn API: v1 = 5, v2 = 16 Compiled on: Nov 23 2021 12:17:22 Built from: https://github.com/alliedmodders/sourcemod/commit/4e3df76 Build ID: 6825:4e3df76 http://www.sourcemod.net/

Additional Information

clugg commented 1 year ago

Hey @lechuga16, thanks for the detailed issue! I don't believe there is any problem here - essentially, what is causing your error is that you are cleaning up joPlayerTA and joPlayerTB inside the loop but not removing those references from the team arrays. As a result, by the time we're finished iterating over the arrays, they both still contain handles at indexes 0 through 3, but these handles have been cleaned up/are invalid. Because json_cleanup_and_delete is recursive (will clean up nested children), when we reach the json_cleanup_and_delete(joMatch), it iterates over the team arrays and attempts to clean up the invalid handles, thus resulting in your error.

The best course of action (if I've understood your use-case correctly) is to remove the player json_cleanup_and_deletes in the loop AND remove the team cleanups (json_cleanup_and_delete(jaTA) and json_cleanup_and_delete(jaTB)). Ultimately you will only have one cleanup call right at the end, json_cleanup_and_delete(joMatch), which will recursively clean up the object and all nested children.

I'm going to close this off but if you have any further questions feel free to reopen it :)

lechuga16 commented 1 year ago

the answer was quite clear, thank you very much for your help