[PATCH] printf: fix exit code on conversion failure

Colin Watson cjwatson at ubuntu.com
Thu Jun 18 21:56:56 UTC 2009


On Thu, Jun 18, 2009 at 11:16:19PM +0200, Denys Vlasenko wrote:
> On Thursday 18 June 2009 22:39, Colin Watson wrote:
> > Using stdio, syslog, etc. is not guaranteed to preserve errno. If you
> > want to keep it reliably, you have to save it. Relying on its value
> > across calls to those functions is courting unspecified behaviour.
> 
> > http://www.opengroup.org/onlinepubs/009695399/functions/errno.html
> > states that "The setting of errno after a successful call to a function
> > is unspecified unless the description of that function specifies that
> > errno shall not be modified", and e.g. neither fflush nor syslog
> > specifies this.
> 
> Well, it may change, but it never goes to 0:
> 
> "No function in this volume of IEEE Std 1003.1-2001 shall set errno to 0."

I thought you might say that. :-) I think this is a grey area (a
prohibition against setting to zero on the one hand, but then lots of
"unspecified"s sprinkled around on the other). It's the sort of area
where it would not remotely surprise me if libc implementations
contained the odd lurking bug, precisely because application programmers
are generally inclined to be conservative about relying on errno across
libc calls; the vast majority of applications only check errno right
after an error. (And indeed scattered reports of messages like "an error
occurred: Success" make me think that bugs such as this are not entirely
unheard of.)

Personally, that isn't a sentence in POSIX that I would feel comfortable
relying on in portable code, but it's your project so obviously it's up
to you ...

> > My changes to print_direc should be kept (with the pointer parameter ->
> > return value change you suggested) because print_direc calls printf all
> > over the place and printf is not guaranteed to preserve errno on
> > success.
> 
> So you are saying that successful printf may set errno to nonzero?!

Yes, of course it may.

> POSIX manpage says:
> 
> ERRORS
>        For the conditions under which fprintf()  and  printf()  fail  and  may
>        fail, refer to fputc() or fputwc() .
> 
>        In addition, all forms of fprintf() may fail if:
> 
>        EILSEQ A  wide-character code that does not correspond to a valid char-
>               acter has been detected.
>        EINVAL There are insufficient arguments.
> 
>        The printf() and fprintf() functions may fail if:
>        ENOMEM Insufficient storage space is available.
> 
> Where do you think they mean they store EINVAL etc?
> Obviously, errno.

Er, yes, I know the Unix API rather well, thanks. :-) But POSIX doesn't
permit you to inspect errno unless the function fails; it is entirely
entitled to succeed (i.e. in the case of printf to return a non-negative
value) *and* to set errno to non-zero.

This might quite reasonably happen if the libc implementation called
some other function which failed and set errno, but decided to ignore
that failure for some reason; it is not required to set errno to 0
afterwards to "discard" the error. In fact, the sentence you posted
above explicitly forbids it from doing so!

> There is a reason why I want to simplify the code:
> 
> Your patch:
> 
> # make bloatcheck

Correctness should come first, surely? If we can agree that your code is
guaranteed to be correct, I won't argue further!

Thanks,

-- 
Colin Watson                                       [cjwatson at ubuntu.com]


More information about the busybox mailing list