summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCraig Robbins <kde.psych@gmail.com>2014-08-07 15:39:12 +1000
committerRealBadAngel <maciej.kasatkin@o2.pl>2014-08-23 06:40:27 +0200
commitf33d31693ed2ab7d2a29320181b6aba2c12f76d3 (patch)
treeb440bfeb24c4beddd5a73ea7ab4f9c4452733a39 /src
parent996ea60642c5d78fc915573af0641d78bc7e2d49 (diff)
downloadminetest-f33d31693ed2ab7d2a29320181b6aba2c12f76d3.tar.gz
minetest-f33d31693ed2ab7d2a29320181b6aba2c12f76d3.tar.bz2
minetest-f33d31693ed2ab7d2a29320181b6aba2c12f76d3.zip
Fix seg fault if popping from empty stack (L-system trees)
See: https://github.com/minetest/minetest/issues/1525 Background Wuzzy2: If you attempt to spawn a L-system tree with minetest.spawn_tree, you can make Minetest crash if it is attempted to pop an empty stack. ShadowNinja: This shouldn't cause a segmentation fault, but it should throw a Lua error Commit Description This commit throws a Lua error instead of causing a segmentation fault. The server will still "crash" but will include a Lua backtrace. L-Systems fix randomness Unless a random seed is provided (via Lua treedef) seed the PRNG with a different seed for each tree Resolves: https://github.com/minetest/minetest/issues/1469 Fix l-system crash when treedef random_level not set by Lua
Diffstat (limited to 'src')
-rw-r--r--src/script/lua_api/l_env.cpp16
-rw-r--r--src/treegen.cpp27
-rw-r--r--src/treegen.h10
3 files changed, 44 insertions, 9 deletions
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index e6ca846d8..deeb5966f 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -747,7 +747,8 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
}
getintfield(L, 2, "angle", tree_def.angle);
getintfield(L, 2, "iterations", tree_def.iterations);
- getintfield(L, 2, "random_level", tree_def.iterations_random_level);
+ if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
+ tree_def.iterations_random_level = 0;
getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
tree_def.fruit_chance=0;
@@ -757,11 +758,20 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
tree_def.fruitnode=ndef->getId(fruit);
getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
}
- getintfield(L, 2, "seed", tree_def.seed);
+ tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
}
else
return 0;
- treegen::spawn_ltree (env, p0, ndef, tree_def);
+
+ treegen::error e;
+ if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
+ if (e == treegen::UNBALANCED_BRACKETS) {
+ luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
+ } else {
+ luaL_error(L, "spawn_tree(): unknown error");
+ }
+ }
+
return 1;
}
diff --git a/src/treegen.cpp b/src/treegen.cpp
index 542bdf21c..bd4a2f2c9 100644
--- a/src/treegen.cpp
+++ b/src/treegen.cpp
@@ -118,14 +118,19 @@ void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
}
// L-System tree LUA spawner
-void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
+treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
{
ServerMap *map = &env->getServerMap();
std::map<v3s16, MapBlock*> modified_blocks;
ManualMapVoxelManipulator vmanip(map);
v3s16 tree_blockp = getNodeBlockPos(p0);
+ treegen::error e;
+
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
- make_ltree (vmanip, p0, ndef, tree_definition);
+ e = make_ltree (vmanip, p0, ndef, tree_definition);
+ if (e != SUCCESS)
+ return e;
+
vmanip.blitBackAll(&modified_blocks);
// update lighting
@@ -142,15 +147,25 @@ void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDe
event.modified_blocks.insert(i->first);
}
map->dispatchEvent(&event);
+ return SUCCESS;
}
//L-System tree generator
-void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
+treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
TreeDef tree_definition)
{
MapNode dirtnode(ndef->getId("mapgen_dirt"));
+ int seed;
+ if (tree_definition.explicit_seed)
+ {
+ seed = tree_definition.seed+14002;
+ }
+ else
+ {
+ seed = p0.X*2 + p0.Y*4 + p0.Z; // use the tree position to seed PRNG
+ }
+ PseudoRandom ps(seed);
- PseudoRandom ps(tree_definition.seed+14002);
// chance of inserting abcd rules
double prop_a = 9;
double prop_b = 8;
@@ -354,6 +369,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
stack_position.push(position);
break;
case ']':
+ if (stack_orientation.empty())
+ return UNBALANCED_BRACKETS;
rotation=stack_orientation.top();
stack_orientation.pop();
position=stack_position.top();
@@ -393,6 +410,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
break;
}
}
+
+ return SUCCESS;
}
void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
diff --git a/src/treegen.h b/src/treegen.h
index 55da6f9e5..a557ad975 100644
--- a/src/treegen.h
+++ b/src/treegen.h
@@ -30,6 +30,11 @@ class ServerEnvironment;
namespace treegen {
+ enum error {
+ SUCCESS,
+ UNBALANCED_BRACKETS
+ };
+
struct TreeDef {
std::string initial_axiom;
std::string rules_a;
@@ -50,6 +55,7 @@ namespace treegen {
MapNode fruitnode;
int fruit_chance;
int seed;
+ bool explicit_seed;
};
// Add default tree
@@ -60,10 +66,10 @@ namespace treegen {
INodeDefManager *ndef, int seed);
// Add L-Systems tree (used by engine)
- void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
+ treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
TreeDef tree_definition);
// Spawn L-systems tree from LUA
- void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
+ treegen::error spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
TreeDef tree_definition);
// L-System tree gen helper functions