Report 1140 Actions
Problem Report Number |
1140 |
Submitter's Classification |
Test Suite problem |
State |
Resolved |
Resolution |
Rejected (REJ) |
Problem Resolution ID |
REJ.X.0342 |
Raised |
1970-01-01 08:00 |
Updated |
2003-03-13 08:00 |
Published |
null |
Product Standard |
Internationalised System Calls and Libraries Extended (UNIX 95) |
Certification Program |
The Open Brand certification program |
Test Suite |
VSU version 4.0.2 |
Test Identification |
base/mmap 17 18 19 21 22 23 |
Problem Summary |
PG4U.00130 This IR claims that the test fails on due to type conversion on 64 bit machines and that MAP_FAILED should be returned instead of (void *)-1. |
Problem Text |
We believe that the tests are in error because they make implicit assumptions about an implementation. Specifically, the test of the return value from mmap() via an equality test for -1. The POSIX.1-1996 standard (12.2.1.3 Returns) explicitly states that: "... it shall return a value MAP_FAILED...". Further, we realize that this is a change from previous POSIX.1 versions. The POSIX.1-1996 rational (Page 538, lines 7477-7481) states that the intention for the change was due to ambiguities in the C standard regarding casting of void* types. The ANSI C standard explicitly states in the section defining Cast operators (note: the section numbers vary depending on which version you examine): "An arbitrary integer may be converted to a pointer. The results is implementation-defined(*)". "(*) The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment." For specific information, a detailed explanation concerning our implementation is included below. We believe that the tests need to be modified to adhere to the current POSIX.1-1996 standard. We believe that this is easily done by replacing all occurances of -1 with MAP_FAILED for mmap() error checking conditions. Alternately, we provide an additional solution proposal below... The following are the technical specifics of this problem. The following lines (taken from the test-program supplied) > > if ((result = mmap(0, pgsz, PROT_READ, MAP_SHARED, fd, 0)) != (void *)-1) > { > printf("ERROR: mmap() did not return -1\n"); > printf("Expected :-1 Received: %p\n", result); > return; > } > are okay ONLY if we are building a 32-bit binary. This is because when mmap() fails, the value returned by mmap() is the maximum 32-bit address. result = 0xffffffff (32-bit address) and when -1 is typecast to (void *) we get (void *)-1 = 0xffffffff (32-bit pointer) Therefore the comparison made in the test-program works for the 32-bit case. However if the test-program is compiled to be a 64-bit binary, upon the failure of mmap() we will get the following case: result = 0xffffffffffffffff (64-bit address) But now when we typecast -1 to (void *) we have (void *)-1 = 0x00000000ffffffff (64-bit pointer) It is no surprise that the comparison is failing. This seems to be the result of the fact that the compiler is not sign-extending the 32-bit negative number (-1 here) when typecasting it to a pointer (which is actually correct). A better way to test for the success/failure status of the mmap() would be to use the following check (which works for both 32-bit and 64-bit binaries): if ((result = mmap(0, pgsz, PROT_READ, MAP_SHARED, fd, 0)) != (void *)-1L) { ... } Or better yet, the constant MAP_FAILED, prescribed by POSIX could be used. This constant is defined as follows: define MAP_FAILED (void *)-1L and therefore we can test for the success of an mmap() as follows: if( ( result = mmap(.....) ) == MAP_FAILED ) { /* failure */ } else { /* success */ }
|
Test Output |
TEST CASE: mmap TEST PURPOSE #17 EBADF in errno and return -1 on a call to void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) when fildes is not a valid file descriptor. PREP: Obtain the system page size by call to sysconf(_SC_PAGESIZE) PREP: Establish signal handlers for SIGSEGV and SIGBUS PREP: Open a file and initialize it PREP: Allocate memory for buffer PREP: Now set proper permissions and re-open file PREP: Create a closed file descriptor TEST: Return -1 when file descriptor is not valid ERROR: mmap() did not return -1 Expected :-1 Received: ffffffffffffffff 17 FAIL TEST PURPOSE #18 EACCES in errno and return -1 on a call to void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) when fildes is not open for reading. PREP: Obtain the system page size by call to sysconf(_SC_PAGESIZE) PREP: Establish signal handlers for SIGSEGV and SIGBUS PREP: Open a file and initialize it PREP: Allocate memory for buffer PREP: Now set proper permissions and re-open file TEST: Return -1 when file descriptor is not open for reading ERROR: mmap() did not return -1 Expected :-1 Received: ffffffffffffffff 18 FAIL TEST PURPOSE #19 EACCES in errno and return -1 on a call to void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) when fildes is not open for writing and PROT_WRITE is specified for a MAP_SHARED operation. PREP: Obtain the system page size by call to sysconf(_SC_PAGESIZE) PREP: Establish signal handlers for SIGSEGV and SIGBUS PREP: Open a file and initialize it PREP: Allocate memory for buffer PREP: Now set proper permissions and re-open file TEST: Return -1 when file descriptor not open for writing & PROT_WRITE is specified for a MAP_SHARED operation ERROR: mmap() did not return -1 Expected :-1 Received: ffffffffffffffff 19 FAIL TEST PURPOSE #21 EINVAL in errno and return -1 on a call to void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) when addr is not a multiple of the page size returned by sysconf(_SC_PAGESIZE) and MAP_FIXED is specified. PREP: Obtain the system page size by call to sysconf(_SC_PAGESIZE) PREP: Establish signal handlers for SIGSEGV and SIGBUS PREP: Open a file and initialize it PREP: Allocate memory for buffer PREP: Now set proper permissions and re-open file PREP: Find a fixed address not aligned to page boundary TEST: Return -1 when MAP_FIXED is set and the map address is not multiple of page size ERROR: mmap() did not return -1 Expected :-1 Received: 0xffffffffffffffff 21 FAIL TEST PURPOSE #22 EINVAL in errno and return -1 on a call to void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) when off is not a multiple of the page size returned by sysconf(_SC_PAGESIZE). PREP: Obtain the system page size by call to sysconf(_SC_PAGESIZE) PREP: Establish signal handlers for SIGSEGV and SIGBUS PREP: Open a file and initialize it PREP: Allocate memory for buffer PREP: Now set proper permissions and re-open file TEST: Return -1 when file offset is half the page size ERROR: mmap() did not return -1 Expected :-1 Received: ffffffffffffffff 22 FAIL TEST PURPOSE #23 EINVAL in errno and return -1 on a call to void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) when flags does not contain either MAP_PRIVATE or MAP_SHARED. PREP: Obtain the system page size by call to sysconf(_SC_PAGESIZE) PREP: Establish signal handlers for SIGSEGV and SIGBUS PREP: Open a file and initialize it PREP: Allocate memory for buffer PREP: Now set proper permissions and re-open file TEST: Return -1 when neither MAP_SHARED nor MAP_PRIVATE are set in flags ERROR: mmap() did not return -1 Expected :-1 Received: ffffffffffffffff 23 UNRESOLVED SECTION: Headers TEST CASE: mmap TEST PURPOSE #17,18,19,21,22,23 ERROR: mmap() did not return -1 Expected :-1 Received: ffffffffffffffff
|
Review Information
Review Type |
TSMA Review |
Start Date |
null |
Completed |
null |
Status |
Complete |
Review Recommendation |
No Resolution Given |
Review Response |
We recommend this request be refused. The journal output is from tests related to XSH4.2, which is testing the following statement from the RETURN VALUE section of mmap(): Upon successful completion, mmap() returns the address at which the mapping was placed (pa). Otherwise, it returns a value of -1 and sets errno to indicate the error. The mmap() function is defined to return a pointer to void, so (void *)-1 is the proper value expected. The standard does not specify a long integer constant (-1L) for the return value. The IUT does not return (void *)-1, so the test properly fails as expected. The references to MAP_FAILED are not meaningful, since this symbol is not defined for XSH4.2. However, MAP_FAILED is defined in XSH5 and tested for in the indicator of compliance for that specification. Note: VSU 4.0.2 is no longer valid for branding. The submitter should be using a more recent version of the test suite for testing. Note: POSIX.1-1996 is not a normative reference for XSH4.2. The submitter should be referencing POSIX.1-1990, which is normative.
|
Review Type |
SA Review |
Start Date |
null |
Completed |
null |
Status |
Complete |
Review Resolution |
No Resolution Given |
Review Conclusion |
The tests are correct as written for the XSH 4 Version 2 specification. However, this should be forwarded to the Base WG for consideration, regarding the issue of whether the XSH4.2 requirements should be waived in this case in favour of the XSH5 requirements which would thus permit this 64-bit implementation.
|
Review Type |
Expert Group Review |
Start Date |
null |
Completed |
null |
Status |
Complete |
Review Resolution |
No Resolution Given |
Review Conclusion |
The XSH4V2 specification states that mmap returns -1 cast to a (void *). This is not an LP64 issue. The waiver should be refused.
|
Review Type |
SA Review |
Start Date |
null |
Completed |
null |
Status |
Complete |
Review Resolution |
Rejected (REJ) |
Review Conclusion |
This request is refused.
|
Problem Reporting System Options:
|