At Tue, 30 Jun 2009 03:00:17 +0000, David Holland <dholland-tech%netbsd.org@localhost> wrote: Subject: Re: strtonum(3) from OpenBSD? > > On Sat, Jun 27, 2009 at 10:26:49PM -0400, Greg A. Woods wrote: > > > That's the POINT. Calls that succeed may set errno anyway. You have to > > > check that an error occurred before inspecting errno. > > > > Well, with strtol(3) _both_ conditions must hold exactly -- it doesn't > > really matter which test is done first! :-) > > In all cases, not just strtol, both conditions must hold, but it does > matter which test is done first if errno might contain a trap > representation. I meant in the strict ordering of terms in the test expression(s). I.e. all of the following statements are equivalent. I.e. it does not matter which test is done first. It can be either errno first: if (errno == ERANGE && rval == LONG_MAX) err(); if (errno == ERANGE) if (rval == LONG_MAX) err(); etc., or the return value first: if (rval == LONG_MAX && errno == ERANGE) err(); if (rval == LONG_MAX) if (errno == ERANGE) err(); > The problem is that if strtol were allowed to leave trash in errno, > and the number you were converting was exactly LONG_MAX, you might > incorrectly conclude that an overflow occurred. Hmmm... yes, but _only_ if that "trash" value were ERANGE (or the undocumented EINVAL return). If I understand you correctly, you are suggesting that ERANGE may be inadvertently set by some arithmetic operation during the conversion of a string that represents _exactly_ LONG_MAX. In any case that's a separate problem and it will only affect whether you ignore the return value and focus on errno alone, assuming that the strtol() implementation does guarantee it to be zero if there was no overflow. Do you know of any C implementations where signed integer arithmetic overflows will trigger some form of trap or exception handling, _and_ where the exception handler will set errno to ERANGE? OpenVMS can raise SIGFPE on integer overflow, division by zero, etc. it seems but as far as I can tell this will abort the program just as on any POSIX system, and I'm not sure it will happen for ordinary int or even long either. (GCC-4 has the "-ftrapv" option, but it just calls abort() after doing a post-condition check assuming execution on a two's complement system. Apparently someone implemented overflow checking on LCC for those target platforms which do hardware overflow checking for small integer operations, but I don't know what it's effect is.) In any case, IIUC, then such a platform cannot be fully conforming to the standard unless their strtol() implementation internally does clear errno in the case where no overflow has occurred (for a completely successful conversion). If it does not clear errno as it would be required to do then it would indeed limit the conversion range to being one less than LONG_MAX and one more than LONG_MIN and violate standard requirements. (of course strtoul() and friends, i.e. the unsigned variants _could_ be made to be conforming even on a platform which did generate arithmetic exceptions for signed integer operations since of course conforming implementations are required to do unsigned integer operations in exactly the one specified way required by the standard) > However, as has been noted elsewhere by now, it's not allowed to leave > trash, which in turn means that there's no particular reason to test > for LONG_MAX or LONG_MIN; provided you clear errno beforehand it's > sufficient to test errno afterwards. Well, at the moment I think that hold true for NetBSD's implementation, at least for the default compile options. :-) Speaking of the NetBSD implementation, I see it returns an undocumented errno in some cases too, and the documentation is far more convoluted and complex than necessary too, especially in light of knowing that errno must be set to zero on return if there was no overflow during an otherwise error-free conversion. -- Greg A. Woods Planix, Inc. <woods%planix.com@localhost> +1 416 218-0099 http://www.planix.com/
Attachment:
pgpf4EMzELRQA.pgp
Description: PGP signature