From: "Daniel P. Berrange" <berrange@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: Eric Blake <eblake@redhat.com>,
qemu-devel@nongnu.org, Ronnie Sahlberg <ronniesahlberg@gmail.com>
Subject: Re: [Qemu-devel] [PATCH] READCONFIG: Allow reading the configuration from a pre-existing filedescriptor
Date: Thu, 26 Jan 2012 10:43:23 +0000 [thread overview]
Message-ID: <20120126104323.GE21211@redhat.com> (raw)
In-Reply-To: <m3pqe629pp.fsf@blackfin.pond.sub.org>
On Thu, Jan 26, 2012 at 08:40:02AM +0100, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
> > On 01/25/2012 03:23 PM, Ronnie Sahlberg wrote:
> >> diff --git a/qemu-config.c b/qemu-config.c
> >> index b030205..c12c5eb 100644
> >> --- a/qemu-config.c
> >> +++ b/qemu-config.c
> >> @@ -770,8 +770,19 @@ out:
> >>
> >> int qemu_read_config_file(const char *filename)
> >> {
> >> - FILE *f = fopen(filename, "r");
> >> - int ret;
> >> + FILE *f;
> >> + int ret, fd;
> >> +
> >> + if (strncmp(filename, "fd:", 3)) {
> >> + f = fopen(filename, "r");
> >> + } else {
> >> + errno = 0;
> >> + fd = strtol(filename + 3, NULL, 10);
> >> + if (errno != 0) {
> >> + return -errno;
> >> + }
> >
> > POSIX says that strtol("", NULL, 10) may return 0 without setting errno
> > (that is, you can't rely on EINVAL in that case). That's another
> > argument for _always_ passing a non-NULL pointer and to see if you
> > accidentally parsed an empty string, since you don't want to have
> > another FILE* competing with stdin. [Libvirt forbids the direct use of
> > strtol and friends, and instead provides wrapper functions that take
> > care of the sanity checking that is not mandated by POSIX; it may be
> > worth introducing a qemu_strtol that does likewise, but that's a
> > different cleanup project with wider scope.]
>
> strtol() should be used like this:
>
> errno = 0;
> val = strtol(str, &end, base);
> if (end == str || || *end != 0 || errno != 0) {
> // conversion failed
> }
>
> Use "*end in follow set" instead of "*end != 0" when the number needn't
> be null terminated.
>
> Plenty of bad examples to be found in qemu, I'm afraid.
The rules for correct strtol() usage are so bizarre that, IMHO, you are
doomed to always have plenty of bad usage in any non-trivial code. As Eric
mentions, after fighting bad usage for a while in libvirt, we eventually
banned all direct usage of strtol() in favour of a saner helper API, which
has really helped our code quality in this area. The most important aspect
of the saner API is the avoidance of overloading the return value to contain
both the error status & and parsed value. We ended up using this (and some
other variants for different sized integers):
/* Like strtol, but produce an "int" result, and check more carefully.
Return 0 upon success; return -1 to indicate failure.
When END_PTR is NULL, the byte after the final valid digit must be NUL.
Otherwise, it's like strtol and lets the caller check any suffix for
validity. This function is careful to return -1 when the string S
represents a number that is not representable as an "int". */
int
virStrToLong_i(char const *s, char **end_ptr, int base, int *result)
{
long int val;
char *p;
int err;
errno = 0;
val = strtol(s, &p, base);
err = (errno || (!end_ptr && *p) || p == s || (int) val != val);
if (end_ptr)
*end_ptr = p;
if (err)
return -1;
*result = val;
return 0;
}
For extra paranoia you could also annotate the header file declaration
with __attribute__((return_check)) to force callers to always check the
error return status. I'd heartily encourage QEMU folks to similarly
ban any use of strtol() (or the similarly badly designed glib equivalent)
in favour of saner helper APIs.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
next prev parent reply other threads:[~2012-01-26 10:43 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-25 22:23 [Qemu-devel] [PATCH 0/0] Allow -readconfig to read from a pre-existing filedescriptor Ronnie Sahlberg
2012-01-25 22:23 ` [Qemu-devel] [PATCH] READCONFIG: Allow reading the configuration " Ronnie Sahlberg
2012-01-25 22:47 ` Eric Blake
2012-01-26 7:40 ` Markus Armbruster
2012-01-26 10:43 ` Daniel P. Berrange [this message]
2012-03-08 19:13 ` Eduardo Habkost
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120126104323.GE21211@redhat.com \
--to=berrange@redhat.com \
--cc=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=ronniesahlberg@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).