* [Qemu-devel] [PATCH v2] qpci_free_pc: sdhci-test and vhost-user-test could free() NULL pointers.
@ 2018-07-02 14:05 Emanuele Giuseppe Esposito
2018-07-02 14:35 ` Paolo Bonzini
0 siblings, 1 reply; 3+ messages in thread
From: Emanuele Giuseppe Esposito @ 2018-07-02 14:05 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Paolo Bonzini, Laurent Vivier, qemu-devel, Marc-André Lureau,
Emanuele Giuseppe Esposito
server->bus in _test_server_free() could be NULL, since TestServer *dest in
test_migrate() was not properly initialized like TestServer *s. Added
init_virtio_dev(dest) and uninit_virtio_dev(dest), so the fields are properly
set and when test_server_free(dest); is called, they can be correctly freed.
Same applies to s->pci.bus, since it is set depending on the architecture.
Problem came out once I modified pci-pc.c and pci-pc.h, modifying QPCIBusPC
by adding another field before QPCIBus bus. Re-running the tests showed
vhost-user-test failing.
Signed-off-by: Emanuele Giuseppe Esposito <esposem@usi.ch>
---
tests/libqos/pci-pc.c | 2 ++
tests/sdhci-test.c | 4 +++-
tests/vhost-user-test.c | 2 ++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index a7803308b7..c126b08ff5 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -152,6 +152,8 @@ QPCIBus *qpci_init_pc(QTestState *qts, QGuestAllocator *alloc)
void qpci_free_pc(QPCIBus *bus)
{
+ g_assert(bus);
+
QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
g_free(s);
diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index 1d825eb010..9b486b93bf 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -209,7 +209,9 @@ static QSDHCI *machine_start(const struct sdhci_t *test)
static void machine_stop(QSDHCI *s)
{
- qpci_free_pc(s->pci.bus);
+ if (s->pci.bus) {
+ qpci_free_pc(s->pci.bus);
+ }
g_free(s->pci.dev);
qtest_quit(global_qtest);
g_free(s);
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 8ff2106d32..a8a02c45cd 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -684,6 +684,7 @@ static void test_migrate(void)
g_free(cmd);
init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
+ init_virtio_dev(dest, 1u << VIRTIO_NET_F_MAC);
wait_for_fds(s);
size = get_log_size(s);
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
@@ -739,6 +740,7 @@ static void test_migrate(void)
read_guest_mem_server(dest);
uninit_virtio_dev(s);
+ uninit_virtio_dev(dest);
g_source_destroy(source);
g_source_unref(source);
--
2.17.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH v2] qpci_free_pc: sdhci-test and vhost-user-test could free() NULL pointers.
2018-07-02 14:05 [Qemu-devel] [PATCH v2] qpci_free_pc: sdhci-test and vhost-user-test could free() NULL pointers Emanuele Giuseppe Esposito
@ 2018-07-02 14:35 ` Paolo Bonzini
2018-07-02 18:04 ` Emanuele
0 siblings, 1 reply; 3+ messages in thread
From: Paolo Bonzini @ 2018-07-02 14:35 UTC (permalink / raw)
To: Emanuele Giuseppe Esposito, Philippe Mathieu-Daudé
Cc: Laurent Vivier, qemu-devel, Marc-André Lureau
On 02/07/2018 16:05, Emanuele Giuseppe Esposito wrote:
> @@ -152,6 +152,8 @@ QPCIBus *qpci_init_pc(QTestState *qts, QGuestAllocator *alloc)
>
> void qpci_free_pc(QPCIBus *bus)
> {
> + g_assert(bus);
> +
> QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
>
> g_free(s);
> diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
> index 1d825eb010..9b486b93bf 100644
> --- a/tests/sdhci-test.c
> +++ b/tests/sdhci-test.c
> @@ -209,7 +209,9 @@ static QSDHCI *machine_start(const struct sdhci_t *test)
>
> static void machine_stop(QSDHCI *s)
> {
> - qpci_free_pc(s->pci.bus);
> + if (s->pci.bus) {
> + qpci_free_pc(s->pci.bus);
> + }
Sorry for chiming in just now.
In general, freeing a NULL pointer is a fine thing to do in C. In your
code you do
QPCIBusPC *ret = g_new0(QPCIBusPC, 1);
qpci_set_pc(ret, qts, alloc);
return &ret->bus;
But now &ret->bus can be inside the pointer. qpci_free_pc must
therefore check for NULL before doing the container_of.
It is debatable whether this change should go in QEMU before your code,
or together with it. There are good arguments for both sides:
- the container_of is assuming that QPCIBus is the first field of the
struct, but that's a strange assumption: container_of usually is used to
go from an interior pointer to an outside struct, and passing NULL to it
is usually wrong
- but, the struct _does_ have QPCIBus as the first field, so we can
assume that if bus == NULL, s will be NULL too. And g_free(NULL) is okay.
I suggest that you add the "if (!bus) { return; }" in your code, in the
same patch that adds the field before QPCIBusPC.
Thanks,
Paolo
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH v2] qpci_free_pc: sdhci-test and vhost-user-test could free() NULL pointers.
2018-07-02 14:35 ` Paolo Bonzini
@ 2018-07-02 18:04 ` Emanuele
0 siblings, 0 replies; 3+ messages in thread
From: Emanuele @ 2018-07-02 18:04 UTC (permalink / raw)
To: Paolo Bonzini, Philippe Mathieu-Daudé
Cc: Laurent Vivier, qemu-devel, Marc-André Lureau
On 07/02/2018 04:35 PM, Paolo Bonzini wrote:
> On 02/07/2018 16:05, Emanuele Giuseppe Esposito wrote:
>> @@ -152,6 +152,8 @@ QPCIBus *qpci_init_pc(QTestState *qts, QGuestAllocator *alloc)
>>
>> void qpci_free_pc(QPCIBus *bus)
>> {
>> + g_assert(bus);
>> +
>> QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
>>
>> g_free(s);
>> diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
>> index 1d825eb010..9b486b93bf 100644
>> --- a/tests/sdhci-test.c
>> +++ b/tests/sdhci-test.c
>> @@ -209,7 +209,9 @@ static QSDHCI *machine_start(const struct sdhci_t *test)
>>
>> static void machine_stop(QSDHCI *s)
>> {
>> - qpci_free_pc(s->pci.bus);
>> + if (s->pci.bus) {
>> + qpci_free_pc(s->pci.bus);
>> + }
> Sorry for chiming in just now.
>
> In general, freeing a NULL pointer is a fine thing to do in C. In your
> code you do
>
> QPCIBusPC *ret = g_new0(QPCIBusPC, 1);
> qpci_set_pc(ret, qts, alloc);
> return &ret->bus;
>
> But now &ret->bus can be inside the pointer. qpci_free_pc must
> therefore check for NULL before doing the container_of.
>
> It is debatable whether this change should go in QEMU before your code,
> or together with it. There are good arguments for both sides:
>
> - the container_of is assuming that QPCIBus is the first field of the
> struct, but that's a strange assumption: container_of usually is used to
> go from an interior pointer to an outside struct, and passing NULL to it
> is usually wrong
>
> - but, the struct _does_ have QPCIBus as the first field, so we can
> assume that if bus == NULL, s will be NULL too. And g_free(NULL) is okay.
>
> I suggest that you add the "if (!bus) { return; }" in your code, in the
> same patch that adds the field before QPCIBusPC.
I see what you mean, I agree this should go in my main patch.
Thank you,
Emanuele
>
> Thanks,
>
> Paolo
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-07-02 18:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-02 14:05 [Qemu-devel] [PATCH v2] qpci_free_pc: sdhci-test and vhost-user-test could free() NULL pointers Emanuele Giuseppe Esposito
2018-07-02 14:35 ` Paolo Bonzini
2018-07-02 18:04 ` Emanuele
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).