idm: Fix bug in ID searching

* ID checking now checks if (id % step) == 0
* Extend possible ID range to allow UINT32_MAX (as long as base is non-zero)
This commit is contained in:
Eladash 2019-07-27 13:59:17 +03:00 committed by Ivan
parent 5c904bf3e2
commit 96527eee5b
4 changed files with 26 additions and 8 deletions

View File

@ -63,9 +63,9 @@ struct vdec_frame
struct vdec_context final
{
static constexpr u32 id_base = 0xf0000000;
static constexpr u32 id_step = 0x00000100;
static constexpr u32 id_count = 1024;
static const u32 id_base = 0xf0000000;
static const u32 id_step = 0x00000100;
static const u32 id_count = 1024;
AVCodec* codec{};
AVCodecContext* ctx{};

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Utilities/StrUtil.h"

View File

@ -16,7 +16,7 @@ sys_vm_t::sys_vm_t(const std::shared_ptr<vm::block_t>& area, const std::shared_p
sys_vm_t::~sys_vm_t()
{
// Free ID
g_ids[addr >> 28].release(0);
g_ids[addr >> 28].release(id_manager::id_traits<sys_vm_t>::invalid);
// Free block
verify(HERE), vm::unmap(addr);

View File

@ -32,7 +32,8 @@ namespace id_manager
static const u32 count = T::id_count;
static const u32 invalid = base > 0 ? 0 : -1;
static_assert(u64{step} * count + base < UINT32_MAX, "ID traits: invalid object range");
// Note: full 32 bits range cannot be used at current implementation
static_assert(count > 0 && step > 0 && u64{step} * count + base < u64{UINT32_MAX} + (base != 0 ? 1 : 0), "ID traits: invalid object range");
};
// Correct usage testing
@ -135,7 +136,19 @@ class idm
template <typename T>
static constexpr u32 get_index(u32 id)
{
return (id - id_manager::id_traits<T>::base) / id_manager::id_traits<T>::step;
using traits = id_manager::id_traits<T>;
// Note: if id is lower than base, diff / step will be higher than count
u32 diff = id - traits::base;
if (diff % traits::step)
{
// id is invalid, return invalid index
return traits::count;
}
// Get actual index
return diff / traits::step;
}
// Helper
@ -217,9 +230,14 @@ class idm
const u32 index = get_index<Type>(id);
if (index >= id_manager::id_traits<Type>::count)
{
return nullptr;
}
auto& vec = g_map[get_type<T>()];
if (index >= vec.size() || index >= id_manager::id_traits<Type>::count)
if (index >= vec.size())
{
return nullptr;
}