mirror of
https://github.com/minetest/minetest.git
synced 2025-04-02 08:22:56 +02:00
Avoid out-of-bounds memory access in attached node placement prediction (#13038)
This commit is contained in:
committed by
GitHub
parent
504e43e0da
commit
1798ad0ec4
@ -3556,24 +3556,23 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
|
|
||||||
const ContentFeatures &predicted_f = nodedef->get(id);
|
const ContentFeatures &predicted_f = nodedef->get(id);
|
||||||
|
|
||||||
// Predict param2 for facedir and wallmounted nodes
|
// Compare core.item_place_node() for what the server does with param2
|
||||||
// Compare core.item_place_node() for what the server does
|
MapNode predicted_node(id, 0, 0);
|
||||||
u8 param2 = 0;
|
|
||||||
|
|
||||||
const u8 place_param2 = selected_def.place_param2;
|
const u8 place_param2 = selected_def.place_param2;
|
||||||
|
|
||||||
if (place_param2) {
|
if (place_param2) {
|
||||||
param2 = place_param2;
|
predicted_node.setParam2(place_param2);
|
||||||
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
v3s16 dir = nodepos - neighborpos;
|
v3s16 dir = nodepos - neighborpos;
|
||||||
|
|
||||||
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
|
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
|
||||||
param2 = dir.Y < 0 ? 1 : 0;
|
predicted_node.setParam2(dir.Y < 0 ? 1 : 0);
|
||||||
} else if (abs(dir.X) > abs(dir.Z)) {
|
} else if (abs(dir.X) > abs(dir.Z)) {
|
||||||
param2 = dir.X < 0 ? 3 : 2;
|
predicted_node.setParam2(dir.X < 0 ? 3 : 2);
|
||||||
} else {
|
} else {
|
||||||
param2 = dir.Z < 0 ? 5 : 4;
|
predicted_node.setParam2(dir.Z < 0 ? 5 : 4);
|
||||||
}
|
}
|
||||||
} else if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
} else if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR ||
|
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR ||
|
||||||
@ -3582,9 +3581,9 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
|
v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
|
||||||
|
|
||||||
if (abs(dir.X) > abs(dir.Z)) {
|
if (abs(dir.X) > abs(dir.Z)) {
|
||||||
param2 = dir.X < 0 ? 3 : 1;
|
predicted_node.setParam2(dir.X < 0 ? 3 : 1);
|
||||||
} else {
|
} else {
|
||||||
param2 = dir.Z < 0 ? 2 : 0;
|
predicted_node.setParam2(dir.Z < 0 ? 2 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3599,17 +3598,16 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
pp = p + v3s16(0, 1, 0);
|
pp = p + v3s16(0, 1, 0);
|
||||||
} else if (an == 2) {
|
} else if (an == 2) {
|
||||||
if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR ||
|
||||||
pp = p + facedir_dirs[param2];
|
predicted_f.param_type_2 == CPT2_4DIR ||
|
||||||
} else if (predicted_f.param_type_2 == CPT2_4DIR ||
|
predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_4DIR ) {
|
pp = p + facedir_dirs[predicted_node.getFaceDir(nodedef)];
|
||||||
pp = p + fourdir_dirs[param2];
|
|
||||||
} else {
|
} else {
|
||||||
pp = p;
|
pp = p;
|
||||||
}
|
}
|
||||||
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
pp = p + wallmounted_dirs[param2];
|
pp = p + predicted_node.getWallMountedDir(nodedef);
|
||||||
} else {
|
} else {
|
||||||
pp = p + v3s16(0, -1, 0);
|
pp = p + v3s16(0, -1, 0);
|
||||||
}
|
}
|
||||||
@ -3632,36 +3630,34 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
if (!indexstr.empty()) {
|
if (!indexstr.empty()) {
|
||||||
s32 index = mystoi(indexstr);
|
s32 index = mystoi(indexstr);
|
||||||
if (predicted_f.param_type_2 == CPT2_COLOR) {
|
if (predicted_f.param_type_2 == CPT2_COLOR) {
|
||||||
param2 = index;
|
predicted_node.setParam2(index);
|
||||||
} else if (predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
} else if (predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
// param2 = pure palette index + other
|
// param2 = pure palette index + other
|
||||||
param2 = (index & 0xf8) | (param2 & 0x07);
|
predicted_node.setParam2((index & 0xf8) | (predicted_node.getParam2() & 0x07));
|
||||||
} else if (predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
} else if (predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
// param2 = pure palette index + other
|
// param2 = pure palette index + other
|
||||||
param2 = (index & 0xe0) | (param2 & 0x1f);
|
predicted_node.setParam2((index & 0xe0) | (predicted_node.getParam2() & 0x1f));
|
||||||
} else if (predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
|
} else if (predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
|
||||||
// param2 = pure palette index + other
|
// param2 = pure palette index + other
|
||||||
param2 = (index & 0xfc) | (param2 & 0x03);
|
predicted_node.setParam2((index & 0xfc) | (predicted_node.getParam2() & 0x03));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add node to client map
|
// Add node to client map
|
||||||
MapNode n(id, 0, param2);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||||
|
|
||||||
// Don't place node when player would be inside new node
|
// Don't place node when player would be inside new node
|
||||||
// NOTE: This is to be eventually implemented by a mod as client-side Lua
|
// NOTE: This is to be eventually implemented by a mod as client-side Lua
|
||||||
if (!nodedef->get(n).walkable ||
|
if (!predicted_f.walkable ||
|
||||||
g_settings->getBool("enable_build_where_you_stand") ||
|
g_settings->getBool("enable_build_where_you_stand") ||
|
||||||
(client->checkPrivilege("noclip") && g_settings->getBool("noclip")) ||
|
(client->checkPrivilege("noclip") && g_settings->getBool("noclip")) ||
|
||||||
(nodedef->get(n).walkable &&
|
(predicted_f.walkable &&
|
||||||
neighborpos != player->getStandingNodePos() + v3s16(0, 1, 0) &&
|
neighborpos != player->getStandingNodePos() + v3s16(0, 1, 0) &&
|
||||||
neighborpos != player->getStandingNodePos() + v3s16(0, 2, 0))) {
|
neighborpos != player->getStandingNodePos() + v3s16(0, 2, 0))) {
|
||||||
// This triggers the required mesh update too
|
// This triggers the required mesh update too
|
||||||
client->addNode(p, n);
|
client->addNode(p, predicted_node);
|
||||||
// Report to server
|
// Report to server
|
||||||
client->interact(INTERACT_PLACE, pointed);
|
client->interact(INTERACT_PLACE, pointed);
|
||||||
// A node is predicted, also play a sound
|
// A node is predicted, also play a sound
|
||||||
|
Reference in New Issue
Block a user