From bc28ca0636f5bce85683a7114ad99df4e7791847 Mon Sep 17 00:00:00 2001
From: kwolekr <kwolekr@minetest.net>
Date: Tue, 28 Oct 2014 00:18:53 -0400
Subject: [PATCH] Prevent invalid memory access under failure conditions

---
 src/biome.cpp                   | 31 ++++++++------
 src/biome.h                     | 19 +++------
 src/script/lua_api/l_mapgen.cpp | 75 ++++++++++++++++++---------------
 3 files changed, 64 insertions(+), 61 deletions(-)

diff --git a/src/biome.cpp b/src/biome.cpp
index 94a2435f2..fc92ad603 100644
--- a/src/biome.cpp
+++ b/src/biome.cpp
@@ -30,7 +30,8 @@ NoiseParams nparams_biome_def_heat(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.
 NoiseParams nparams_biome_def_humidity(50, 50, v3f(500.0, 500.0, 500.0), 842, 3, 0.55);
 
 
-BiomeDefManager::BiomeDefManager(NodeResolver *resolver) {
+BiomeDefManager::BiomeDefManager(NodeResolver *resolver)
+{
 	biome_registration_finished = false;
 	np_heat     = &nparams_biome_def_heat;
 	np_humidity = &nparams_biome_def_humidity;
@@ -58,7 +59,8 @@ BiomeDefManager::BiomeDefManager(NodeResolver *resolver) {
 }
 
 
-BiomeDefManager::~BiomeDefManager() {
+BiomeDefManager::~BiomeDefManager()
+{
 	//if (biomecache)
 	//	delete[] biomecache;
 	
@@ -67,7 +69,8 @@ BiomeDefManager::~BiomeDefManager() {
 }
 
 
-Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) {
+Biome *BiomeDefManager::createBiome(BiomeTerrainType btt)
+{
 	/*switch (btt) {
 		case BIOME_TERRAIN_NORMAL:
 			return new Biome;
@@ -86,7 +89,8 @@ Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) {
 
 
 // just a PoC, obviously needs optimization later on (precalculate this)
-void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) {
+void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map)
+{
 	int i = 0;
 	for (int y = 0; y != input->mapsize.Y; y++) {
 		for (int x = 0; x != input->mapsize.X; x++, i++) {
@@ -98,29 +102,31 @@ void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) {
 }
 
 
-void BiomeDefManager::addBiome(Biome *b) {
+bool BiomeDefManager::addBiome(Biome *b)
+{
 	if (biome_registration_finished) {
-		errorstream << "BIomeDefManager: biome registration already "
+		errorstream << "BiomeDefManager: biome registration already "
 			"finished, dropping " << b->name << std::endl;
-		delete b;
-		return;
+		return false;
 	}
 	
 	size_t nbiomes = biomes.size();
 	if (nbiomes >= 0xFF) {
 		errorstream << "BiomeDefManager: too many biomes, dropping "
 			<< b->name << std::endl;
-		delete b;
-		return;
+		return false;
 	}
 
 	b->id = (u8)nbiomes;
 	biomes.push_back(b);
 	verbosestream << "BiomeDefManager: added biome " << b->name << std::endl;
+
+	return true;
 }
 
 
-Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y) {
+Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y)
+{
 	Biome *b, *biome_closest = NULL;
 	float dist_min = FLT_MAX;
 
@@ -143,7 +149,8 @@ Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y) {
 }
 
 
-u8 BiomeDefManager::getBiomeIdByName(const char *name) {
+u8 BiomeDefManager::getBiomeIdByName(const char *name)
+{
 	for (size_t i = 0; i != biomes.size(); i++) {
 		if (!strcasecmp(name, biomes[i]->name.c_str()))
 			return i;
diff --git a/src/biome.h b/src/biome.h
index fdfefeaf9..554a61f4e 100644
--- a/src/biome.h
+++ b/src/biome.h
@@ -44,24 +44,16 @@ class Biome {
 	u8 id;
 	std::string name;
 	u32 flags;
-	
-/*
-	std::string nname_top;
-	std::string nname_filler;
-	std::string nname_water;
-	std::string nname_dust;
-	std::string nname_dust_water;
-*/
 
 	content_t c_top;
 	content_t c_filler;
 	content_t c_water;
 	content_t c_dust;
 	content_t c_dust_water;
-	
+
 	s16 depth_top;
 	s16 depth_filler;
-	
+
 	s16 height_min;
 	s16 height_max;
 	float heat_point;
@@ -85,15 +77,14 @@ class BiomeDefManager {
 
 	BiomeDefManager(NodeResolver *resolver);
 	~BiomeDefManager();
-	
+
 	Biome *createBiome(BiomeTerrainType btt);
 	void  calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map);
 	Biome *getBiome(float heat, float humidity, s16 y);
 
-	void addBiome(Biome *b);
-	void resolveNodeNames(INodeDefManager *ndef);
+	bool addBiome(Biome *b);
 	u8 getBiomeIdByName(const char *name);
-	
+
 	s16 calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime);
 	s16 calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime);
 };
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index b75488815..d0337cad6 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -142,7 +142,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
 			// emerged max pos
 			push_v3s16(L, vm->m_area.MaxEdge);
 
-			return 3; }
+			return 3;
+		}
 		case MGOBJ_HEIGHTMAP: {
 			if (!mg->heightmap)
 				return 0;
@@ -153,7 +154,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
 				lua_rawseti(L, -2, i + 1);
 			}
 
-			return 1; }
+			return 1;
+		}
 		case MGOBJ_BIOMEMAP: {
 			if (!mg->biomemap)
 				return 0;
@@ -164,7 +166,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
 				lua_rawseti(L, -2, i + 1);
 			}
 
-			return 1; }
+			return 1;
+		}
 		case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
 		case MGOBJ_HUMIDMAP:
 			if (strcmp(emerge->params.mg_name.c_str(), "v7"))
@@ -183,7 +186,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
 				lua_rawseti(L, -2, i + 1);
 			}
 
-			return 1; }
+			return 1;
+		}
 		case MGOBJ_GENNOTIFY: {
 			lua_newtable(L);
 			for (int i = 0; flagdesc_gennotify[i].name; i++) {
@@ -204,7 +208,8 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
 				posvec->clear();
 			}
 
-			return 1; }
+			return 1;
+		}
 	}
 
 	return 0;
@@ -302,15 +307,26 @@ int ModApiMapgen::l_register_biome(lua_State *L)
 
 	NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
 	BiomeDefManager *bmgr  = getServer(L)->getEmergeManager()->biomedef;
-	if (!bmgr) {
-		verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
-		return 0;
-	}
 
 	enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
 				"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
 	Biome *b = bmgr->createBiome(terrain);
 
+	b->name           = getstringfield_default(L, index, "name", "<no name>");
+	b->depth_top      = getintfield_default(L, index, "depth_top",    1);
+	b->depth_filler   = getintfield_default(L, index, "depth_filler", 3);
+	b->height_min     = getintfield_default(L, index, "height_min",   0);
+	b->height_max     = getintfield_default(L, index, "height_max",   0);
+	b->heat_point     = getfloatfield_default(L, index, "heat_point",     0.);
+	b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
+	b->flags          = 0; //reserved
+
+	if (!bmgr->addBiome(b)) {
+		delete b;
+		return 0;
+	}
+
+	// Pend node resolutions only if insertion succeeded
 	resolver->addNode(getstringfield_default(L, index, "node_top", ""),
 		 "mapgen_dirt_with_grass", CONTENT_AIR, &b->c_top);
 	resolver->addNode(getstringfield_default(L, index, "node_filler", ""),
@@ -322,17 +338,7 @@ int ModApiMapgen::l_register_biome(lua_State *L)
 	resolver->addNode(getstringfield_default(L, index, "node_dust_water", ""),
 		"mapgen_water_source", CONTENT_IGNORE, &b->c_dust_water);
 
-	b->name           = getstringfield_default(L, index, "name", "<no name>");
-	b->depth_top      = getintfield_default(L, index, "depth_top",    1);
-	b->depth_filler   = getintfield_default(L, index, "depth_filler", 3);
-	b->height_min     = getintfield_default(L, index, "height_min",   0);
-	b->height_max     = getintfield_default(L, index, "height_max",   0);
-	b->heat_point     = getfloatfield_default(L, index, "heat_point",     0.);
-	b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
-	b->flags          = 0; //reserved
-
 	verbosestream << "register_biome: " << b->name << std::endl;
-	bmgr->addBiome(b);
 
 	return 0;
 }
@@ -496,9 +502,6 @@ int ModApiMapgen::l_register_ore(lua_State *L)
 		return 0;
 	}
 
-	resolver->addNode(getstringfield_default(L, index, "ore", ""),
-		"", CONTENT_AIR, &ore->c_ore);
-
 	ore->ore_param2     = (u8)getintfield_default(L, index, "ore_param2", 0);
 	ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
 	ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
@@ -506,19 +509,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
 	ore->height_min     = getintfield_default(L, index, "height_min", 0);
 	ore->height_max     = getintfield_default(L, index, "height_max", 0);
 	ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0.);
+	ore->noise          = NULL;
 	ore->flags          = 0;
-	getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
-
-	std::vector<const char *> wherein_names;
-	getstringlistfield(L, index, "wherein", wherein_names);
-	for (size_t i = 0; i != wherein_names.size(); i++)
-		resolver->addNodeList(wherein_names[i], &ore->c_wherein);
-
-	lua_getfield(L, index, "noise_params");
-	ore->np = read_noiseparams(L, -1);
-	lua_pop(L, 1);
-
-	ore->noise = NULL;
 
 	if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) {
 		errorstream << "register_ore: clust_scarcity and clust_num_ores"
@@ -527,6 +519,20 @@ int ModApiMapgen::l_register_ore(lua_State *L)
 		return 0;
 	}
 
+	getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
+
+	lua_getfield(L, index, "noise_params");
+	ore->np = read_noiseparams(L, -1);
+	lua_pop(L, 1);
+
+	std::vector<const char *> wherein_names;
+	getstringlistfield(L, index, "wherein", wherein_names);
+	for (size_t i = 0; i != wherein_names.size(); i++)
+		resolver->addNodeList(wherein_names[i], &ore->c_wherein);
+
+	resolver->addNode(getstringfield_default(L, index, "ore", ""),
+		"", CONTENT_AIR, &ore->c_ore);
+
 	emerge->ores.push_back(ore);
 
 	//verbosestream << "register_ore: ore '" << ore->ore_name
@@ -595,7 +601,6 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
 	return 1;
 }
 
-
 // place_schematic(p, schematic, rotation, replacement)
 int ModApiMapgen::l_place_schematic(lua_State *L)
 {
-- 
GitLab