From 514a3bfd64506d08ee8a062c34a5f03c828e8528 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sat, 21 Sep 2013 13:38:44 +0000 Subject: [PATCH] Prevent calling function pointers cast to an incompatible type. Most often, this had happened when casting comparison functions for qsort() like these: "int yax_cmpbunches(const int16_t *b1, const int16_t *b2)" to a function pointer type expecting "const void *". Alas, this is undefined behavior: see http://blog.frama-c.com/index.php?post/2013/08/24/Function-pointers-in-C and posts linked from it. At least two cases have not been fixed: - The savegame system maintains pointers which are either to data or a function in the generic "void *". This ought to be made into a union. - Probably also: #define OSD_ALIAS (int32_t (*)(const osdfuncparm_t*))0x1337 git-svn-id: https://svn.eduke32.com/eduke32@4068 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/include/editor.h | 4 ++-- polymer/eduke32/build/src/build.c | 16 ++++++++-------- polymer/eduke32/build/src/engine.c | 19 +++++++++---------- polymer/eduke32/build/src/sdlayer.c | 7 +++++-- polymer/eduke32/build/src/winlayer.c | 7 +++++-- polymer/eduke32/source/astub.c | 10 +++++----- polymer/eduke32/source/m32exec.c | 14 +++++++------- polymer/eduke32/source/net.c | 6 +++--- 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/polymer/eduke32/build/include/editor.h b/polymer/eduke32/build/include/editor.h index faf83f845..30bed4364 100644 --- a/polymer/eduke32/build/include/editor.h +++ b/polymer/eduke32/build/include/editor.h @@ -214,9 +214,9 @@ void fade_editor_screen(int32_t keepcol); extern int32_t getnumber_internal1(char ch, int32_t *danumptr, int32_t maxnumber, char sign); extern int32_t getnumber_autocomplete(const char *namestart, char ch, int32_t *danum, int32_t flags); -int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t)); +int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, char sign, const char *(func)(int32_t)); #define getnumber256(namestart, num, maxnumber, sign) _getnumber256(namestart, num, maxnumber, sign, NULL) -int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t)); +int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char sign, const char *(func)(int32_t)); #define getnumber16(namestart, num, maxnumber, sign) _getnumber16(namestart, num, maxnumber, sign, NULL) void printmessage256(int32_t x, int32_t y, const char *name); void message(const char *fmt, ...) ATTRIBUTE((format(printf,1,2))); diff --git a/polymer/eduke32/build/src/build.c b/polymer/eduke32/build/src/build.c index 76dcec86c..73d34554e 100644 --- a/polymer/eduke32/build/src/build.c +++ b/polymer/eduke32/build/src/build.c @@ -2595,10 +2595,10 @@ static int32_t sectors_components(int16_t hlsectcnt, const int16_t *hlsector, in return 2; } -static int cmpgeomwal1(const int16_t *w1, const int16_t *w2) +static int cmpgeomwal1(const void *w1, const void *w2) { - const walltype *wal1 = &wall[*w1]; - const walltype *wal2 = &wall[*w2]; + const walltype *wal1 = &wall[*(int16_t *)w1]; + const walltype *wal2 = &wall[*(int16_t *)w2]; if (wal1->x == wal2->x) return wal1->y - wal2->y; @@ -2608,7 +2608,7 @@ static int cmpgeomwal1(const int16_t *w1, const int16_t *w2) static void sort_walls_geometrically(int16_t *wallist, int32_t nwalls) { - qsort(wallist, nwalls, sizeof(int16_t), (int(*)(const void *, const void *))&cmpgeomwal1); + qsort(wallist, nwalls, sizeof(int16_t), &cmpgeomwal1); } #endif @@ -8946,7 +8946,7 @@ int32_t getnumber_autocomplete(const char *namestart, char ch, int32_t *danum, i // 2: autocomplete names // 4: autocomplete taglabels // 8: return -1 if cancelled -int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t)) +int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char sign, const char *(func)(int32_t)) { char buffer[80], ournamestart[80-17], ch; int32_t n, danum, oldnum; @@ -8978,7 +8978,7 @@ int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char if (func != NULL) { - Bsnprintf(buffer, sizeof(buffer), "%s", (char *)func(danum)); + Bsnprintf(buffer, sizeof(buffer), "%s", func(danum)); // printext16(200L-24, ydim-STATUS2DSIZ+20L, editorcolors[9], editorcolors[0], buffer, 0); printext16(n<<3, ydim-STATUS2DSIZ+128, editorcolors[11], -1, buffer,0); } @@ -9017,7 +9017,7 @@ static void getnumber_clearline(void) } // sign: |16: don't draw scene -int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t)) +int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, char sign, const char *(func)(int32_t)) { char buffer[80], ournamestart[80-13], ch; int32_t danum, oldnum; @@ -9062,7 +9062,7 @@ int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, cha printmessage256(0, 0, buffer); if (func != NULL) { - Bsnprintf(buffer, sizeof(buffer), "%s", (char *)func(danum)); + Bsnprintf(buffer, sizeof(buffer), "%s", func(danum)); printmessage256(0, 9, buffer); } diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index 0022a2f26..2801bcb4b 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -785,9 +785,9 @@ static void yax_scanbunches(int32_t bbeg, int32_t numhere, const uint8_t *lastgo scansector_retfast = 0; } -static int yax_cmpbunches(const int16_t *b1, const int16_t *b2) +static int yax_cmpbunches(const void *b1, const void *b2) { - return (bunchdist[*b2] - bunchdist[*b1]); + return (bunchdist[*(int16_t *)b2] - bunchdist[*(int16_t *)b1]); } @@ -1009,8 +1009,7 @@ void yax_drawrooms(void (*SpriteAnimFunc)(int32_t,int32_t,int32_t,int32_t), yax_scanbunches(bbeg, numhere, (uint8_t *)gotsector); - qsort(&bunches[cf][bbeg], numhere, sizeof(int16_t), - (int(*)(const void *, const void *))&yax_cmpbunches); + qsort(&bunches[cf][bbeg], numhere, sizeof(int16_t), &yax_cmpbunches); if (numhere > 1 && lev != YAX_MAXDRAWS-1) Bmemset(lgotsector, 0, (numsectors+7)>>3); @@ -8459,7 +8458,7 @@ static inline int32_t raytrace(int32_t x3, int32_t y3, int32_t *x4, int32_t *y4) #define _POSIX_REALTIME_SIGNALS #endif #include -static void sighandler(int32_t sig, const siginfo_t *info, void *ctx) +static void sighandler(int sig, siginfo_t *info, void *ctx) { const char *s; UNREFERENCED_PARAMETER(ctx); @@ -8611,7 +8610,7 @@ int32_t initengine(void) #if !defined _WIN32 && defined DEBUGGINGAIDS && !defined GEKKO struct sigaction sigact, oldact; memset(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = (void (*)(int, siginfo_t*, void*))sighandler; + sigact.sa_sigaction = &sighandler; sigact.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &sigact, &oldact); #endif @@ -15628,10 +15627,10 @@ static void sideview_getdist(int16_t sw, int16_t sect) m32_sidedist[sw] = p->x*m32_viewplane.x + p->y*m32_viewplane.y + (p->z>>4)*m32_viewplane.z; } -static int sideview_cmppoints(const int16_t *sw1, const int16_t *sw2) +static int sideview_cmppoints(const void *sw1, const void *sw2) { - int32_t dist1 = m32_sidedist[*sw1]; - int32_t dist2 = m32_sidedist[*sw2]; + int32_t dist1 = m32_sidedist[*(int16_t *)sw1]; + int32_t dist2 = m32_sidedist[*(int16_t *)sw2]; if (dist2>dist1) return 1; @@ -16240,7 +16239,7 @@ void draw2dscreen(const vec3_t *pos, int16_t cursectnum, int16_t ange, int32_t z if (m32_sideview) { - qsort(m32_wallsprite, m32_swcnt, sizeof(int16_t), (int( *)(const void *, const void *))&sideview_cmppoints); + qsort(m32_wallsprite, m32_swcnt, sizeof(int16_t), &sideview_cmppoints); for (i=0; ifs - b->fs) != 0) return x; if ((x = a->bpp - b->bpp) != 0) return x; if ((x = a->xdim - b->xdim) != 0) return x; @@ -1093,7 +1096,7 @@ void getvalidmodes(void) #undef CHECK #undef ADDMODE - qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), (int32_t( *)(const void *,const void *))sortmodes); + qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes); modeschecked=1; } diff --git a/polymer/eduke32/build/src/winlayer.c b/polymer/eduke32/build/src/winlayer.c index c3684f59b..731803ad2 100644 --- a/polymer/eduke32/build/src/winlayer.c +++ b/polymer/eduke32/build/src/winlayer.c @@ -1807,10 +1807,13 @@ static HRESULT WINAPI getvalidmodes_enum(DDSURFACEDESC *ddsd, VOID *udata) return(DDENUMRET_OK); } -static int32_t sortmodes(const struct validmode_t *a, const struct validmode_t *b) +static int sortmodes(const void *a_, const void *b_) { int32_t x; + const struct validmode_t *a = (const struct validmode_t *)a_; + const struct validmode_t *b = (const struct validmode_t *)b_; + if ((x = a->fs - b->fs) != 0) return x; if ((x = a->bpp - b->bpp) != 0) return x; if ((x = a->xdim - b->xdim) != 0) return x; @@ -1867,7 +1870,7 @@ void getvalidmodes(void) ADDMODE(defaultres[i][0],defaultres[i][1],cdepths[j],0,-1) } - qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), (int32_t( *)(const void *,const void *))sortmodes); + qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes); modeschecked=1; } diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index 198c8aa21..01bee858a 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -6169,21 +6169,21 @@ static void Keys3d(void) else if (AIMING_AT_CEILING_OR_FLOOR) { sector[searchsector].lotag = - _getnumber256("Sector lotag: ", sector[searchsector].lotag, BTAG_MAX, 0, (void *(*)(int32_t))ExtGetSectorType); + _getnumber256("Sector lotag: ", sector[searchsector].lotag, BTAG_MAX, 0, &ExtGetSectorType); } else if (AIMING_AT_SPRITE) { if (sprite[searchwall].picnum == SECTOREFFECTOR) { sprite[searchwall].lotag = - _getnumber256("Sprite lotag: ", sprite[searchwall].lotag, BTAG_MAX, 0+j, (void *(*)(int32_t))SectorEffectorTagText); + _getnumber256("Sprite lotag: ", sprite[searchwall].lotag, BTAG_MAX, 0+j, &SectorEffectorTagText); } else if (sprite[searchwall].picnum == MUSICANDSFX) { int16_t oldtag = sprite[searchwall].lotag; sprite[searchwall].lotag = - _getnumber256("Sprite lotag: ", sprite[searchwall].lotag, BTAG_MAX, 0+j, (void *(*)(int32_t))MusicAndSFXTagText); + _getnumber256("Sprite lotag: ", sprite[searchwall].lotag, BTAG_MAX, 0+j, &MusicAndSFXTagText); if ((sprite[searchwall].filler&1) && sprite[searchwall].lotag != oldtag) { @@ -7795,7 +7795,7 @@ static void Keys2d(void) j = 4*(j&1); Bsprintf(buffer,"Sprite (%d) Lo-tag: ", i); sprite[i].lotag = _getnumber16(buffer, sprite[i].lotag, BTAG_MAX, 0+j, sprite[i].picnum==SECTOREFFECTOR ? - (void *(*)(int32_t))SectorEffectorTagText : NULL); + &SectorEffectorTagText : NULL); } else if (linehighlight >= 0) { @@ -7819,7 +7819,7 @@ static void Keys2d(void) { Bsprintf(buffer,"Sector (%d) Lo-tag: ", tcursectornum); sector[tcursectornum].lotag = - _getnumber16(buffer, sector[tcursectornum].lotag, BTAG_MAX, 0, (void *(*)(int32_t))ExtGetSectorType); + _getnumber16(buffer, sector[tcursectornum].lotag, BTAG_MAX, 0, &ExtGetSectorType); } } } diff --git a/polymer/eduke32/source/m32exec.c b/polymer/eduke32/source/m32exec.c index 7bbda50f6..13c929d15 100644 --- a/polymer/eduke32/source/m32exec.c +++ b/polymer/eduke32/source/m32exec.c @@ -224,15 +224,15 @@ static inline void __fastcall VM_DoConditional(register int32_t condition) } } -static int32_t X_DoSortDefault(const int32_t *lv, const int32_t *rv) +static int X_DoSortDefault(const void *lv, const void *rv) { - return (*rv - *lv); + return *(int32_t *)rv - *(int32_t *)lv; } -static int32_t X_DoSort(const int32_t *lv, const int32_t *rv) +static int X_DoSort(const void *lv, const void *rv) { - m32_sortvar1 = *lv; - m32_sortvar2 = *rv; + m32_sortvar1 = *(int32_t *)lv; + m32_sortvar2 = *(int32_t *)rv; insptr = x_sortingstateptr; VM_Execute(0); return g_iReturnVar; @@ -1213,13 +1213,13 @@ skip_check: if (state < 0) { - qsort(aGameArrays[aridx].vals, count, sizeof(int32_t), (int32_t(*)(const void *,const void *))X_DoSortDefault); + qsort(aGameArrays[aridx].vals, count, sizeof(int32_t), X_DoSortDefault); } else { x_sortingstateptr = script + statesinfo[state].ofs; vm.g_st = 1+MAXEVENTS+state; - qsort(aGameArrays[aridx].vals, count, sizeof(int32_t), (int32_t(*)(const void *,const void *))X_DoSort); + qsort(aGameArrays[aridx].vals, count, sizeof(int32_t), X_DoSort); vm.g_st = o_g_st; insptr = end; } diff --git a/polymer/eduke32/source/net.c b/polymer/eduke32/source/net.c index 685e6d697..611d3ff42 100644 --- a/polymer/eduke32/source/net.c +++ b/polymer/eduke32/source/net.c @@ -1076,9 +1076,9 @@ void Net_ReceiveMapUpdate(ENetEvent *event) //////////////////////////////////////////////////////////////////////////////// // Map State -static int Net_CompareActors(const netactor_t *actor1, const netactor_t *actor2) +static int Net_CompareActors(const void *actor1, const void *actor2) { - return actor1->netIndex - actor2->netIndex; + return ((netactor_t *)actor1)->netIndex - ((netactor_t *)actor2)->netIndex; } void Net_SaveMapState(netmapstate_t *save) @@ -1112,7 +1112,7 @@ void Net_SaveMapState(netmapstate_t *save) } } - qsort(save->actor, save->numActors, sizeof(netactor_t), (int( *)(const void *, const void *)) &Net_CompareActors); + qsort(save->actor, save->numActors, sizeof(netactor_t), &Net_CompareActors); } void Net_FillMapDiff(uint32_t fromRevision, uint32_t toRevision)