Hello dear Cygwin developpers !

This is my first post here, so I would like to begin by sending you a big thank 
for Cygwin ! This is a great tool to port programs to Windows.


I think I found a bug in mprotect() implementation. This call is unable to set 
some protections (PROT_READ|PROT_WRITE for example) on a given memory area, 
while it can set some others (PROT_NONE or PROT_READ for example) on the same 
memory area. From my tests, it seems to happen only on WNT5+ (ie. Windows 2000 
and Windows XP - detailed results below).

I upgraded my whole Cygwin setup to confirm the problem is still alive. I also 
searched the web, FAQ, and ML archive without success before posting here.

I wrote a simple testcase to allow you to reproduce the bug. You'll find the 
source code as an attachement to this mail (to compile with "gcc -o 
testcase.exe testcase.c" and to run with "./testcase.exe"). This testcase 
allocate a block of memory with mmap(), fill it with memset(), plays with its 
protection with mprotect() and fill it again with memset().

I ran this test on various Windows flavour available around. Here are the 
results :

Windows OS                Lang   Result
------------------------- ------ ----------------------------------------
W98                       French OK
WNT4 SP6 (Workstation)    French OK
WNT4 SP6 (Server)         French OK
W2K SP4 (Professional)    French mprotect() (3) failed : Invalid argument
W2K SP4 (Advanced server) French mprotect() (3) failed : Invalid argument
WXP SP1 (Professional)    French mprotect() (3) failed : Invalid argument

Of course I'm ready to dig more if needed. But I really need some help since 
I'm not familiar with Cygwin source code, nor with Windows developpement.


For the curious, I discovered this bug while trying to support ARAnyM's m68k 
JIT compiler on Cygwin. ARAnyM (http://aranym.atari.org) is a free (GPLed) 
virtual Atari-compatible system.


Best Regards, and thanks in advance for any help,


Xavier
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>

int main(void)
{
        void *addr;
        size_t size, page_size;

        page_size = getpagesize();
        printf("Page size : %i\n", (int)page_size);
        size = 6 * (int)page_size;

        addr = mmap((caddr_t)0,
                    size,
                    (PROT_READ | PROT_WRITE),
                    (MAP_PRIVATE | MAP_ANONYMOUS),
                    0,
                    0);
        if (addr == MAP_FAILED)
        {
                printf("mmap() failed !\n");
                return 1;
        }
        printf("Address   : %X\n", (int)addr);

        if (memset(addr, 0, size) != addr)
        {
                printf("memset() failed !\n");
                return 2;
        }

        if (mprotect((caddr_t)addr, size, (PROT_NONE)) != 0)
        {
                printf("mprotect() (1) failed : %s\n", strerror(errno));
                return 3;
        }

        if (mprotect((caddr_t)addr, size, (PROT_READ)) != 0)
        {
                printf("mprotect() (2) failed : %s\n", strerror(errno));
                return 3;
        }

        if (mprotect((caddr_t)addr, size, (PROT_READ | PROT_WRITE)) != 0)
        {
                printf("mprotect() (3) failed : %s\n", strerror(errno));
                return 3;
        }

        if (memset(addr, 1, size) != addr)
        {
                printf("memset() failed !\n");
                return 4;
        }

        return 0;
}
--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Reply via email to