From 5be786c804d36e9950598a01cf39f05574af2acc Mon Sep 17 00:00:00 2001 From: MetaDucky Date: Wed, 20 Nov 2013 22:11:57 +0100 Subject: [PATCH] Fixed potential NULL pointer and leak when setting node metadata --- src/map.cpp | 19 ++++++++----------- src/map.h | 17 ++++++++++++++++- src/rollback_interface.cpp | 8 +++++++- src/script/lua_api/l_nodemeta.cpp | 18 ++++++++++++------ src/script/lua_api/l_nodemeta.h | 13 +++++++++++++ 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 0dbfd42f..0f9c82c3 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2279,7 +2279,7 @@ void Map::transformLiquids(std::map & modified_blocks) updateLighting(lighting_modified_blocks, modified_blocks); } -NodeMetadata* Map::getNodeMetadata(v3s16 p) +NodeMetadata *Map::getNodeMetadata(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE; @@ -2289,8 +2289,7 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p) <m_node_metadata.set(p_rel, meta); + return true; } void Map::removeNodeMetadata(v3s16 p) @@ -2342,8 +2341,7 @@ NodeTimer Map::getNodeTimer(v3s16 p) <setNodeMetadata(p, meta); + if(!map->setNodeMetadata(p, meta)){ + delete meta; + infostream<<"RollbackAction::applyRevert(): " + <<"setNodeMetadata failed at " + <deSerialize(is); diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index f9c8794d..4f20e56f 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -42,10 +42,12 @@ NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg) NodeMetadata* NodeMetaRef::getmeta(NodeMetaRef *ref, bool auto_create) { NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); - if(meta == NULL && auto_create) - { + if(meta == NULL && auto_create) { meta = new NodeMetadata(ref->m_env->getGameDef()); - ref->m_env->getMap().setNodeMetadata(ref->m_p, meta); + if(!ref->m_env->getMap().setNodeMetadata(ref->m_p, meta)) { + delete meta; + return NULL; + } } return meta; } @@ -227,17 +229,21 @@ int NodeMetaRef::l_from_table(lua_State *L) NodeMetaRef *ref = checkobject(L, 1); int base = 2; + // clear old metadata first + ref->m_env->getMap().removeNodeMetadata(ref->m_p); + if(lua_isnil(L, base)){ // No metadata - ref->m_env->getMap().removeNodeMetadata(ref->m_p); lua_pushboolean(L, true); return 1; } - // Has metadata; clear old one first - ref->m_env->getMap().removeNodeMetadata(ref->m_p); // Create new metadata NodeMetadata *meta = getmeta(ref, true); + if(meta == NULL){ + lua_pushboolean(L, false); + return 1; + } // Set fields lua_getfield(L, base, "fields"); int fieldstable = lua_gettop(L); diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h index ed06ff0f..e39ac393 100644 --- a/src/script/lua_api/l_nodemeta.h +++ b/src/script/lua_api/l_nodemeta.h @@ -39,6 +39,19 @@ private: static NodeMetaRef *checkobject(lua_State *L, int narg); + /** + * Retrieve metadata for a node. + * If @p auto_create is set and the specified node has no metadata information + * associated with it yet, the method attempts to attach a new metadata object + * to the node and returns a pointer to the metadata when successful. + * + * However, it is NOT guaranteed that the method will return a pointer, + * and @c NULL may be returned in case of an error regardless of @p auto_create. + * + * @param ref specifies the node for which the associated metadata is retrieved. + * @param auto_create when true, try to create metadata information for the node if it has none. + * @return pointer to a @c NodeMetadata object or @c NULL in case of error. + */ static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create); static void reportMetadataChange(NodeMetaRef *ref); -- 2.30.2