Hi Ted, Ted Unangst wrote on Thu, Jul 27, 2017 at 01:08:24AM -0400: > Ingo Schwarze wrote:
>> So i say in all cases above, return -1, set ENOMEM, and it doesn't >> matter much whether anything is printed, except that asprintf(3) >> must of course free(3) any allocated memory before returning and >> set the pointer to NULL. > yeah. the number of bytes returned seems like a mistake in the api > design. there is almost nothing one can do with this information. Here you are going overboard. I just did a quick audit of /bin, /sbin, and /usr/bin/mandoc for uses of *printf(3) returns values. * The overwhelming majority of uses ignores the return value. * Of the rest, the vast majority only checks against -1. * Of the rest, most are mere snprintf(3) truncation checks. * But i did find a dozen real uses of the return value (see below for details). However, you are right that reporting errors is *much* more important than positive return values. * If a malloc error is not reported, but instead the length of what was already printed is returned, programs typically SILENTLY print WRONG CONTENT in a nice, well-aligned format. (But note that our current implementation usually reports a wrong length in these cases - which could be fixed, but is currently broken. So right now, the content is usually wrong *and* misaligned.) * If malloc error is returned even though something was already printed, output may sometimes be misaligned, but the program has a chance to notify the user that the requested information is not (completely) available. Fortunately, most of the cases where the return value is used do not involve floating point format specifiers. But that is beside the point and mere luck. The fact stands that most programs really need to know about failure, and not having access to the number of characters printed during failure is usually of minor concern. Besides, i did find one real bug. As long as printf(%f) reports partial success rather than failure, it requires a somewhat ugly workaround for correct operation. The longer i'm looking at this, the more i think that the answer to kettenis@ good question "Do we want partial success or failure after %f malloc failure?" should be "failure". Also, it is unlikely to cause many real-world surprises because it is also what glibc and NetBSD do. Yours, Ingo AUDIT RESULTS ============= The real bug ------------ 1. mandoc PDF output module, mdoc/term_ps.c The printf(3) return value is used for keeping track of the number of bytes printed to the PDF document, and many of these values are later used to write the PDF table of contents. One of the (frequently called) output statements is: ps_printf(p, "%.3f %.3f moveto\n(", ...) At this point, a short write results in invalid PDF document syntax, so we *really* need a -1 return value, such that we can abort writing the document. Besides, wrong positive return values (which we have now!) result in a corrupt PDF TOC. Other uses of the return value (without floating point) ------------------------------------------------------- 2. ls(1): printf(3): for columnation 3. stty(1): printf(3): for line breaking 4. dhclient(8): snprintf(3): to keep track of the position in the static buffer used for printing DHCP options 5./6. newfs(8) and growfs(8): line breaking in progress output 7. isakmpd(8): vsnprintf(3): used to assemble error messages in a static buffer 8. mandoc(1) eqn(7) parser: asprintf(3): keep track of the length of an allocated string - not relying on it for iteration, only as an upper bound 9. mandoc(1) date formatter: snprintf(3): advance the pointer after printing the number of the day 10. mandoc(1) internal preconv(1) module: snprintf(3): advance in the output buffer after printing an \[uXXXX] escape sequence 11. mandoc(1) input file reader and roff(7) parser: asprintf(3): keep track of the length of allocated strings, mostly as an upper bound, but in one case also to iterate over all the bytes printed