[system] error_code_test.cpp does not account for implementation-specific behaviour of strerror()

Test error_code_test[_dll] fails on HP-UX and AIX and I'd expect it to fail on Tru64 also (Tru64 results are currently not on the web). The test checks message for error code -1 in both system and posix category and expects it to be "Unknown error". For system category: ec = error_code( -1, system_category ); std::cout << "error_code message for -1 is \"" << ec.message() << "\"\n"; BOOST_CHECK( ec.message().substr( 0, 13) == "Unknown error" ); IIUC, the assumption is that strerror(invalid-error-code) either returns a pointer to a string starting with "Unknown error", which is the case on Linux -- see below, or returns a null pointer in which case libs/system/src/error_code.cpp maps it to "Unknown error" string: const char * c_str = std::strerror( ev ); return std::string( c_str ? c_str : "Unknown error" ); The problem with this assumption is that there is no requirement in the C standard that the message string generated by strerror() for an invalid error code starts with "Unknown error" -- see excerpt from C99 below. For example, on HP-UX, strerror() returns an empty string and on Tru64 it returns "Error -1 occurred." As for the null pointer, strerror() cannot return it -- again, see excerpt from C99 below. X/Open explicitly states that strerror() may signal error by setting errno, but not by returning any particular value: " Upon successful completion, strerror() returns a pointer to the generated message string. On error errno may be set, but no return value is reserved to indicate an error. " It does not mean that error_code.cpp should not check for a null pointer as a precaution against non-conformant implementation of strerror(). In libs/system/test/error_code_test.cpp, the check for the message string corresponding to error code -1 should either be conditionalized for different platforms or removed. Here is conditionalization for system category for HP-UX and Tru64 (I don't have IBM machine at my disposal and cannot figure out conditionalization for AIX): #if defined(__hpux) BOOST_CHECK( *(ec.message().c_str()) == 0 ); #elif defined(__osf__) BOOST_CHECK( ec.message().c_str() == "Error -1 occurred." ); #else BOOST_CHECK( ec.message().substr( 0, 13) == "Unknown error" ); #endif x.c --- #include <stdio.h> #include <string.h> int main() { const char * c_str = strerror( -1 ); printf( "%s\n", c_str ? c_str : "Unknown error" ); } bash-3.00$ uname Linux bash-3.00$ cc x.c && a.out Unknown error 18446744073709551615 bash-3.00$ bash-2.03$ uname HP-UX bash-2.03$ cc x.c && a.out bash-2.03$ cosf.zko.hp.com> uname OSF1 cosf.zko.hp.com> cc x.c && a.out Error -1 occurred. cosf.zko.hp.com>
From C99:
7.21.6.2 The strerror function Synopsis [#1] #include <string.h> char *strerror(int errnum); Description [#2] The strerror function maps the number in errnum to a message string. Typically, the values for errnum come from errno, but strerror shall map any value of type int to a message. [#3] The implementation shall behave as if no library function calls the strerror function. Returns [#4] The strerror function returns a pointer to the string, the contents of which are locale-specific. The array pointed to shall not be modified by the program, but may be overwritten by a subsequent call to the strerror function. Thanks, Boris

Boris Gubenko wrote:
Test error_code_test[_dll] fails on HP-UX and AIX and I'd expect it to fail on Tru64 also (Tru64 results are currently not on the web).
The test checks message for error code -1 in both system and posix category and expects it to be "Unknown error". For system category:
ec = error_code( -1, system_category ); std::cout << "error_code message for -1 is \"" << ec.message() << "\"\n"; BOOST_CHECK( ec.message().substr( 0, 13) == "Unknown error" );
IIUC, the assumption is that strerror(invalid-error-code) either returns a pointer to a string starting with "Unknown error", which is the case on Linux -- see below, or returns a null pointer in which case libs/system/src/error_code.cpp maps it to "Unknown error" string:
const char * c_str = std::strerror( ev ); return std::string( c_str ? c_str : "Unknown error" );
The problem with this assumption is that there is no requirement in the C standard that the message string generated by strerror() for an invalid error code starts with "Unknown error" -- see excerpt from C99 below. For example, on HP-UX, strerror() returns an empty string and on Tru64 it returns "Error -1 occurred."
As for the null pointer, strerror() cannot return it -- again, see excerpt from C99 below. X/Open explicitly states that strerror() may signal error by setting errno, but not by returning any particular value:
" Upon successful completion, strerror() returns a pointer to the generated message string. On error errno may be set, but no return value is reserved to indicate an error. "
It does not mean that error_code.cpp should not check for a null pointer as a precaution against non-conformant implementation of strerror().
It's in there because that's what Microsoft does, and I happened to start testing on Windows.
In libs/system/test/error_code_test.cpp, the check for the message string corresponding to error code -1 should either be conditionalized for different platforms or removed.
I think it should be conditional for various platforms. The test was added because of a reported crash, so I really do want to continue to do some testing of the return. But it really does need to be conditional. Thanks, --Beman
participants (2)
-
Beman Dawes
-
Boris Gubenko