Skip to content

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

@s745147415

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);释放逻辑。

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