From 00e7005c0213d61afbf8d6a9c560ae3db2ac51fa Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sat, 15 Feb 2025 14:31:52 +0100 Subject: [PATCH] map sanitization (invalid references in map) --- game/console.c | 10 ++++--- game/globals.h | 2 +- game/realgame.c | 69 +++++++++++++++++++++++++++++++++++++++--------- game/sndandmus.c | 2 +- 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/game/console.c b/game/console.c index eabb7b3..bac29b9 100644 --- a/game/console.c +++ b/game/console.c @@ -380,7 +380,7 @@ static const int console_height = 165; static const int console_padding = 3; static int console_blink = 0; static char console_visible = 0; -#define CONSOLE_FONT H_FTINY +#define CONSOLE_FONT H_FLITT5 void draw_console_window() { if (!console_visible) return; @@ -584,15 +584,17 @@ static int process_actions(const char *command) { } if (istrcmp(command, "ascent") == 0) { - int lev = postavy[0].exp; + int lev = postavy[0].level; for (int i = 0; i < POCET_POSTAV; ++i) { THUMAN *p = postavy+i; if (p->used) lev = MAX(lev,p->level); } for (int i = 0; i < POCET_POSTAV; ++i) { THUMAN *p = postavy+i; - p->exp = level_map[lev-1]; - check_player_new_level(p); + if (p->used) { + p->exp = level_map[lev-1]; + check_player_new_level(p); + } } return 1; } diff --git a/game/globals.h b/game/globals.h index 15c8733..c237ce1 100644 --- a/game/globals.h +++ b/game/globals.h @@ -748,7 +748,7 @@ void a_touch(int sector,int dir); int do_action(int action_numb,int sector,int direct,int flags,int nosend); void delay_action(int action_numb,int sector,int direct,int flags,int nosend,int delay); int32_t load_section(FILE *f,void **section, int *sct_type,int32_t *sect_size); -void prepare_graphics(int *ofs,char *names,int32_t size,ABLOCK_DECODEPROC decomp,int class); +int prepare_graphics(int *ofs,char *names,int32_t size,ABLOCK_DECODEPROC decomp,int class); void show_automap(char full); void draw_medium_map(void); void anim_sipky(int h,int mode); diff --git a/game/realgame.c b/game/realgame.c index 6281845..94caac4 100644 --- a/game/realgame.c +++ b/game/realgame.c @@ -68,6 +68,7 @@ TMAP_EDIT_INFO *map_coord; TSTR_LIST level_texts; int mapsize; int num_ofsets[10]; //tabulka ofsetu pro cisla sten k levelu +int num_ofsets_count[10]; //count of items in each table char sekceid[]=""; char datapath; D_ACTION *d_action={NULL}; @@ -115,9 +116,10 @@ int32_t load_section(FILE *f,void **section, int *sct_type,int32_t *sect_size) } -void prepare_graphics(int *ofs,char *names,int32_t size,ABLOCK_DECODEPROC decomp,int class) +int prepare_graphics(int *ofs,char *names,int32_t size,ABLOCK_DECODEPROC decomp,int class) { char *p,*end; + int count = 0; end=names+size; p=names; @@ -127,7 +129,9 @@ void prepare_graphics(int *ofs,char *names,int32_t size,ABLOCK_DECODEPROC decom p=strchr(p,'\0'); p++; (*ofs)++; + ++count; } + return count; } @@ -187,6 +191,43 @@ const char *find_map_from_hash_impl(char *c, uint32_t h, int sz) { return c; } +void sanitize_map() { + for(int i = 1; i < mapsize; ++i) { + for (int j = 0; j < 4;++j) { + int nx = map_sectors[i].step_next[j]; + if (nx > mapsize) { + map_sectors[i].step_next[j] = i; + } + } + TSECTOR *sctr = map_sectors+i; + if (sctr->floor > num_ofsets_count[FLOOR_NUM]) { + sctr->floor = 0; + } if (sctr->ceil > num_ofsets_count[CEIL_NUM]) { + sctr->ceil = 0; + } + } + for (int i = 1, cnt = mapsize * 4; i < cnt; ++i) { + TSTENA *s = map_sides+i; + int max_side = MIN(num_ofsets_count[MAIN_NUM],MIN(num_ofsets_count[LEFT_NUM],num_ofsets_count[RIGHT_NUM])); + int max_obl = MIN(num_ofsets_count[OBL_NUM],num_ofsets_count[OBL2_NUM]); + if (s->prim > max_side) { + s->prim = 0; + } + if (s->sec > max_side) { + s->sec = 0; + } + if ((s->oblouk & 0x0F)> max_obl) { + s->oblouk &= ~0x0F; + } + if (s->prim + (s->prim_anim & 0xF) > max_side) { + s->prim_anim = max_side - (s->prim_anim & 0xF); + } + if (s->sec + (s->sec_anim & 0xF) > max_side) { + s->sec_anim = max_side - (s->sec_anim & 0xF); + } + } + +} int load_map(const char *filename) { @@ -238,42 +279,43 @@ int load_map(const char *filename) free(temp); break; case A_STRMAIN: - num_ofsets[0]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); + num_ofsets[MAIN_NUM]=ofsts-1; + num_ofsets_count[MAIN_NUM]=prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); free(temp); break; case A_STRLEFT: - num_ofsets[1]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); + num_ofsets[LEFT_NUM]=ofsts-1; + num_ofsets_count[LEFT_NUM]=prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); free(temp); break; case A_STRRIGHT: - num_ofsets[2]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); + num_ofsets[RIGHT_NUM]=ofsts-1; + num_ofsets_count[RIGHT_NUM] = prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); free(temp); break; case A_STRCEIL: - num_ofsets[3]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_15bit_autofade,SR_GRAFIKA); + num_ofsets[CEIL_NUM]=ofsts-1; + num_ofsets_count[CEIL_NUM]=prepare_graphics(&ofsts,temp,size,pcx_15bit_autofade,SR_GRAFIKA); free(temp); break; case A_STRFLOOR: - num_ofsets[4]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_15bit_autofade,SR_GRAFIKA); + num_ofsets[FLOOR_NUM]=ofsts-1; + num_ofsets_count[FLOOR_NUM]=prepare_graphics(&ofsts,temp,size,pcx_15bit_autofade,SR_GRAFIKA); free(temp); break; case A_STRARC: num_ofsets[OBL_NUM]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); + num_ofsets_count[OBL_NUM]=prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); free(temp); break; case A_STRARC2: num_ofsets[OBL2_NUM]=ofsts-1; - prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); + num_ofsets_count[OBL2_NUM]=prepare_graphics(&ofsts,temp,size,pcx_fade_decomp,SR_GRAFIKA); free(temp); break; case A_MAPGLOB: num_ofsets[BACK_NUM]=ofsts; + num_ofsets_count[BACK_NUM]=1; memset(&mglob,0,sizeof(mglob)); memcpy(&mglob,temp,MIN((int)size,(int)sizeof(mglob))); free(temp); @@ -364,6 +406,7 @@ int load_map(const char *filename) current_map_hash = fnv1a_hash(filename); const char * hash_str = map_hash_to_string(current_map_hash); temp_storage_store(hash_str, filename, strlen(filename)); + sanitize_map(); return failed; } diff --git a/game/sndandmus.c b/game/sndandmus.c index a964016..535ff90 100644 --- a/game/sndandmus.c +++ b/game/sndandmus.c @@ -365,7 +365,7 @@ static void build_dungeon_sound_map_in_dir(int sector, int side, int position, i if (d<32) { for (int i = 0; i < 4; ++i) { int nx = map_sectors[cursect].step_next[i]; - if (nx && (map_sides[cursect * 4 +i].flags & SD_TRANSPARENT)) { + if (nx && nx < mapsize && (map_sides[cursect * 4 +i].flags & SD_TRANSPARENT)) { if (current_sound_sector_map[nx].parts[position].visit_counter != counter) { TSOUND_MAP_QUEUE *t = queue+(qend % countof(queue)); ++qend;