Add rudimentary sanity checks when playing ANM files.

- Don't attempt to play an ANM file if it is empty (warn) or too short (error).
- If failing to read IVF file header or initializing VPX codec, don't play ANM.
- Return early from gltexapplyprops() if not in GL modes.

git-svn-id: https://svn.eduke32.com/eduke32@3628 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-03-31 18:57:59 +00:00
parent 85d6526264
commit fe69ee5476
4 changed files with 50 additions and 24 deletions

View file

@ -492,6 +492,9 @@ void gltexapplyprops(void)
int32_t i; int32_t i;
pthtyp *pth; pthtyp *pth;
if (rendmode == REND_CLASSIC)
return;
if (glinfo.maxanisotropy > 1.0) if (glinfo.maxanisotropy > 1.0)
{ {
if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy)

View file

@ -209,7 +209,7 @@ static void endanimvol43(int32_t fr)
void G_PlayAnim(const char *fn, char t) void G_PlayAnim(const char *fn, char t)
{ {
char *animbuf; uint8_t *animbuf;
int32_t i, length=0, numframes=0; int32_t i, length=0, numframes=0;
#ifdef USE_OPENGL #ifdef USE_OPENGL
int32_t ogltexfiltermode=gltexfiltermode; int32_t ogltexfiltermode=gltexfiltermode;
@ -237,7 +237,7 @@ void G_PlayAnim(const char *fn,char t)
if (I_CheckAllInput()) if (I_CheckAllInput())
{ {
FX_StopAllSounds(); FX_StopAllSounds();
goto ENDOFANIMLOOP; goto end_anim;
} }
#ifdef USE_LIBVPX #ifdef USE_LIBVPX
@ -273,14 +273,15 @@ void G_PlayAnim(const char *fn,char t)
OSD_Printf("Failed reading IVF file: %s\n", OSD_Printf("Failed reading IVF file: %s\n",
animvpx_read_ivf_header_errmsg[i]); animvpx_read_ivf_header_errmsg[i]);
kclose(handle); kclose(handle);
break; return;
} }
animvpx_setup_glstate(); animvpx_setup_glstate();
if (animvpx_init_codec(&info, handle, &codec)) if (animvpx_init_codec(&info, handle, &codec))
{ {
OSD_Printf("Error initializing VPX codec.\n");
animvpx_restore_glstate(); animvpx_restore_glstate();
break; return;
} }
animidx = t-1; animidx = t-1;
@ -356,9 +357,16 @@ void G_PlayAnim(const char *fn,char t)
#endif #endif
// ANM playback --- v v v --- // ANM playback --- v v v ---
handle = kopen4load((char *)fn,0); handle = kopen4load(fn, 0);
if (handle == -1) return; if (handle == -1)
return;
length = kfilelength(handle); length = kfilelength(handle);
if (length == 0)
{
OSD_Printf("Warning: skipping playback of empty ANM file \"%s\".\n", fn);
goto end_anim;
}
walock[TILE_ANIM] = 219+t; walock[TILE_ANIM] = 219+t;
@ -370,7 +378,14 @@ void G_PlayAnim(const char *fn,char t)
kread(handle, animbuf, length); kread(handle, animbuf, length);
kclose(handle); kclose(handle);
ANIM_LoadAnim(animbuf); if (ANIM_LoadAnim(animbuf, length) < 0)
{
// XXX: ANM_LoadAnim() still checks less than the bare minimum,
// e.g. ANM file could still be too small and not contain any frames.
OSD_Printf("Error: malformed ANM file \"%s\".\n", fn);
goto end_anim;
}
numframes = ANIM_NumFrames(); numframes = ANIM_NumFrames();
basepaltable[ANIMPAL] = ANIM_GetPalette(); basepaltable[ANIMPAL] = ANIM_GetPalette();
@ -391,7 +406,7 @@ void G_PlayAnim(const char *fn,char t)
if (i > 4 && totalclock > frametime + 60) if (i > 4 && totalclock > frametime + 60)
{ {
OSD_Printf("WARNING: slowdown in %s, skipping playback\n", fn); OSD_Printf("WARNING: slowdown in %s, skipping playback\n", fn);
goto ENDOFANIMLOOP; goto end_anim_restore_gl;
} }
frametime = totalclock; frametime = totalclock;
@ -406,7 +421,7 @@ void G_PlayAnim(const char *fn,char t)
G_HandleAsync(); G_HandleAsync();
if (I_CheckAllInput()) if (I_CheckAllInput())
goto ENDOFANIMLOOP; goto end_anim_restore_gl;
if (g_restorePalette == 1) if (g_restorePalette == 1)
{ {
@ -440,11 +455,12 @@ void G_PlayAnim(const char *fn,char t)
else if (t < 4) endanimsounds(i); else if (t < 4) endanimsounds(i);
} }
ENDOFANIMLOOP: end_anim_restore_gl:
#ifdef USE_OPENGL #ifdef USE_OPENGL
gltexfiltermode = ogltexfiltermode; gltexfiltermode = ogltexfiltermode;
gltexapplyprops(); gltexapplyprops();
#endif #endif
end_anim:
I_ClearAllInput(); I_ClearAllInput();
ANIM_FreeAnim(); ANIM_FreeAnim();
walock[TILE_ANIM] = 1; walock[TILE_ANIM] = 1;

View file

@ -89,7 +89,7 @@ typedef struct
lp_descriptor * curlp; // header of large page currently in memory lp_descriptor * curlp; // header of large page currently in memory
uint16_t * thepage; // buffer where current large page is loaded uint16_t * thepage; // buffer where current large page is loaded
uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded
uint8_t * buffer; const uint8_t * buffer;
uint8_t pal[768]; uint8_t pal[768];
int32_t currentframe; int32_t currentframe;
} anim_t; } anim_t;
@ -254,10 +254,14 @@ static inline void drawframe(uint16_t framenumber)
renderframe(framenumber, anim->thepage); renderframe(framenumber, anim->thepage);
} }
// <length> is the file size, for consistency checking.
void ANIM_LoadAnim(char * buffer) int32_t ANIM_LoadAnim(const uint8_t *buffer, int32_t length)
{ {
uint16_t i; int32_t i;
length -= sizeof(lpfileheader)+128+768;
if (length < 0)
return -1;
anim = (anim_t *)Brealloc(anim, sizeof(anim_t)); anim = (anim_t *)Brealloc(anim, sizeof(anim_t));
@ -279,6 +283,10 @@ void ANIM_LoadAnim(char * buffer)
anim->lpheader->nFrames = B_LITTLE32(anim->lpheader->nFrames); anim->lpheader->nFrames = B_LITTLE32(anim->lpheader->nFrames);
anim->lpheader->framesPerSecond = B_LITTLE16(anim->lpheader->framesPerSecond); anim->lpheader->framesPerSecond = B_LITTLE16(anim->lpheader->framesPerSecond);
length -= anim->lpheader->nLps * sizeof(lp_descriptor);
if (length < 0)
return -2;
buffer += sizeof(lpfileheader)+128; buffer += sizeof(lpfileheader)+128;
// load the color palette // load the color palette
@ -301,17 +309,16 @@ void ANIM_LoadAnim(char * buffer)
anim->LpArray[i].nRecords = B_LITTLE16(anim->LpArray[i].nRecords); anim->LpArray[i].nRecords = B_LITTLE16(anim->LpArray[i].nRecords);
anim->LpArray[i].nBytes = B_LITTLE16(anim->LpArray[i].nBytes); anim->LpArray[i].nBytes = B_LITTLE16(anim->LpArray[i].nBytes);
} }
return 0;
} }
void ANIM_FreeAnim(void) void ANIM_FreeAnim(void)
{
if (anim != NULL)
{ {
Bfree(anim); Bfree(anim);
anim = NULL; anim = NULL;
} }
}
int32_t ANIM_NumFrames(void) int32_t ANIM_NumFrames(void)

View file

@ -45,7 +45,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
// //
//**************************************************************************** //****************************************************************************
void ANIM_LoadAnim(char * buffer); int32_t ANIM_LoadAnim(const uint8_t *buffer, int32_t length);
//**************************************************************************** //****************************************************************************
// //