Skip to content

调用Replace方法替换一个不存在节点的value时会导致内存泄漏 #72

Description

@s745147415

问题描述

neb::CJsonObject将一个JSON字串构造成对象后,调用Replace方法替换一个不存在key的value时,Replace方法在返回错误前,未释放方法内部动态申请的节点对象,此时会导致内存泄漏!

代码段

该BUG涉及Replace相关的重载方法:

bool CJsonObject::Replace(const std::string& strKey, const CJsonObject& oJsonObject);
bool CJsonObject::Replace(const std::string& strKey, const std::string& strValue);
bool CJsonObject::Replace(const std::string& strKey, int32 iValue);
bool CJsonObject::Replace(const std::string& strKey, uint32 uiValue);
bool CJsonObject::Replace(const std::string& strKey, int64 llValue);
bool CJsonObject::Replace(const std::string& strKey, uint64 ullValue);
bool CJsonObject::Replace(const std::string& strKey, bool bValue, bool bValueAgain);
bool CJsonObject::Replace(const std::string& strKey, float fValue);
bool CJsonObject::Replace(const std::string& strKey, double dValue);
bool CJsonObject::ReplaceWithNull(const std::string& strKey);

BUG所在代码段示例

bool CJsonObject::Replace(const std::string& strKey, const std::string& strValue)
{
    cJSON* pFocusData = NULL;
    if (m_pJsonData == NULL)
    {
        pFocusData = m_pExternJsonDataRef;
    }
    else
    {
        pFocusData = m_pJsonData;
    }
    if (pFocusData == NULL)
    {
        m_strErrMsg = "json data is null!";
        return(false);
    }
    if (pFocusData->type != cJSON_Object)
    {
        m_strErrMsg = "not a json object! json array?";
        return(false);
    }
    cJSON* pJsonStruct = cJSON_CreateString(strValue.c_str());
    if (pJsonStruct == NULL)
    {
        return(false);
    }
#if __cplusplus < 201101L
    std::map<std::string, CJsonObject*>::iterator iter = m_mapJsonObjectRef.find(strKey);
#else
    auto iter = m_mapJsonObjectRef.find(strKey);
#endif
    if (iter != m_mapJsonObjectRef.end())
    {
        if (iter->second != NULL)
        {
            delete (iter->second);
            iter->second = NULL;
        }
        m_mapJsonObjectRef.erase(iter);
    }
    cJSON_ReplaceItemInObject(pFocusData, strKey.c_str(), pJsonStruct);
    if (cJSON_GetObjectItem(pFocusData, strKey.c_str()) == NULL)
    {
        // !!!此处返回失败前未释放方法内部新Create的cJSON对象,会导致内存泄漏!!!
        return(false);
    }
    return(true);
}

问题复现方法

可在CJsonObject工程中的demo.cpp调用Replace方法进行复现。

详细说明

bool CJsonObject::Replace(const std::string& strKey, const std::string& strValue)方法为例,在调用此方法替换一个key的字符串类型value时,方法内部会先cJSON_CreateString一个cJSON对象,但下文调用cJSON_ReplaceItemInObject进行Replace操作后,若调用cJSON_GetObjectItem获取节点失败,在 return (false) 前未调用cJSON_Delete释放新创建的对象,最终导致内存泄漏。

BUG解决建议

在上述涉及的Replace重载方法中,在方法 return(false) 前,新增cJSON_Delete(pJsonStruct);释放逻辑。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions