From f03f3e4421470f9068f24ac48a1cf3788c1a9a05 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 5 Feb 2024 09:24:00 -0800 Subject: [PATCH] robustify ctrl memory streaming cache & texture cache layer to unreasonably large sizes/dimensions --- src/base/base_arena.c | 47 +++++++++++++++-------------- src/ctrl/ctrl_core.c | 49 ++++++++++++++++++++----------- src/df/gfx/df_view_rule_hooks.c | 6 +++- src/texture_cache/texture_cache.c | 6 ++-- 4 files changed, 63 insertions(+), 45 deletions(-) diff --git a/src/base/base_arena.c b/src/base/base_arena.c index 6e1a234f..06f38de4 100644 --- a/src/base/base_arena.c +++ b/src/base/base_arena.c @@ -10,44 +10,44 @@ arena_alloc__sized(U64 init_res, U64 init_cmt) ProfBeginFunction(); Assert(ARENA_HEADER_SIZE < init_cmt && init_cmt <= init_res); - void *memory; - U64 res; - U64 cmt; - + void *memory = 0; + U64 res = 0; + U64 cmt = 0; B32 large_pages = os_large_pages_enabled(); - if (large_pages) { + if(large_pages) + { U64 page_size = os_large_page_size(); res = AlignPow2(init_res, page_size); - #if OS_WINDOWS cmt = res; #else cmt = AlignPow2(init_cmt, page_size); #endif - memory = os_reserve_large(res); - if (!os_commit_large(memory, cmt)) { - memory = 0; - os_release(memory, res); - } - } else { - U64 page_size = os_page_size(); - res = AlignPow2(init_res, page_size); - cmt = AlignPow2(init_cmt, page_size); - - memory = os_reserve(res); - if (!os_commit(memory, cmt)) { + if(!os_commit_large(memory, cmt)) + { + memory = 0; + os_release(memory, res); + } + } + else + { + U64 page_size = os_page_size(); + res = AlignPow2(init_res, page_size); + cmt = AlignPow2(init_cmt, page_size); + memory = os_reserve(res); + if(!os_commit(memory, cmt)) + { memory = 0; os_release(memory, res); } } - Assert(memory); - - AsanPoisonMemoryRegion(memory, cmt); - AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE); Arena *arena = (Arena*)memory; - if (arena) { + if(arena) + { + AsanPoisonMemoryRegion(memory, cmt); + AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE); arena->prev = 0; arena->current = arena; arena->base_pos = 0; @@ -148,7 +148,6 @@ arena_push__impl(Arena *arena, U64 size) cmt_new_size = cmt_new_clamped - current->cmt; is_cmt_ok = os_commit((U8*)current + current->cmt, cmt_new_size); } - Assert(is_cmt_ok); if (is_cmt_ok) { current->cmt = cmt_new_clamped; diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 63f68c67..b6d886e2 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3232,6 +3232,14 @@ ctrl_mem_stream_thread__entry_point(void *p) take_task__break_all:; } + //- rjf: clamp range to be sensible + Rng1U64 vaddr_range_clamped = vaddr_range; + { + vaddr_range_clamped.max = Max(vaddr_range_clamped.max, vaddr_range_clamped.min); + U64 max_size_cap = Min(max_U64-vaddr_range_clamped.min, GB(1)); + vaddr_range_clamped.max = Min(vaddr_range_clamped.max, vaddr_range_clamped.min+max_size_cap); + } + //- rjf: task was taken -> read memory U64 range_size = 0; Arena *range_arena = 0; @@ -3240,31 +3248,38 @@ ctrl_mem_stream_thread__entry_point(void *p) U64 memgen_idx = ctrl_memgen_idx(); if(got_task && memgen_idx != preexisting_memgen_idx) { - range_size = dim_1u64(vaddr_range); + range_size = dim_1u64(vaddr_range_clamped); U64 arena_size = AlignPow2(range_size + ARENA_HEADER_SIZE, KB(64)); range_arena = arena_alloc__sized(range_size+ARENA_HEADER_SIZE, range_size+ARENA_HEADER_SIZE); - range_base = push_array_no_zero(range_arena, U8, range_size); - U64 bytes_read = ctrl_process_read(machine_id, process, vaddr_range, range_base); - if(bytes_read == 0) + if(range_arena == 0) { - arena_release(range_arena); - range_base = 0; range_size = 0; - range_arena = 0; } - else if(bytes_read < range_size) + else { - MemoryZero((U8 *)range_base + bytes_read, range_size-bytes_read); - } - zero_terminated_size = range_size; - if(zero_terminated) - { - for(U64 idx = 0; idx < bytes_read; idx += 1) + range_base = push_array_no_zero(range_arena, U8, range_size); + U64 bytes_read = ctrl_process_read(machine_id, process, vaddr_range_clamped, range_base); + if(bytes_read == 0) { - if(((U8 *)range_base)[idx] == 0) + arena_release(range_arena); + range_base = 0; + range_size = 0; + range_arena = 0; + } + else if(bytes_read < range_size) + { + MemoryZero((U8 *)range_base + bytes_read, range_size-bytes_read); + } + zero_terminated_size = range_size; + if(zero_terminated) + { + for(U64 idx = 0; idx < bytes_read; idx += 1) { - zero_terminated_size = idx; - break; + if(((U8 *)range_base)[idx] == 0) + { + zero_terminated_size = idx; + break; + } } } } diff --git a/src/df/gfx/df_view_rule_hooks.c b/src/df/gfx/df_view_rule_hooks.c index 2849a678..992a993a 100644 --- a/src/df/gfx/df_view_rule_hooks.c +++ b/src/df/gfx/df_view_rule_hooks.c @@ -933,7 +933,11 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap) df_gfx_request_frame(); } } - if(sig.hovering) + if(sig.hovering && r_handle_match(texture, r_handle_zero())) UI_Tooltip + { + ui_labelf("Texture not loaded."); + } + if(sig.hovering && !r_handle_match(texture, r_handle_zero())) { if(dim.y > (F32)topology_info.height) { diff --git a/src/texture_cache/texture_cache.c b/src/texture_cache/texture_cache.c index 1003e2f4..18a606fa 100644 --- a/src/texture_cache/texture_cache.c +++ b/src/texture_cache/texture_cache.c @@ -8,8 +8,8 @@ internal TEX_Topology tex_topology_make(Vec2S32 dim, R_Tex2DFormat fmt) { TEX_Topology top = {0}; - top.dim.x = (S16)dim.x; - top.dim.y = (S16)dim.y; + top.dim.x = (S16)Clamp(0, dim.x, max_S32); + top.dim.y = (S16)Clamp(0, dim.y, max_S32); top.fmt = fmt; return top; } @@ -352,7 +352,7 @@ tex_xfer_thread__entry_point(void *p) //- rjf: data * topology -> texture R_Handle texture = {0}; - if(got_task && top.dim.x != 0 && top.dim.y != 0 && data.size >= (U64)top.dim.x*(U64)top.dim.y*r_tex2d_format_bytes_per_pixel_table[top.fmt]) + if(got_task && top.dim.x > 0 && top.dim.y > 0 && data.size >= (U64)top.dim.x*(U64)top.dim.y*(U64)r_tex2d_format_bytes_per_pixel_table[top.fmt]) { texture = r_tex2d_alloc(R_Tex2DKind_Static, v2s32(top.dim.x, top.dim.y), top.fmt, data.str); }