Path: utzoo!attcan!uunet!seismo!sundc!pitstop!sun!quintus!ok From: ok@quintus.uucp (Richard A. O'Keefe) Newsgroups: comp.lang.c Subject: Re: sprintf(3s) query Message-ID: <887@quintus.UUCP> Date: 19 Dec 88 05:33:42 GMT References: <1102@entropy.ms.washington.edu> <8131@ihlpl.ATT.COM> <865@quintus.UUCP> <9181@smoke.BRL.MIL> <878@quintus.UUCP> <9205@smoke.BRL.MIL> Sender: news@quintus.UUCP Reply-To: ok@quintus.UUCP (Richard A. O'Keefe) Organization: Quintus Computer Systems, Inc. Lines: 58 In article <9205@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) writes: >In article <878@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >-In article <9181@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) writes: >->I hope by now all the BSD code that depends on the value of >->sprintf() being anything in particular has been changed to use >->some other method. Usually, something like >-> buf[0] = '\0'; >-> (void)sprintf(buf, fmt, args); >-> if (buf[0] == '\0') >-> /* error */ >->is sufficient (it works with both definitions of sprintf()). >-Except that it doesn't work with either. Consider >- sprintf("%.*s", len, ptr); >-when len happens to be 0. >Again, I said "Usually, ..." which implies "not always". The vast >majority of sprintf() usage can correctly be changed to follow my >suggestion. I note that you offered no alternative. I offered no alternative because I wanted to keep the message short. According to the ULTRIX documentation, sprintf(3s) returns EOF to indicate an error. The alternative is thus #ifdef BSD #define BadSprintf (char*)(EOF) == sprintf #else /*SYS5*/ #define BadSprintf EOF == sprintf #endif and then do if (BadSprintf(buf, fmt, args)) /* error */; >-By the way, what _are_ the output error >-conditions that *printf() can detect other than by crashing? >There are several possible errors other than I/O errors. Think >hard enough and you should be able to imagine at least one. I can _imagine_ a lot of possible errors, no problem. The trouble is that all the ones I've tested either dump core or are quietly accepted. For example, "?" is not a defined conversion code, but sprintf accepts "%.*?" as a format conversion, and writes '?'. Then there are negative field widths. One might expect sprintf(buf, "%.*d", -9999, 44) to either report an error or else act like "%-9999d", but it does neither. It would be reasonable for sprintf(buf, "(%s)", (char*)NULL) to report an error, but on my system it writes "((null))". Another obvious error is sprintf(buffer, "%4294967299d", 1), but it is not reported. And so it goes. I think the following three points are uncontroversial: (1) The (4.2BSD, S5R2, S5R3, Ultrix, SunOS) manual pages for printf(3s) do not say what any of the conditions which can cause an error return are. (I haven't seen the 4.3BSD manual page.) (2) There are a lot of errors which sprintf() either converts quietly to something plausible or dumps core with, not least buffer overflow. (3) A portable program cannot rely on sprintf() catching any error at all, and thus had better do its own argument validation in any case. It would be interesting to hear from someone who has UNIX sources what the reported errors are.