diff options
author | Craig Robbins <kde.psych@gmail.com> | 2014-08-07 15:39:12 +1000 |
---|---|---|
committer | RealBadAngel <maciej.kasatkin@o2.pl> | 2014-08-23 06:40:27 +0200 |
commit | f33d31693ed2ab7d2a29320181b6aba2c12f76d3 (patch) | |
tree | b440bfeb24c4beddd5a73ea7ab4f9c4452733a39 /src/treegen.cpp | |
parent | 996ea60642c5d78fc915573af0641d78bc7e2d49 (diff) | |
download | minetest-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/treegen.cpp')
-rw-r--r-- | src/treegen.cpp | 27 |
1 files changed, 23 insertions, 4 deletions
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, |