BLE Host - Free mbufs on exec-write-failure This was an mbuf leak. If the device receives an exec-write request, and the attribute callback fails (or the attribute doesn't allow writes at all), the mbufs holding the data intended to be written to that attribute never got freed.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/80f488f7 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/80f488f7 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/80f488f7 Branch: refs/heads/develop Commit: 80f488f75e2147ff90a5646940c51857e473778a Parents: a590ce0 Author: Christopher Collins <[email protected]> Authored: Sat Aug 6 16:04:17 2016 -0700 Committer: Christopher Collins <[email protected]> Committed: Sat Aug 6 16:08:24 2016 -0700 ---------------------------------------------------------------------- net/nimble/host/src/ble_att_svr.c | 6 ++++-- net/nimble/host/src/ble_gattc.c | 8 ++++++++ net/nimble/host/src/test/ble_att_svr_test.c | 14 +++++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/80f488f7/net/nimble/host/src/ble_att_svr.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c index 2e1f158..b3dd2f3 100644 --- a/net/nimble/host/src/ble_att_svr.c +++ b/net/nimble/host/src/ble_att_svr.c @@ -2347,9 +2347,11 @@ ble_att_svr_prep_write(uint16_t conn_handle, *err_handle = attr_handle; } else { rc = ble_att_svr_write(conn_handle, attr, 0, &om, &att_err); + os_mbuf_free_chain(om); + if (rc != 0) { + return att_err; + } } - - os_mbuf_free_chain(om); } return 0; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/80f488f7/net/nimble/host/src/ble_gattc.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c index 84ecff3..67c13d6 100644 --- a/net/nimble/host/src/ble_gattc.c +++ b/net/nimble/host/src/ble_gattc.c @@ -177,6 +177,7 @@ struct ble_gattc_proc { struct { struct ble_gatt_attr attr; uint16_t length; + uint8_t exec_sent:1; ble_gatt_attr_fn *cb; void *cb_arg; } write_long; @@ -186,6 +187,7 @@ struct ble_gattc_proc { uint8_t num_attrs; uint8_t cur_attr; uint16_t length; + uint8_t exec_sent:1; ble_gatt_reliable_attr_fn *cb; void *cb_arg; } write_reliable; @@ -3528,6 +3530,12 @@ static int ble_gattc_write_long_rx_exec(struct ble_gattc_proc *proc, int status) { ble_gattc_dbg_assert_proc_not_inserted(proc); + + /* Ignore the response if we haven't sent the corresponding request yet. */ + if (!proc->write_long.exec_sent) { + return 0; + } + ble_gattc_write_long_cb(proc, status, 0); return BLE_HS_EDONE; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/80f488f7/net/nimble/host/src/test/ble_att_svr_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/test/ble_att_svr_test.c b/net/nimble/host/src/test/ble_att_svr_test.c index e5968d5..09e7bf9 100644 --- a/net/nimble/host/src/test/ble_att_svr_test.c +++ b/net/nimble/host/src/test/ble_att_svr_test.c @@ -2083,12 +2083,16 @@ TEST_CASE(ble_att_svr_test_prep_write) data[i] = i; } - /* Register two attributes. */ + /* Register two writable attributes. */ ble_att_svr_test_misc_register_uuid16(0x1234, HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_w_1); ble_att_svr_test_misc_register_uuid16(0x8989, HA_FLAG_PERM_RW, 2, ble_att_svr_test_misc_attr_fn_w_2); + /* Register a third attribute that is not writable. */ + ble_att_svr_test_misc_register_uuid16(0xabab, BLE_ATT_F_READ, 3, + ble_att_svr_test_misc_attr_fn_r_1); + /*** Empty write succeeds. */ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_CONFIRM, 0, 0); @@ -2132,6 +2136,14 @@ TEST_CASE(ble_att_svr_test_prep_write) BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN, 1); ble_att_svr_test_misc_verify_w_1(NULL, 0); + /*** Failure due to attribute callback. */ + ble_att_svr_test_misc_prep_write(conn_handle, 3, 0, data, 35, 0); + ble_att_svr_test_misc_prep_write(conn_handle, 3, 35, data + 35, 43, 0); + ble_att_svr_test_misc_prep_write(conn_handle, 3, 78, data + 78, 1, 0); + ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_CONFIRM, + BLE_ATT_ERR_WRITE_NOT_PERMITTED, 0); + ble_att_svr_test_misc_verify_w_1(NULL, 0); + /*** Successful two part write. */ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 20, 0); ble_att_svr_test_misc_prep_write(conn_handle, 1, 20, data + 20, 20, 0);
