svn commit: r252672 - head/sbin/nvmecontrol
Bruce Evans
brde at optusnet.com.au
Thu Jul 4 01:44:31 UTC 2013
On Thu, 4 Jul 2013, Jim Harris wrote:
> Log:
> Fix printf argument mismatch reported by gcc on i386.
This just substitutes one printf format with another.
> Modified: head/sbin/nvmecontrol/firmware.c
> ==============================================================================
> --- head/sbin/nvmecontrol/firmware.c Thu Jul 4 00:16:43 2013 (r252671)
> +++ head/sbin/nvmecontrol/firmware.c Thu Jul 4 00:26:24 2013 (r252672)
> @@ -82,7 +82,7 @@ read_image_file(char *path, void **buf,
> exit(EX_IOERR);
> }
> if ((*buf = malloc(sb.st_size)) == NULL) {
> - fprintf(stderr, "Unable to malloc %zd bytes.\n",
> + fprintf(stderr, "Unable to malloc %jd bytes.\n",
> sb.st_size);
> close(fd);
> exit(EX_IOERR);
> @@ -95,7 +95,7 @@ read_image_file(char *path, void **buf,
> }
> if (*size != sb.st_size) {
> fprintf(stderr, "Error reading '%s', "
> - "read %zd bytes, requested %zd bytes\n",
> + "read %zd bytes, requested %jd bytes\n",
> path, *size, sb.st_size);
> close(fd);
> exit(EX_IOERR);
st_size has type off_t. The format is for intmax_t. off_t is only
accidentally compatible with off_t (on more arches that with ssize_t,
so compile-time testing takes longer to find the bug).
There are many other type errors visible in this patch:
- st_size has type off_t. It is blindly converted to size_t when it is
passed to malloc(). The message for malloc() failure prints the
non- converted size, but says that the non-converted size was
requested. Careful code would convert to size_t and check that the
result fits. The converted value has the correct type for printing
with %zu. (The old printf format also has a sign error in the format.).
- st_size has type off_t. It is blindly converted to size_t when it is
passed to read(). And although read() takes a size_t arg, ones larger
than SSIZE_MAX give implementation-defined behaviour. On FreeBSD,
the behaviour is to fail. The message for read() failure prints the
non-converted size, but says that the converted size was requested.
Careful code would convert to size_t and check that the result fits in
ssize_t. The converted value has the correct type and range for printing
with %zd.
Many style bugs are visible in this patch:
- the err() family is not used. This gives secondary bugs:
- the program name is not put in the the error messages in another way
- the string for the read() error is not put in the message in another
way. This leads back to a non-style bug: the condition for an error
is not (*size != sb.st_size); that can be for a short read; but using
err() would only be correct if there is actually an error
- warn(); ...; exit(); would have to be used instead of err(), since
close(fd) might clobber errno. But close() before exit() is bogus
unless errors in close() are checked for and handled, and they are
not.
- sysexits.h is used
- EX_IOERR for malloc() failure is just wrong
- the error messages are capitalized
- the first error message is terminated with a "."
- the second error message is obfuscated at the source level using string
concatenation and splitting it across multiple lines
- the second error message has grammar errors (2 comma splices, with the
error largest for the first).
Many programs use similar sloppy error checking for read(). This is only
broken if the file size exceeds SSIZE_MAX or short reads occur. Neither
is likely to occur for image files. But neither is malloc() failure.
Fixing most of these bugs gives:
size_t filesize;
...
if (sb.st_size > SSIZE_MAX)
errx(1, "size of file '%s is too large (%jd bytes)",
(intmax_t)sb.st_size);
filesize = sb.st_size;
if ((*buf = malloc(filesize)) == NULL)
errx(1, "unable to malloc %zd bytes", filesize);
...
/* Repeat above size check if necessary (better do it up-front).
/* XXX still assume no short reads. */
if (*size != filesize)
err(1, "error reading '%s' (read %zd bytes; requested %zd)",
path, *size, filesize);
Bruce
More information about the svn-src-head
mailing list