Skip to content

Commit f33d316

Browse files
Zeno-RealBadAngel
authored andcommittedAug 23, 2014
Fix seg fault if popping from empty stack (L-system trees)
See: #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: #1469 Fix l-system crash when treedef random_level not set by Lua
1 parent 996ea60 commit f33d316

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed
 

‎doc/lua_api.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2208,7 +2208,7 @@ treedef={
22082208
thin_branches, - boolean true -> use thin (1 node) branches
22092209
fruit, - string fruit node name
22102210
fruit_chance, - num chance (0-100) to replace leaves with fruit node
2211-
seed, - num random seed
2211+
seed, - num random seed; if no seed is provided, the engine will create one
22122212
}
22132213

22142214
Key for Special L-System Symbols used in Axioms

‎src/script/lua_api/l_env.cpp

+13-3
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,8 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
747747
}
748748
getintfield(L, 2, "angle", tree_def.angle);
749749
getintfield(L, 2, "iterations", tree_def.iterations);
750-
getintfield(L, 2, "random_level", tree_def.iterations_random_level);
750+
if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
751+
tree_def.iterations_random_level = 0;
751752
getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
752753
getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
753754
tree_def.fruit_chance=0;
@@ -757,11 +758,20 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
757758
tree_def.fruitnode=ndef->getId(fruit);
758759
getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
759760
}
760-
getintfield(L, 2, "seed", tree_def.seed);
761+
tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
761762
}
762763
else
763764
return 0;
764-
treegen::spawn_ltree (env, p0, ndef, tree_def);
765+
766+
treegen::error e;
767+
if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
768+
if (e == treegen::UNBALANCED_BRACKETS) {
769+
luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
770+
} else {
771+
luaL_error(L, "spawn_tree(): unknown error");
772+
}
773+
}
774+
765775
return 1;
766776
}
767777

‎src/treegen.cpp

+23-4
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,19 @@ void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
118118
}
119119

120120
// L-System tree LUA spawner
121-
void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
121+
treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
122122
{
123123
ServerMap *map = &env->getServerMap();
124124
std::map<v3s16, MapBlock*> modified_blocks;
125125
ManualMapVoxelManipulator vmanip(map);
126126
v3s16 tree_blockp = getNodeBlockPos(p0);
127+
treegen::error e;
128+
127129
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
128-
make_ltree (vmanip, p0, ndef, tree_definition);
130+
e = make_ltree (vmanip, p0, ndef, tree_definition);
131+
if (e != SUCCESS)
132+
return e;
133+
129134
vmanip.blitBackAll(&modified_blocks);
130135

131136
// update lighting
@@ -142,15 +147,25 @@ void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDe
142147
event.modified_blocks.insert(i->first);
143148
}
144149
map->dispatchEvent(&event);
150+
return SUCCESS;
145151
}
146152

147153
//L-System tree generator
148-
void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
154+
treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
149155
TreeDef tree_definition)
150156
{
151157
MapNode dirtnode(ndef->getId("mapgen_dirt"));
158+
int seed;
159+
if (tree_definition.explicit_seed)
160+
{
161+
seed = tree_definition.seed+14002;
162+
}
163+
else
164+
{
165+
seed = p0.X*2 + p0.Y*4 + p0.Z; // use the tree position to seed PRNG
166+
}
167+
PseudoRandom ps(seed);
152168

153-
PseudoRandom ps(tree_definition.seed+14002);
154169
// chance of inserting abcd rules
155170
double prop_a = 9;
156171
double prop_b = 8;
@@ -354,6 +369,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
354369
stack_position.push(position);
355370
break;
356371
case ']':
372+
if (stack_orientation.empty())
373+
return UNBALANCED_BRACKETS;
357374
rotation=stack_orientation.top();
358375
stack_orientation.pop();
359376
position=stack_position.top();
@@ -393,6 +410,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
393410
break;
394411
}
395412
}
413+
414+
return SUCCESS;
396415
}
397416

398417
void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,

‎src/treegen.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class ServerEnvironment;
3030

3131
namespace treegen {
3232

33+
enum error {
34+
SUCCESS,
35+
UNBALANCED_BRACKETS
36+
};
37+
3338
struct TreeDef {
3439
std::string initial_axiom;
3540
std::string rules_a;
@@ -50,6 +55,7 @@ namespace treegen {
5055
MapNode fruitnode;
5156
int fruit_chance;
5257
int seed;
58+
bool explicit_seed;
5359
};
5460

5561
// Add default tree
@@ -60,10 +66,10 @@ namespace treegen {
6066
INodeDefManager *ndef, int seed);
6167

6268
// Add L-Systems tree (used by engine)
63-
void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
69+
treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
6470
TreeDef tree_definition);
6571
// Spawn L-systems tree from LUA
66-
void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
72+
treegen::error spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
6773
TreeDef tree_definition);
6874

6975
// L-System tree gen helper functions

0 commit comments

Comments
 (0)
Please sign in to comment.