Fix crash when page text is empty; add checks for MAX_PROMPTS and MAX_PAGES

This commit is contained in:
mazmazz 2018-11-09 21:55:14 -05:00
parent 311cb27818
commit b8897db308
3 changed files with 18 additions and 12 deletions

View file

@ -1773,17 +1773,17 @@ static void readtextprompt(MYFILE *f, INT32 num)
if (fastcmp(word, "NUMPAGES")) if (fastcmp(word, "NUMPAGES"))
{ {
textprompts[num]->numpages = value; textprompts[num]->numpages = min(max(value, 0), MAX_PAGES);
} }
else if (fastcmp(word, "PAGE")) else if (fastcmp(word, "PAGE"))
{ {
if (1 <= value && value <= 128) if (1 <= value && value <= MAX_PAGES)
{ {
textprompts[num]->page[value - 1].backcolor = UINT8_MAX; // non-zero default textprompts[num]->page[value - 1].backcolor = UINT8_MAX; // non-zero default
readtextpromptpage(f, num, value - 1); readtextpromptpage(f, num, value - 1);
} }
else else
deh_warning("Page number %d out of range (1 - 128)", value); deh_warning("Page number %d out of range (1 - %d)", value, MAX_PAGES);
} }
else else

View file

@ -166,6 +166,9 @@ typedef struct
extern cutscene_t *cutscenes[128]; extern cutscene_t *cutscenes[128];
#define MAX_PROMPTS 256
#define MAX_PAGES 128
typedef struct typedef struct
{ {
char name[32]; // narrator name char name[32]; // narrator name
@ -186,11 +189,11 @@ typedef struct
typedef struct typedef struct
{ {
textpage_t page[128]; // 128 pages per prompt. textpage_t page[MAX_PAGES];
INT32 numpages; // Number of pages in this prompt INT32 numpages; // Number of pages in this prompt
} textprompt_t; } textprompt_t;
extern textprompt_t *textprompts[256]; extern textprompt_t *textprompts[MAX_PROMPTS];
// For the Custom Exit linedef. // For the Custom Exit linedef.
extern INT16 nextmapoverride; extern INT16 nextmapoverride;

View file

@ -2065,7 +2065,7 @@ static void F_PreparePageText(char *pagetext)
if (promptpagetext) if (promptpagetext)
Z_Free(promptpagetext); Z_Free(promptpagetext);
promptpagetext = V_WordWrap(textx, textr, 0, pagetext); promptpagetext = (pagetext && pagetext[0]) ? V_WordWrap(textx, textr, 0, pagetext) : "";
F_NewCutscene(promptpagetext); F_NewCutscene(promptpagetext);
cutscene_textspeed = textprompts[cutnum]->page[scenenum].textspeed ? textprompts[cutnum]->page[scenenum].textspeed : TICRATE/5; cutscene_textspeed = textprompts[cutnum]->page[scenenum].textspeed ? textprompts[cutnum]->page[scenenum].textspeed : TICRATE/5;
@ -2085,7 +2085,7 @@ static void F_AdvanceToNextPage(void)
// determine next prompt // determine next prompt
if (nextprompt) if (nextprompt)
{ {
if (textprompts[nextprompt-1]) if (nextprompt <= MAX_PROMPTS && textprompts[nextprompt-1])
cutnum = nextprompt-1; cutnum = nextprompt-1;
else else
cutnum = INT32_MAX; cutnum = INT32_MAX;
@ -2095,14 +2095,14 @@ static void F_AdvanceToNextPage(void)
if (nextpage) if (nextpage)
{ {
scenenum = nextpage-1; scenenum = nextpage-1;
if (scenenum > textprompts[cutnum]->numpages-1) if (scenenum >= MAX_PAGES || scenenum > textprompts[cutnum]->numpages-1)
scenenum = INT32_MAX; scenenum = INT32_MAX;
} }
else else
{ {
if (cutnum != oldcutnum) if (cutnum != oldcutnum)
scenenum = 0; scenenum = 0;
else if (scenenum < textprompts[cutnum]->numpages-1) else if (scenenum + 1 < MAX_PAGES && scenenum < textprompts[cutnum]->numpages-1)
scenenum++; scenenum++;
else else
scenenum = INT32_MAX; scenenum = INT32_MAX;
@ -2157,8 +2157,8 @@ void F_StartTextPrompt(INT32 promptnum, INT32 pagenum, mobj_t *mo, UINT16 postex
(void)freezerealtime; // \todo freeze player->realtime, maybe this needs to cycle through player thinkers (void)freezerealtime; // \todo freeze player->realtime, maybe this needs to cycle through player thinkers
// Initialize current prompt and scene // Initialize current prompt and scene
cutnum = (textprompts[promptnum]) ? promptnum : INT32_MAX; cutnum = (promptnum < MAX_PROMPTS && textprompts[promptnum]) ? promptnum : INT32_MAX;
scenenum = (cutnum != INT32_MAX && pagenum <= textprompts[cutnum]->numpages-1) ? pagenum : INT32_MAX; scenenum = (cutnum != INT32_MAX && pagenum < MAX_PAGES && pagenum <= textprompts[cutnum]->numpages-1) ? pagenum : INT32_MAX;
promptactive = (cutnum != INT32_MAX && scenenum != INT32_MAX); promptactive = (cutnum != INT32_MAX && scenenum != INT32_MAX);
if (promptactive) if (promptactive)
@ -2320,7 +2320,10 @@ void F_TextPromptTicker(void)
} }
// generate letter-by-letter text // generate letter-by-letter text
if (!F_WriteText()) if (scenenum >= MAX_PAGES ||
!textprompts[cutnum]->page[scenenum].text ||
!textprompts[cutnum]->page[scenenum].text[0] ||
!F_WriteText())
timetonext = !promptblockcontrols; // never show the chevron if we can't toggle pages timetonext = !promptblockcontrols; // never show the chevron if we can't toggle pages
} }