* [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
@ 2012-07-23 11:33 Laszlo Ersek
2012-07-23 12:34 ` Peter Maydell
2012-07-23 12:46 ` Markus Armbruster
0 siblings, 2 replies; 13+ messages in thread
From: Laszlo Ersek @ 2012-07-23 11:33 UTC (permalink / raw)
To: qemu-devel, lersek
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
hw/qdev.c | 14 +++++++++++++-
vl.c | 7 ++++++-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index af54467..f1e83a4 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -502,6 +502,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
if (dev && dev->parent_bus) {
char *d;
l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
+ if (l >= size) {
+ return l;
+ }
+
d = bus_get_fw_dev_path(dev->parent_bus, dev);
if (d) {
l += snprintf(p + l, size - l, "%s", d);
@@ -509,6 +513,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
} else {
l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
}
+
+ if (l >= size) {
+ return l;
+ }
}
l += snprintf(p + l , size - l, "/");
@@ -520,8 +528,12 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
char path[128];
int l;
- l = qdev_get_fw_dev_path_helper(dev, path, 128);
+ l = qdev_get_fw_dev_path_helper(dev, path, sizeof(path));
+ assert(l > 0);
+ if (l >= sizeof(path)) {
+ return NULL;
+ }
path[l-1] = '\0';
return strdup(path);
diff --git a/vl.c b/vl.c
index 8904db1..78dcc93 100644
--- a/vl.c
+++ b/vl.c
@@ -913,7 +913,12 @@ char *get_boot_devices_list(uint32_t *size)
if (i->dev) {
devpath = qdev_get_fw_dev_path(i->dev);
- assert(devpath);
+ if (devpath == NULL) {
+ fprintf(stderr,
+ "OpenFirmware Device Path too long (boot index %d)\n",
+ i->bootindex);
+ exit(1);
+ }
}
if (i->suffix && devpath) {
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 11:33 [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path Laszlo Ersek
@ 2012-07-23 12:34 ` Peter Maydell
2012-07-23 12:39 ` Peter Maydell
2012-07-23 12:46 ` Markus Armbruster
1 sibling, 1 reply; 13+ messages in thread
From: Peter Maydell @ 2012-07-23 12:34 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: qemu-devel
On 23 July 2012 12:33, Laszlo Ersek <lersek@redhat.com> wrote:
>
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
I think it would be much nicer to just rewrite qdev_get_fw_dev_path
so we weren't trying to fill the path into a fixed string buffer
at all. Here is an entirely untested implementation:
char *qdev_get_fw_dev_path(DeviceState *dev)
{
char *path;
char **strarray;
int depth = 0;
DeviceState *d = dev;
for (d = dev; d && d->parent_bus; d = d->parent_bus->parent) {
depth++;
}
depth++;
strarray = g_new(char*, depth);
for (d = dev; d && d->parent_bus; d = d->parent_bus->parent) {
depth--;
strarray[depth] = bus_get_fw_dev_path(dev->parent_bus, dev);
if (!strarray[depth]) {
strarray[depth] = g_strdup(object_get_typename(OBJECT(dev)));
}
}
strarray[0] = g_strdup("");
path = g_strjoinv("/", strarray);
g_strfreev(strarray);
return path;
}
Bonus extra patch: check that all the implementations of get_fw_dev_path()
are returning a g_malloc'd string rather than a plain malloc'd one
(both this code and the current implementation assume so but at least
the scsi bus implementation doesn't use the glib functions.)
-- PMM
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 12:34 ` Peter Maydell
@ 2012-07-23 12:39 ` Peter Maydell
0 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-07-23 12:39 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: qemu-devel
On 23 July 2012 13:34, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 23 July 2012 12:33, Laszlo Ersek <lersek@redhat.com> wrote:
>>
>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>
> I think it would be much nicer to just rewrite qdev_get_fw_dev_path
> so we weren't trying to fill the path into a fixed string buffer
> at all. Here is an entirely untested implementation:
>
> char *qdev_get_fw_dev_path(DeviceState *dev)
> {
> char *path;
> char **strarray;
> int depth = 0;
> DeviceState *d = dev;
> for (d = dev; d && d->parent_bus; d = d->parent_bus->parent) {
> depth++;
> }
> depth++;
> strarray = g_new(char*, depth);
> for (d = dev; d && d->parent_bus; d = d->parent_bus->parent) {
> depth--;
> strarray[depth] = bus_get_fw_dev_path(dev->parent_bus, dev);
"d" not "dev" here and in the line below, obviously. I said it was
untested :-)
> if (!strarray[depth]) {
> strarray[depth] = g_strdup(object_get_typename(OBJECT(dev)));
> }
> }
> strarray[0] = g_strdup("");
> path = g_strjoinv("/", strarray);
> g_strfreev(strarray);
> return path;
> }
-- PMM
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 11:33 [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path Laszlo Ersek
2012-07-23 12:34 ` Peter Maydell
@ 2012-07-23 12:46 ` Markus Armbruster
2012-07-23 13:08 ` Laszlo Ersek
1 sibling, 1 reply; 13+ messages in thread
From: Markus Armbruster @ 2012-07-23 12:46 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: qemu-devel
Laszlo Ersek <lersek@redhat.com> writes:
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
> ---
> hw/qdev.c | 14 +++++++++++++-
> vl.c | 7 ++++++-
> 2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/hw/qdev.c b/hw/qdev.c
> index af54467..f1e83a4 100644
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
> @@ -502,6 +502,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> if (dev && dev->parent_bus) {
> char *d;
> l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> + if (l >= size) {
> + return l;
> + }
> +
> d = bus_get_fw_dev_path(dev->parent_bus, dev);
> if (d) {
> l += snprintf(p + l, size - l, "%s", d);
> @@ -509,6 +513,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> } else {
> l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
> }
> +
> + if (l >= size) {
> + return l;
> + }
> }
> l += snprintf(p + l , size - l, "/");
>
If the return value is less than the size argument, it's the length of
the string written into p[]. Else, it means p[] has insufficient
space.
> @@ -520,8 +528,12 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
> char path[128];
> int l;
>
> - l = qdev_get_fw_dev_path_helper(dev, path, 128);
> + l = qdev_get_fw_dev_path_helper(dev, path, sizeof(path));
>
> + assert(l > 0);
> + if (l >= sizeof(path)) {
> + return NULL;
> + }
Failure mode could be avoided with the common technique: make
qdev_get_fw_dev_path_helper() return the true length. If it fit into
path[], return strdup(path). Else, allocate a suitable buffer and try
again.
What do you think?
> path[l-1] = '\0';
>
> return strdup(path);
> diff --git a/vl.c b/vl.c
> index 8904db1..78dcc93 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -913,7 +913,12 @@ char *get_boot_devices_list(uint32_t *size)
>
> if (i->dev) {
> devpath = qdev_get_fw_dev_path(i->dev);
> - assert(devpath);
> + if (devpath == NULL) {
> + fprintf(stderr,
> + "OpenFirmware Device Path too long (boot index %d)\n",
> + i->bootindex);
> + exit(1);
> + }
> }
>
> if (i->suffix && devpath) {
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 12:46 ` Markus Armbruster
@ 2012-07-23 13:08 ` Laszlo Ersek
2012-07-23 15:01 ` Markus Armbruster
0 siblings, 1 reply; 13+ messages in thread
From: Laszlo Ersek @ 2012-07-23 13:08 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
On 07/23/12 14:46, Markus Armbruster wrote:
> Laszlo Ersek <lersek@redhat.com> writes:
>
>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>> ---
>> hw/qdev.c | 14 +++++++++++++-
>> vl.c | 7 ++++++-
>> 2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/qdev.c b/hw/qdev.c
>> index af54467..f1e83a4 100644
>> --- a/hw/qdev.c
>> +++ b/hw/qdev.c
>> @@ -502,6 +502,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>> if (dev && dev->parent_bus) {
>> char *d;
>> l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
>> + if (l >= size) {
>> + return l;
>> + }
>> +
>> d = bus_get_fw_dev_path(dev->parent_bus, dev);
>> if (d) {
>> l += snprintf(p + l, size - l, "%s", d);
>> @@ -509,6 +513,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>> } else {
>> l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
>> }
>> +
>> + if (l >= size) {
>> + return l;
>> + }
>> }
>> l += snprintf(p + l , size - l, "/");
>>
>
> If the return value is less than the size argument, it's the length of
> the string written into p[]. Else, it means p[] has insufficient
> space.
Yes. (snprintf() returns the number of bytes it would store, excluding
the terminating NUL, had there been enough room.
<http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04>)
Did I make a mistake?
Supposing snprintf() encounters no error, it returns a positive value P
in the above.
P = snprintf(..., size - l0, ...)
l1 = l0 + P;
l1 >= size
<-> l0 + P >= size
<-> P >= size - l0
The return value of qdev_get_fw_dev_path_helper() comes from another
invocation of itself, or from the trailing snprintf(), so it behaves
like snprintf.
Or what do you have in mind?
>
>> @@ -520,8 +528,12 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
>> char path[128];
>> int l;
>>
>> - l = qdev_get_fw_dev_path_helper(dev, path, 128);
>> + l = qdev_get_fw_dev_path_helper(dev, path, sizeof(path));
>>
>> + assert(l > 0);
>> + if (l >= sizeof(path)) {
>> + return NULL;
>> + }
>
> Failure mode could be avoided with the common technique: make
> qdev_get_fw_dev_path_helper() return the true length. If it fit into
> path[], return strdup(path). Else, allocate a suitable buffer and try
> again.
>
> What do you think?
You're right of course, but I didn't have (or wanted to spend) the time
to change the code that much (and to test it...), especially because it
would have been fixed already if it had caused actual problems. I think
the patch could work as a "last resort", small improvement, but I don't
mind if someone posts a better fix :)
Laszlo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 13:08 ` Laszlo Ersek
@ 2012-07-23 15:01 ` Markus Armbruster
2012-07-23 15:29 ` Laszlo Ersek
0 siblings, 1 reply; 13+ messages in thread
From: Markus Armbruster @ 2012-07-23 15:01 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: qemu-devel
Laszlo Ersek <lersek@redhat.com> writes:
> On 07/23/12 14:46, Markus Armbruster wrote:
>> Laszlo Ersek <lersek@redhat.com> writes:
>>
>>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>>> ---
>>> hw/qdev.c | 14 +++++++++++++-
>>> vl.c | 7 ++++++-
>>> 2 files changed, 19 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/qdev.c b/hw/qdev.c
>>> index af54467..f1e83a4 100644
>>> --- a/hw/qdev.c
>>> +++ b/hw/qdev.c
>>> @@ -502,6 +502,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>>> if (dev && dev->parent_bus) {
>>> char *d;
>>> l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
>>> + if (l >= size) {
>>> + return l;
>>> + }
>>> +
>>> d = bus_get_fw_dev_path(dev->parent_bus, dev);
>>> if (d) {
>>> l += snprintf(p + l, size - l, "%s", d);
>>> @@ -509,6 +513,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>>> } else {
>>> l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
>>> }
>>> +
>>> + if (l >= size) {
>>> + return l;
>>> + }
>>> }
>>> l += snprintf(p + l , size - l, "/");
>>>
>>
>> If the return value is less than the size argument, it's the length of
>> the string written into p[]. Else, it means p[] has insufficient
>> space.
>
> Yes. (snprintf() returns the number of bytes it would store, excluding
> the terminating NUL, had there been enough room.
> <http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04>)
>
> Did I make a mistake?
>
> Supposing snprintf() encounters no error, it returns a positive value P
> in the above.
>
> P = snprintf(..., size - l0, ...)
> l1 = l0 + P;
>
> l1 >= size
> <-> l0 + P >= size
> <-> P >= size - l0
>
>
> The return value of qdev_get_fw_dev_path_helper() comes from another
> invocation of itself, or from the trailing snprintf(), so it behaves
> like snprintf.
>
> Or what do you have in mind?
If I read your code correctly, qdev_get_fw_dev_path_helper() bails out
after the first snprintf() that goes beyond the buffer size. When that
happens before the job's done, the return value is less than the length
of the full path.
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
{
int l = 0;
if (dev && dev->parent_bus) {
char *d;
l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
+ if (l >= size) {
+ return l; <--- bail out early
+ }
+
if (dev->parent_bus->info->get_fw_dev_path) {
d = dev->parent_bus->info->get_fw_dev_path(dev);
l += snprintf(p + l, size - l, "%s", d);
qemu_free(d);
} else {
l += snprintf(p + l, size - l, "%s", dev->info->name);
}
+
+ if (l >= size) {
+ return l; <--- bail out early
+ }
}
l += snprintf(p + l , size - l, "/");
return l;
}
>>> @@ -520,8 +528,12 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
>>> char path[128];
>>> int l;
>>>
>>> - l = qdev_get_fw_dev_path_helper(dev, path, 128);
>>> + l = qdev_get_fw_dev_path_helper(dev, path, sizeof(path));
>>>
>>> + assert(l > 0);
>>> + if (l >= sizeof(path)) {
>>> + return NULL;
>>> + }
>>
>> Failure mode could be avoided with the common technique: make
>> qdev_get_fw_dev_path_helper() return the true length. If it fit into
>> path[], return strdup(path). Else, allocate a suitable buffer and try
>> again.
>>
>> What do you think?
>
> You're right of course, but I didn't have (or wanted to spend) the time
> to change the code that much (and to test it...), especially because it
> would have been fixed already if it had caused actual problems. I think
> the patch could work as a "last resort", small improvement, but I don't
> mind if someone posts a better fix :)
Only marginally harder than handling the failure :)
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 15:01 ` Markus Armbruster
@ 2012-07-23 15:29 ` Laszlo Ersek
2012-07-23 15:42 ` Markus Armbruster
0 siblings, 1 reply; 13+ messages in thread
From: Laszlo Ersek @ 2012-07-23 15:29 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-devel
On 07/23/12 17:01, Markus Armbruster wrote:
> Laszlo Ersek <lersek@redhat.com> writes:
>
>> On 07/23/12 14:46, Markus Armbruster wrote:
>>> Laszlo Ersek <lersek@redhat.com> writes:
>>>
>>>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>>>> ---
>>>> hw/qdev.c | 14 +++++++++++++-
>>>> vl.c | 7 ++++++-
>>>> 2 files changed, 19 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/qdev.c b/hw/qdev.c
>>>> index af54467..f1e83a4 100644
>>>> --- a/hw/qdev.c
>>>> +++ b/hw/qdev.c
>>>> @@ -502,6 +502,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>>>> if (dev && dev->parent_bus) {
>>>> char *d;
>>>> l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
>>>> + if (l >= size) {
>>>> + return l;
>>>> + }
>>>> +
>>>> d = bus_get_fw_dev_path(dev->parent_bus, dev);
>>>> if (d) {
>>>> l += snprintf(p + l, size - l, "%s", d);
>>>> @@ -509,6 +513,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>>>> } else {
>>>> l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
>>>> }
>>>> +
>>>> + if (l >= size) {
>>>> + return l;
>>>> + }
>>>> }
>>>> l += snprintf(p + l , size - l, "/");
>>>>
>>>
>>> If the return value is less than the size argument, it's the length of
>>> the string written into p[]. Else, it means p[] has insufficient
>>> space.
>>
>> Yes. (snprintf() returns the number of bytes it would store, excluding
>> the terminating NUL, had there been enough room.
>> <http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04>)
>>
>> Did I make a mistake?
>>
>> Supposing snprintf() encounters no error, it returns a positive value P
>> in the above.
>>
>> P = snprintf(..., size - l0, ...)
>> l1 = l0 + P;
>>
>> l1 >= size
>> <-> l0 + P >= size
>> <-> P >= size - l0
>>
>>
>> The return value of qdev_get_fw_dev_path_helper() comes from another
>> invocation of itself, or from the trailing snprintf(), so it behaves
>> like snprintf.
>>
>> Or what do you have in mind?
>
> If I read your code correctly, qdev_get_fw_dev_path_helper() bails out
> after the first snprintf() that goes beyond the buffer size. When that
> happens before the job's done, the return value is less than the length
> of the full path.
Yes, but still greater than what would fit in the buffer. Is it a problem?
... Oh, did you mean the first comment in connection with the second?
Ie. we should continue to format (just for length counting's sake) and
then retry? IOW the early return isn't problematic in itself, but it
doesn't support the reallocation?
Thanks,
Laszlo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path
2012-07-23 15:29 ` Laszlo Ersek
@ 2012-07-23 15:42 ` Markus Armbruster
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 0/2] assorted device path formatting cleanups Laszlo Ersek
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Markus Armbruster @ 2012-07-23 15:42 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: qemu-devel
Laszlo Ersek <lersek@redhat.com> writes:
> On 07/23/12 17:01, Markus Armbruster wrote:
>> Laszlo Ersek <lersek@redhat.com> writes:
>>
>>> On 07/23/12 14:46, Markus Armbruster wrote:
>>>> Laszlo Ersek <lersek@redhat.com> writes:
>>>>
>>>>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>>>>> ---
>>>>> hw/qdev.c | 14 +++++++++++++-
>>>>> vl.c | 7 ++++++-
>>>>> 2 files changed, 19 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/hw/qdev.c b/hw/qdev.c
>>>>> index af54467..f1e83a4 100644
>>>>> --- a/hw/qdev.c
>>>>> +++ b/hw/qdev.c
>>>>> @@ -502,6 +502,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>>>>> if (dev && dev->parent_bus) {
>>>>> char *d;
>>>>> l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
>>>>> + if (l >= size) {
>>>>> + return l;
>>>>> + }
>>>>> +
>>>>> d = bus_get_fw_dev_path(dev->parent_bus, dev);
>>>>> if (d) {
>>>>> l += snprintf(p + l, size - l, "%s", d);
>>>>> @@ -509,6 +513,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
>>>>> } else {
>>>>> l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
>>>>> }
>>>>> +
>>>>> + if (l >= size) {
>>>>> + return l;
>>>>> + }
>>>>> }
>>>>> l += snprintf(p + l , size - l, "/");
>>>>>
>>>>
>>>> If the return value is less than the size argument, it's the length of
>>>> the string written into p[]. Else, it means p[] has insufficient
>>>> space.
>>>
>>> Yes. (snprintf() returns the number of bytes it would store, excluding
>>> the terminating NUL, had there been enough room.
>>> <http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04>)
>>>
>>> Did I make a mistake?
>>>
>>> Supposing snprintf() encounters no error, it returns a positive value P
>>> in the above.
>>>
>>> P = snprintf(..., size - l0, ...)
>>> l1 = l0 + P;
>>>
>>> l1 >= size
>>> <-> l0 + P >= size
>>> <-> P >= size - l0
>>>
>>>
>>> The return value of qdev_get_fw_dev_path_helper() comes from another
>>> invocation of itself, or from the trailing snprintf(), so it behaves
>>> like snprintf.
>>>
>>> Or what do you have in mind?
>>
>> If I read your code correctly, qdev_get_fw_dev_path_helper() bails out
>> after the first snprintf() that goes beyond the buffer size. When that
>> happens before the job's done, the return value is less than the length
>> of the full path.
>
> Yes, but still greater than what would fit in the buffer. Is it a problem?
>
> ... Oh, did you mean the first comment in connection with the second?
> Ie. we should continue to format (just for length counting's sake) and
> then retry? IOW the early return isn't problematic in itself, but it
> doesn't support the reallocation?
Yes.
Your code lets the caller detect "need more space" reliably. How much
more it can only guess, and need to be prepared for the retry to fail
again. If we return the required size, like snprintf() does, the caller
knows, and the retry will succeed.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 0/2] assorted device path formatting cleanups
2012-07-23 15:42 ` Markus Armbruster
@ 2012-07-25 0:19 ` Laszlo Ersek
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage Laszlo Ersek
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 2/2] get_fw_dev_path() impls should allocate memory with glib functions Laszlo Ersek
2 siblings, 0 replies; 13+ messages in thread
From: Laszlo Ersek @ 2012-07-25 0:19 UTC (permalink / raw)
To: qemu-devel, armbru, peter.maydell, lersek
As long as "two" qualifies as "assorted".
v1->v2:
- abandon original "idea", allocate sufficient memory for OFW device path
formatting [Markus]
- all bus formatters should rely on glib for dynamic allocation [Peter]
Tested with an OVMF debug patch that grabs and logs the "bootorder" fw_cfg
file:
/pci@i0cf8/ide@1,1/drive@0/disk@0
/pci@i0cf8/ide@1,1/drive@1/disk@0
/pci@i0cf8/isa@1/fdc@03f0/floppy@0
/pci@i0cf8/ethernet@3/ethernet-phy@0
Laszlo Ersek (2):
accomodate OpenFirmware device paths in sufficient storage
get_fw_dev_path() impls should allocate memory with glib functions
hw/ide/qdev.c | 2 +-
hw/isa-bus.c | 2 +-
hw/pci.c | 2 +-
hw/qdev.c | 54 +++++++++++++++++++++++++++++++++++++++++++-----------
hw/scsi-bus.c | 2 +-
hw/sysbus.c | 2 +-
6 files changed, 48 insertions(+), 16 deletions(-)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage
2012-07-23 15:42 ` Markus Armbruster
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 0/2] assorted device path formatting cleanups Laszlo Ersek
@ 2012-07-25 0:19 ` Laszlo Ersek
2012-07-25 7:34 ` Peter Maydell
2012-07-25 8:11 ` Markus Armbruster
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 2/2] get_fw_dev_path() impls should allocate memory with glib functions Laszlo Ersek
2 siblings, 2 replies; 13+ messages in thread
From: Laszlo Ersek @ 2012-07-25 0:19 UTC (permalink / raw)
To: qemu-devel, armbru, peter.maydell, lersek
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
hw/qdev.c | 54 +++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index af54467..59cc0c2 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -25,6 +25,8 @@
inherit from a particular bus (e.g. PCI or I2C) rather than
this API directly. */
+#include <stdarg.h>
+
#include "net.h"
#include "qdev.h"
#include "sysemu.h"
@@ -495,36 +497,66 @@ static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
return NULL;
}
+static int snprintf_helper(char *p, int size, int len, const char *format, ...)
+{
+ char *target;
+ int free_sz;
+ va_list args;
+ int ret;
+
+ if (len < size) {
+ target = p + len;
+ free_sz = size - len;
+ }
+ else {
+ target = NULL;
+ free_sz = 0;
+ }
+
+ va_start(args, format);
+ ret = vsnprintf(target, free_sz, format, args);
+ va_end(args);
+
+ assert(ret >= 0);
+ return ret;
+}
+
+
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
{
- int l = 0;
+ int len = 0;
if (dev && dev->parent_bus) {
char *d;
- l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
+ len = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
d = bus_get_fw_dev_path(dev->parent_bus, dev);
if (d) {
- l += snprintf(p + l, size - l, "%s", d);
+ len += snprintf_helper(p, size, len, "%s", d);
g_free(d);
} else {
- l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
+ len += snprintf_helper(p, size, len, "%s",
+ object_get_typename(OBJECT(dev)));
}
}
- l += snprintf(p + l , size - l, "/");
+ len += snprintf_helper(p, size, len, "/");
- return l;
+ return len;
}
char* qdev_get_fw_dev_path(DeviceState *dev)
{
- char path[128];
- int l;
+ int len, len2;
+ char *path;
- l = qdev_get_fw_dev_path_helper(dev, path, 128);
+ len = qdev_get_fw_dev_path_helper(dev, NULL, 0);
+ path = g_malloc(len + 1);
- path[l-1] = '\0';
+ len2 = qdev_get_fw_dev_path_helper(dev, path, len + 1);
+ assert(len2 == len);
- return strdup(path);
+ assert(len > 0);
+ path[len - 1] = '\0';
+ return path;
}
char *qdev_get_dev_path(DeviceState *dev)
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] get_fw_dev_path() impls should allocate memory with glib functions
2012-07-23 15:42 ` Markus Armbruster
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 0/2] assorted device path formatting cleanups Laszlo Ersek
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage Laszlo Ersek
@ 2012-07-25 0:19 ` Laszlo Ersek
2 siblings, 0 replies; 13+ messages in thread
From: Laszlo Ersek @ 2012-07-25 0:19 UTC (permalink / raw)
To: qemu-devel, armbru, peter.maydell, lersek
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
hw/ide/qdev.c | 2 +-
hw/isa-bus.c | 2 +-
hw/pci.c | 2 +-
hw/scsi-bus.c | 2 +-
hw/sysbus.c | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 22e58df..4f15070 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -60,7 +60,7 @@ static char *idebus_get_fw_dev_path(DeviceState *dev)
snprintf(path, sizeof(path), "%s@%d", qdev_fw_name(dev),
((IDEBus*)dev->parent_bus)->bus_id);
- return strdup(path);
+ return g_strdup(path);
}
static int ide_qdev_init(DeviceState *qdev)
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index f9b2373..47c93d3 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -236,7 +236,7 @@ static char *isabus_get_fw_dev_path(DeviceState *dev)
snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
}
- return strdup(path);
+ return g_strdup(path);
}
MemoryRegion *isa_address_space(ISADevice *dev)
diff --git a/hw/pci.c b/hw/pci.c
index 99a4304..ef8996d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1920,7 +1920,7 @@ static char *pcibus_get_fw_dev_path(DeviceState *dev)
PCI_SLOT(d->devfn));
if (PCI_FUNC(d->devfn))
snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn));
- return strdup(path);
+ return g_strdup(path);
}
static char *pcibus_get_dev_path(DeviceState *dev)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index dc74063..4544d0b 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1547,7 +1547,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel,
qdev_fw_name(dev), d->id, d->lun);
- return strdup(path);
+ return g_strdup(path);
}
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 9d8b1ea..c173840 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -211,7 +211,7 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
}
- return strdup(path);
+ return g_strdup(path);
}
void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr,
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage Laszlo Ersek
@ 2012-07-25 7:34 ` Peter Maydell
2012-07-25 8:11 ` Markus Armbruster
1 sibling, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-07-25 7:34 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: qemu-devel, armbru
On 25 July 2012 01:19, Laszlo Ersek <lersek@redhat.com> wrote:
>
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
> ---
> hw/qdev.c | 54 +++++++++++++++++++++++++++++++++++++++++++-----------
> 1 files changed, 43 insertions(+), 11 deletions(-)
Yuck. Just redo qdev_get_fw_dev_path along the lines I
suggested please. This is way too complicated.
-- PMM
> diff --git a/hw/qdev.c b/hw/qdev.c
> index af54467..59cc0c2 100644
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
> @@ -25,6 +25,8 @@
> inherit from a particular bus (e.g. PCI or I2C) rather than
> this API directly. */
>
> +#include <stdarg.h>
> +
> #include "net.h"
> #include "qdev.h"
> #include "sysemu.h"
> @@ -495,36 +497,66 @@ static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
> return NULL;
> }
>
> +static int snprintf_helper(char *p, int size, int len, const char *format, ...)
> +{
> + char *target;
> + int free_sz;
> + va_list args;
> + int ret;
> +
> + if (len < size) {
> + target = p + len;
> + free_sz = size - len;
> + }
> + else {
> + target = NULL;
> + free_sz = 0;
> + }
> +
> + va_start(args, format);
> + ret = vsnprintf(target, free_sz, format, args);
> + va_end(args);
> +
> + assert(ret >= 0);
> + return ret;
> +}
> +
> +
> static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
> {
> - int l = 0;
> + int len = 0;
>
> if (dev && dev->parent_bus) {
> char *d;
> - l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> + len = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
> d = bus_get_fw_dev_path(dev->parent_bus, dev);
> if (d) {
> - l += snprintf(p + l, size - l, "%s", d);
> + len += snprintf_helper(p, size, len, "%s", d);
> g_free(d);
> } else {
> - l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
> + len += snprintf_helper(p, size, len, "%s",
> + object_get_typename(OBJECT(dev)));
> }
> }
> - l += snprintf(p + l , size - l, "/");
> + len += snprintf_helper(p, size, len, "/");
>
> - return l;
> + return len;
> }
>
> char* qdev_get_fw_dev_path(DeviceState *dev)
> {
> - char path[128];
> - int l;
> + int len, len2;
> + char *path;
>
> - l = qdev_get_fw_dev_path_helper(dev, path, 128);
> + len = qdev_get_fw_dev_path_helper(dev, NULL, 0);
> + path = g_malloc(len + 1);
>
> - path[l-1] = '\0';
> + len2 = qdev_get_fw_dev_path_helper(dev, path, len + 1);
> + assert(len2 == len);
>
> - return strdup(path);
> + assert(len > 0);
> + path[len - 1] = '\0';
> + return path;
> }
>
> char *qdev_get_dev_path(DeviceState *dev)
> --
> 1.7.1
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage Laszlo Ersek
2012-07-25 7:34 ` Peter Maydell
@ 2012-07-25 8:11 ` Markus Armbruster
1 sibling, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2012-07-25 8:11 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: peter.maydell, qemu-devel
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-07-25 8:11 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-23 11:33 [Qemu-devel] [PATCH] check for available room when formatting OpenFirmware device path Laszlo Ersek
2012-07-23 12:34 ` Peter Maydell
2012-07-23 12:39 ` Peter Maydell
2012-07-23 12:46 ` Markus Armbruster
2012-07-23 13:08 ` Laszlo Ersek
2012-07-23 15:01 ` Markus Armbruster
2012-07-23 15:29 ` Laszlo Ersek
2012-07-23 15:42 ` Markus Armbruster
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 0/2] assorted device path formatting cleanups Laszlo Ersek
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 1/2] accomodate OpenFirmware device paths in sufficient storage Laszlo Ersek
2012-07-25 7:34 ` Peter Maydell
2012-07-25 8:11 ` Markus Armbruster
2012-07-25 0:19 ` [Qemu-devel] [PATCH v2 2/2] get_fw_dev_path() impls should allocate memory with glib functions Laszlo Ersek
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).