Skip to content

Commit

Permalink
Fix /emergeblocks crashing in debug builds (#11461)
Browse files Browse the repository at this point in the history
The reason for the bug was an u16 overflow, thus failing the assert. This only happened in Debug build but not in Release builds.
  • Loading branch information
Wuzzy2 committed Jul 31, 2021
1 parent 0257e71 commit e7cd4cf
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 24 deletions.
6 changes: 3 additions & 3 deletions builtin/settingtypes.txt
Expand Up @@ -2218,15 +2218,15 @@ chunksize (Chunk size) int 5
enable_mapgen_debug_info (Mapgen debug) bool false

# Maximum number of blocks that can be queued for loading.
emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 1024
emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 1024 1 1000000

# Maximum number of blocks to be queued that are to be loaded from file.
# This limit is enforced per player.
emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 128
emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 128 1 1000000

# Maximum number of blocks to be queued that are to be generated.
# This limit is enforced per player.
emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 128
emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 128 1 1000000

# Number of emerge threads to use.
# Value 0:
Expand Down
29 changes: 12 additions & 17 deletions src/emerge.cpp
Expand Up @@ -165,20 +165,17 @@ EmergeManager::EmergeManager(Server *server)
if (nthreads < 1)
nthreads = 1;

m_qlimit_total = g_settings->getU16("emergequeue_limit_total");
m_qlimit_total = g_settings->getU32("emergequeue_limit_total");
// FIXME: these fallback values are probably not good
if (!g_settings->getU16NoEx("emergequeue_limit_diskonly", m_qlimit_diskonly))
if (!g_settings->getU32NoEx("emergequeue_limit_diskonly", m_qlimit_diskonly))
m_qlimit_diskonly = nthreads * 5 + 1;
if (!g_settings->getU16NoEx("emergequeue_limit_generate", m_qlimit_generate))
if (!g_settings->getU32NoEx("emergequeue_limit_generate", m_qlimit_generate))
m_qlimit_generate = nthreads + 1;

// don't trust user input for something very important like this
if (m_qlimit_total < 1)
m_qlimit_total = 1;
if (m_qlimit_diskonly < 1)
m_qlimit_diskonly = 1;
if (m_qlimit_generate < 1)
m_qlimit_generate = 1;
m_qlimit_total = rangelim(m_qlimit_total, 1, 1000000);
m_qlimit_diskonly = rangelim(m_qlimit_diskonly, 1, 1000000);
m_qlimit_generate = rangelim(m_qlimit_generate, 1, 1000000);

for (s16 i = 0; i < nthreads; i++)
m_threads.push_back(new EmergeThread(server, i));
Expand Down Expand Up @@ -425,14 +422,14 @@ bool EmergeManager::pushBlockEmergeData(
void *callback_param,
bool *entry_already_exists)
{
u16 &count_peer = m_peer_queue_count[peer_requested];
u32 &count_peer = m_peer_queue_count[peer_requested];

if ((flags & BLOCK_EMERGE_FORCE_QUEUE) == 0) {
if (m_blocks_enqueued.size() >= m_qlimit_total)
return false;

if (peer_requested != PEER_ID_INEXISTENT) {
u16 qlimit_peer = (flags & BLOCK_EMERGE_ALLOW_GEN) ?
u32 qlimit_peer = (flags & BLOCK_EMERGE_ALLOW_GEN) ?
m_qlimit_generate : m_qlimit_diskonly;
if (count_peer >= qlimit_peer)
return false;
Expand Down Expand Up @@ -467,20 +464,18 @@ bool EmergeManager::pushBlockEmergeData(

bool EmergeManager::popBlockEmergeData(v3s16 pos, BlockEmergeData *bedata)
{
std::map<v3s16, BlockEmergeData>::iterator it;
std::unordered_map<u16, u16>::iterator it2;

it = m_blocks_enqueued.find(pos);
auto it = m_blocks_enqueued.find(pos);
if (it == m_blocks_enqueued.end())
return false;

*bedata = it->second;

it2 = m_peer_queue_count.find(bedata->peer_requested);
auto it2 = m_peer_queue_count.find(bedata->peer_requested);
if (it2 == m_peer_queue_count.end())
return false;

u16 &count_peer = it2->second;
u32 &count_peer = it2->second;

assert(count_peer != 0);
count_peer--;

Expand Down
8 changes: 4 additions & 4 deletions src/emerge.h
Expand Up @@ -194,11 +194,11 @@ class EmergeManager {

std::mutex m_queue_mutex;
std::map<v3s16, BlockEmergeData> m_blocks_enqueued;
std::unordered_map<u16, u16> m_peer_queue_count;
std::unordered_map<u16, u32> m_peer_queue_count;

u16 m_qlimit_total;
u16 m_qlimit_diskonly;
u16 m_qlimit_generate;
u32 m_qlimit_total;
u32 m_qlimit_diskonly;
u32 m_qlimit_generate;

// Managers of various map generation-related components
// Note that each Mapgen gets a copy(!) of these to work with
Expand Down
9 changes: 9 additions & 0 deletions src/settings.cpp
Expand Up @@ -755,6 +755,15 @@ bool Settings::getS16NoEx(const std::string &name, s16 &val) const
}
}

bool Settings::getU32NoEx(const std::string &name, u32 &val) const
{
try {
val = getU32(name);
return true;
} catch (SettingNotFoundException &e) {
return false;
}
}

bool Settings::getS32NoEx(const std::string &name, s32 &val) const
{
Expand Down
1 change: 1 addition & 0 deletions src/settings.h
Expand Up @@ -186,6 +186,7 @@ class Settings {
bool getFlag(const std::string &name) const;
bool getU16NoEx(const std::string &name, u16 &val) const;
bool getS16NoEx(const std::string &name, s16 &val) const;
bool getU32NoEx(const std::string &name, u32 &val) const;
bool getS32NoEx(const std::string &name, s32 &val) const;
bool getU64NoEx(const std::string &name, u64 &val) const;
bool getFloatNoEx(const std::string &name, float &val) const;
Expand Down

0 comments on commit e7cd4cf

Please sign in to comment.