This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: mmap() and gcc precompiled headers


On Fri, Jul 04, 2003 at 12:34:13PM -0700, Earl Chew wrote:
> 	  DWORD high;
> 	  DWORD low = GetFileSize (fh->get_handle (), &high);
> 	  __off64_t fsiz = ((__off64_t)high << 32) + low;
> /*1*/	  fsiz -= gran_off;
> 	  if (gran_len > fsiz)
> /*2*/	    gran_len = fsiz;
> 
> Firstly, gran_off was larger than fsiz. The subtraction at /*1*/

Urgh, isn't that a very strange border case?  Who the heck is trying
to establish a mmap with an offset beyond EOF (since that is the case
if gran_off is > filesize)?  What's the purpose of that?

> doesn't check for overflow, resulting in fsiz becoming negative.
> This results in gran_len taking on a very strange value. I suspect
> this situation should return with EINVAL or ENXIO.

Yeah, I admit that the above code isn't overly secure...

> Secondly, even if the value does not underflow, there is an
> interesting side-effect to the assignment made at /*2*/. This
> assignment can drastically reduce the value of gran_len.
> The caller is not aware that the actual mapping is much smaller
> than requested. (Should this fail with EOVERFLOW?)

The whole reasoning of the above kludgy statement is to make sure that
gran_off + gran_len is not bigger than GetFileSize, otherwise
MapViewOfFileEx fails.  Mapping beyond EOF is impossible on Windows,
unfortunately.

How to get this right?  Well, it's hard to get it like in Linux.
At least an offset >= filesize is not easily established.  I guess
returning EOVERFLOW would be correct according to SUSv3:

  [EOVERFLOW]
    The file is a regular file and the value of off plus len exceeds
    the offset maximum established in the open file description
    associated with fildes.

EINVAL is reserved for invalid addr or flags values.  ENXIO is a good
candidate as well:

  [ENXIO]
    Addresses in the range [off,off+len) are invalid for the object
    specified by fildes.

OTOH, if just off+len >= filesize, then it still should work, methinks.
off_len is reduced to match the filesize as it's currently implemented
and now let's have a look into munmap.

>     The munmap() function shall remove any mappings for those
>     entire pages containing any part of the address space of
>     the process starting at addr and continuing for len bytes.
>     Further references to these pages shall result in the generation
>     of a SIGSEGV signal to the process. If there are no mappings in
>     the specified address range, then munmap() has no effect.

Yes, mulling over this description for a while, I see that the
implementation of munmap isn't quite ok.  EINVAL is returned if
no mapping could be unmapped but that's obviously wrong.  
I'll rewrite munmap this weekend if I get the chance.

Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                                mailto:cygwin@cygwin.com
Red Hat, Inc.

--
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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]