Package: libsdl1.2-dev
Version: 1.2.13-1
Severity: important
Justification: Violation of SYS V ABI specification

Hello,
Christoph Mallon, the driving coder behind ja2 stracciatella [0], has discovered
a serious problem. libsdl is violating the SYS V ABI (x86) [1]. There it is
stated that the "direction flag must be set to the "forward" (that is, zero)
direction before entry and upon exit." [2]. But as the program in the attachment
demonstrates ([3]) libsdl doesn't do that always.

If you use SDL_BlitSurface(), the direction flag is set after exiting the
function. This problem occurs because SDL_BlitSurface() calls SDL_revcpy(), the
sequence is:
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()

SDL_revcpy() sets but doesn't clear the direction flag. The incriminating code
is to be found in SDL_stdinc.h:
> #if defined(__GNUC__) && defined(i386)
> #define SDL_revcpy(dst, src, len)                     \
> do {                                                  \
>       int u0, u1, u2;                                 \
>       char *dstp = (char *)(dst);                     \
>       char *srcp = (char *)(src);                     \
>       int n = (len);                                  \
>       if ( n >= 4 ) {                                 \
>       __asm__ __volatile__ (                          \
>               "std\n\t"                               \
>               "rep ; movsl\n\t"                       \
>               : "=&c" (u0), "=&D" (u1), "=&S" (u2)    \
>               : "0" (n >> 2),                         \
>                 "1" (dstp+(n-4)), "2" (srcp+(n-4))    \
>               : "memory" );                           \
>       }                                               \
>       switch (n & 3) {                                \
>               case 3: dstp[2] = srcp[2];              \
>               case 2: dstp[1] = srcp[1];              \
>               case 1: dstp[0] = srcp[0];              \
>                       break;                          \
>               default:                                \
>                       break;                          \
>       }                                               \
> } while(0)
> #endif

As a sidenote: in the GCC 4.3 changelog it is stated that: "It is now invalid to
set the flag in asm statement without reseting it afterward.".

Kind regards,
Kai

P.S.: Please CC Christoph always!

[0] http://ja2.dragonriders.de/
[1] http://www.sco.com/developers/devspecs/abi386-4.pdf
[2] [1], page 38, EFLAGS
[3] Used build command: cc -O `sdl-config --cflags --libs` sdl_bug.c


-- System Information:
Debian Release: lenny/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)

Kernel: Linux 2.6.22.10-cabal
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8) (ignored: LC_ALL
set to de_DE.UTF-8)
Shell: /bin/sh linked to /bin/bash



-- 

Kai Wasserbäch (Kai Wasserbaech)

E-Mail: [EMAIL PROTECTED]
Jabber (debianforum.de): Drizzt
URL: http://wiki.debianforum.de/Drizzt_Do%27Urden
GnuPG: 0xE1DE59D2      0600 96CE F3C8 E733 E5B6 1587 A309 D76C E1DE 59D2
(http://pgpkeys.pca.dfn.de/pks/lookup?search=0xE1DE59D2&fingerprint=on&hash=on&op=vindex)


#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;
}

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to