The x86 inline assembler version of the SDL macro SDL_revcpy() sets the direction flag ("std"), but does not clear it ("cld"). This is invalid according to GCC (inline assembler, which sets the direction flag, must reset it[0]) and the SYS V ABI (functions must leave with the direction flag cleared[1]). The macro is (indirectly, exact call sequence below) used in SDL_BlitSurface(), so this call sometimes returns with the direction flag set. This happens for bliting a surface onto itself with the destination coordinates set right/down of the source coordinates (typical use of this is scrolling left/up). Later on other parts of the code (like inlined memcpy()) cause memory corruption. Call sequence: SDL_BlitSurface() (#define SDL_Blit_Surface SDL_BlitUpper) SDL_BlitUpper() SDL_BlitLower() src->map->sw_blit() (function pointer to SDL_SoftBlit()) SDL_SoftBlit() src->map->sw_data->blit() (function pointer to SDL_BlitCopyOverlap()) SDL_BlitCopyOverlap() SDL_revcpy() [0] http://gcc.gnu.org/gcc-4.3/changes.html - "IA-32/x86-64", fourth bullet [1] http://www.sco.com/developers/devspecs/abi386-4.pdf - page 38 EFLAGS Fix: Add a "cld" in the macro SDL_revcpy(), see attached patch. Patch attached with submission follows: How-To-Repeat: This program demonstrates the problem (compile with "cc -O `sdl-config --cflags --libs` $FILENAME"): #include <SDL.h> #include <stdio.h> #include <stdlib.h> static inline int TestDirectionFlag(void) { unsigned eflags; __asm__ __volatile__("pushf\n\tpop %0" : "=r" (eflags)); return (eflags & 0x400) != 0; } int main(void) { SDL_Init(SDL_INIT_VIDEO); SDL_Surface* const s = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); SDL_Rect src_rect = { 0, 0, 630, 470 }; SDL_Rect dst_rect = { 10, 10, 630, 470 }; if (TestDirectionFlag()) { fputs("direction flag set BEFORE SDL_BlitSurface()\n", stderr); abort(); } SDL_BlitSurface(s, &src_rect, s, &dst_rect); if (TestDirectionFlag()) { fputs("direction flag set AFTER SDL_BlitSurface()\n", stderr); abort(); } SDL_Quit(); return 0; }
To which port does this PR apply? mcl
Responsible Changed From-To: freebsd-ports-bugs->db I'll take it
db 2008-01-27 21:37:56 UTC FreeBSD ports repository Added files: devel/sdl12/files patch-include_SDL_stdinc.h Log: - The x86 inline assembler version of the SDL macro SDL_revcpy() sets the direction flag ("std"), but does not clear it ("cld"). This is invalid according to GCC (inline assembler, which sets the direction flag, must reset it[0]) and the SYS V ABI (functions must leave with the direction flag cleared[1]). The macro is (indirectly, exact call sequence below) used in SDL_BlitSurface(), so this call sometimes returns with the direction flag set. This happens for bliting a surface onto itself with the destination coordinates set right/down of the source coordinates (typical use of this is scrolling left/up). Later on other parts of the code (like inlined memcpy()) cause memory corruption. [1] - Give maintaintership to submitter (as discussed on irc) PR: ports/120052 [1] Revision Changes Path 1.1 +10 -0 ports/devel/sdl12/files/patch-include_SDL_stdinc.h (new) _______________________________________________ cvs-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/cvs-all To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
State Changed From-To: open->closed Committed. Thanks!