From dbc4eb1d0cfe2c6f23ba6b9e2762ddb6c8dfbe34 Mon Sep 17 00:00:00 2001 From: Olivier Guiter Date: Tue, 9 Oct 2012 14:52:25 +0200 Subject: [PATCH] Add set of tags functions - bugfix: double free bugfix: Fix a possible double free tag: Add near_tag_get_blank function tag: Dereference writing after reading new data tag: Don't check presence while busy --- include/tag.h | 1 + src/adapter.c | 33 ++++++++++++++++++++++++++++ src/near.h | 2 ++ src/tag.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/include/tag.h b/include/tag.h index 54b9763..7a2ca6e 100644 --- a/include/tag.h +++ b/include/tag.h @@ -79,6 +79,7 @@ struct near_tag; struct near_tag *near_tag_get_tag(uint32_t adapter_idx, uint32_t target_idx); void near_tag_set_ro(struct near_tag *tag, near_bool_t readonly); void near_tag_set_blank(struct near_tag *tag, near_bool_t blank); +near_bool_t near_tag_get_blank(struct near_tag *tag); int near_tag_add_data(uint32_t adapter_idx, uint32_t target_idx, uint8_t *data, size_t data_length); int near_tag_add_records(struct near_tag *tag, GList *records, diff --git a/src/adapter.c b/src/adapter.c index e5f9e6a..ca80ed6 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -499,6 +499,39 @@ static void tag_present_cb(uint32_t adapter_idx, uint32_t target_idx, check_presence, adapter); } +void __near_adapter_start_check_presence(uint32_t adapter_idx, + uint32_t target_idx) +{ + struct near_adapter *adapter; + + DBG(""); + + adapter = g_hash_table_lookup(adapter_hash, + GINT_TO_POINTER(adapter_idx)); + if (adapter == NULL) + return; + + adapter->presence_timeout = + g_timeout_add_seconds(CHECK_PRESENCE_PERIOD, + check_presence, adapter); +} + +void __near_adapter_stop_check_presence(uint32_t adapter_idx, + uint32_t target_idx) +{ + struct near_adapter *adapter; + + DBG(""); + + adapter = g_hash_table_lookup(adapter_hash, + GINT_TO_POINTER(adapter_idx)); + if (adapter == NULL) + return; + + if (adapter->presence_timeout > 0) + g_source_remove(adapter->presence_timeout); +} + static const GDBusMethodTable adapter_methods[] = { { GDBUS_METHOD("GetProperties", NULL, GDBUS_ARGS({"properties", "a{sv}"}), diff --git a/src/near.h b/src/near.h index aee34be..3e0ccf6 100644 --- a/src/near.h +++ b/src/near.h @@ -91,6 +91,8 @@ void __near_adapter_tags_changed(uint32_t adapter_idx); void __near_adapter_devices_changed(uint32_t adapter_idx); void __near_adapter_listen(struct near_device_driver *driver); void __near_adapter_list(DBusMessageIter *iter, void *user_data); +void __near_adapter_start_check_presence(uint32_t adapter_idx, uint32_t target_idx); +void __near_adapter_stop_check_presence(uint32_t adapter_idx, uint32_t target_idx); int __near_adapter_init(void); void __near_adapter_cleanup(void); diff --git a/src/tag.c b/src/tag.c index b4aff76..2a46837 100644 --- a/src/tag.c +++ b/src/tag.c @@ -230,6 +230,18 @@ static DBusMessage *set_property(DBusConnection *conn, static void tag_read_cb(uint32_t adapter_idx, uint32_t target_idx, int status) { + struct near_tag *tag; + + tag = near_tag_get_tag(adapter_idx, target_idx); + + if (tag == NULL) + return; + + dbus_message_unref(tag->write_msg); + tag->write_msg = NULL; + + __near_adapter_start_check_presence(adapter_idx, target_idx); + __near_adapter_tags_changed(adapter_idx); } @@ -241,12 +253,14 @@ static void write_cb(uint32_t adapter_idx, uint32_t target_idx, int status) DBG("Write status %d", status); - conn = near_dbus_get_connection(); tag = near_tag_get_tag(adapter_idx, target_idx); - - if (conn == NULL || tag == NULL) + if (tag == NULL) return; + conn = near_dbus_get_connection(); + if (conn == NULL) + goto out; + if (status != 0) { reply = __near_error_failed(tag->write_msg, EINVAL); if (reply != NULL) @@ -255,16 +269,26 @@ static void write_cb(uint32_t adapter_idx, uint32_t target_idx, int status) g_dbus_send_reply(conn, tag->write_msg, DBUS_TYPE_INVALID); } - dbus_message_unref(tag->write_msg); - tag->write_msg = NULL; - near_ndef_records_free(tag->records); tag->n_records = 0; tag->records = NULL; g_free(tag->data); + tag->data = NULL; - if (status == 0) + if (status == 0) { + /* + * If writing succeeded, + * check presence will be restored after reading + */ __near_tag_read(tag, tag_read_cb); + return; + } + +out: + dbus_message_unref(tag->write_msg); + tag->write_msg = NULL; + + __near_adapter_start_check_presence(tag->adapter_idx, tag->target_idx); } static void format_cb(uint32_t adapter_idx, uint32_t target_idx, int status) @@ -754,6 +778,11 @@ void near_tag_set_blank(struct near_tag *tag, near_bool_t blank) tag->blank = blank; } +near_bool_t near_tag_get_blank(struct near_tag *tag) +{ + return tag->blank; +} + uint8_t *near_tag_get_data(struct near_tag *tag, size_t *data_length) { if (data_length == NULL) @@ -908,6 +937,9 @@ int __near_tag_read(struct near_tag *tag, near_tag_io_cb cb) DBG("type 0x%x", tag->type); + /* Stop check presence while reading */ + __near_adapter_stop_check_presence(tag->adapter_idx, tag->target_idx); + for (list = driver_list; list; list = list->next) { struct near_tag_driver *driver = list->data; @@ -936,21 +968,32 @@ int __near_tag_write(struct near_tag *tag, DBG("driver type 0x%x", driver->type); if (driver->type == tag->type) { + /* Stop check presence while writing */ + __near_adapter_stop_check_presence(tag->adapter_idx, + tag->target_idx); + if (tag->blank == TRUE && driver->format != NULL) { DBG("Blank tag detected, formatting"); err = driver->format(tag->adapter_idx, tag->target_idx, format_cb); - if (err < 0) - return err; } else { - return driver->write(tag->adapter_idx, - tag->target_idx, ndef, - cb); + err = driver->write(tag->adapter_idx, + tag->target_idx, ndef, + cb); } + + break; } } - return 0; + if (list == NULL) + err = -EOPNOTSUPP; + + if (err < 0) + __near_adapter_start_check_presence(tag->adapter_idx, + tag->target_idx); + + return err; } int __near_tag_check_presence(struct near_tag *tag, near_tag_io_cb cb) -- 2.7.4