-
Notifications
You must be signed in to change notification settings - Fork 241
Description
问题描述
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);释放逻辑。