This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit b18cbe2f19808589b654127eb2b721fe129369a5 Author: Oleksandr Nychyporuk <[email protected]> AuthorDate: Wed Feb 11 21:45:14 2026 +0200 nimble/host: Add UT for large value Read By Type and Find By Type Value Verify that Read By Type and Find By Type Value correctly handle attribute values exceeding the old hardcoded buffer limits. Tests cover full value return, MTU-based truncation, large value matching, value mismatch, and length mismatch. Also raise the 16-byte limit in the Find By Type Value test helper to BLE_ATT_ATTR_MAX_LEN. --- nimble/host/test/src/ble_att_svr_test.c | 137 ++++++++++++++++++++++++++++++++ nimble/host/test/src/ble_hs_test_util.c | 4 +- 2 files changed, 139 insertions(+), 2 deletions(-) diff --git a/nimble/host/test/src/ble_att_svr_test.c b/nimble/host/test/src/ble_att_svr_test.c index c61c7d413..c4adf1359 100644 --- a/nimble/host/test/src/ble_att_svr_test.c +++ b/nimble/host/test/src/ble_att_svr_test.c @@ -2126,6 +2126,142 @@ TEST_CASE_SELF(ble_att_svr_test_unsupported_req) ble_att_svr_test_assert_mbufs_freed(); } +/** + * Tests that Read By Type and Find By Type Value work correctly with attribute + * values larger than the old hardcoded buffer limits (19 and 16 bytes + * respectively). Verifies proper truncation per Core Spec 3.4.4.2: + * max value length = min(ATT_MTU - 4, 253). + */ +TEST_CASE_SELF(ble_att_svr_test_large_value) +{ + static uint8_t large_val[128]; + uint16_t conn_handle; + uint16_t mtu; + uint16_t expected_len; + int rc; + int i; + + /* Fill test buffer with a recognizable pattern. */ + for (i = 0; i < (int)sizeof(large_val); i++) { + large_val[i] = i; + } + + /*** + * Read By Type with large attribute value (MTU = 260). + * max value = min(260 - 4, 253) = 253, but our value is 128 bytes so + * the full value should be returned without truncation. + */ + mtu = 260; + conn_handle = ble_att_svr_test_misc_init(mtu); + + ble_att_svr_test_attr_r_1 = large_val; + ble_att_svr_test_attr_r_1_len = sizeof(large_val); + + /* Register a primary service attribute with the r_1 access callback. */ + ble_att_svr_test_misc_register_uuid( + BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE), + HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_r_1); + + /* Read by type: value is 128 bytes, fits within min(256, 253) = 253. */ + rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 0xffff, + BLE_ATT_UUID_PRIMARY_SERVICE); + TEST_ASSERT(rc == 0); + ble_att_svr_test_misc_verify_tx_read_type_rsp( + ((struct ble_att_svr_test_type_entry[]) { { + .handle = 1, + .value = large_val, + .value_len = sizeof(large_val), + }, { + .handle = 0, + } })); + + /*** + * Read By Type with value truncated by MTU. + * MTU = 64, max value = min(64 - 4, 253) = 60. Value is 128 bytes, + * so response should contain only the first 60 bytes. + */ + mtu = 64; + conn_handle = ble_att_svr_test_misc_init(mtu); + + ble_att_svr_test_attr_r_1 = large_val; + ble_att_svr_test_attr_r_1_len = sizeof(large_val); + + ble_att_svr_test_misc_register_uuid( + BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE), + HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_r_1); + + expected_len = mtu - 4; /* 60 */ + + rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 0xffff, + BLE_ATT_UUID_PRIMARY_SERVICE); + TEST_ASSERT(rc == 0); + ble_att_svr_test_misc_verify_tx_read_type_rsp( + ((struct ble_att_svr_test_type_entry[]) { { + .handle = 1, + .value = large_val, + .value_len = expected_len, + }, { + .handle = 0, + } })); + + /*** + * Find By Type Value with large attribute value (> 16 bytes). + * The request value must match the full attribute value for a hit. + */ + mtu = 260; + conn_handle = ble_att_svr_test_misc_init(mtu); + + ble_att_svr_test_attr_r_1 = large_val; + ble_att_svr_test_attr_r_1_len = sizeof(large_val); + + ble_att_svr_test_misc_register_uuid( + BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE), + HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_r_1); + + /* Search with the correct 128-byte value: should match. */ + rc = ble_hs_test_util_rx_att_find_type_value_req( + conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE, + large_val, sizeof(large_val)); + TEST_ASSERT(rc == 0); + ble_att_svr_test_misc_verify_tx_find_type_value_rsp( + ((struct ble_att_svr_test_type_value_entry[]) { { + .first = 1, + .last = 1, + }, { + .first = 0, + } })); + + /*** + * Find By Type Value with wrong large value: should not match. + */ + { + uint8_t wrong_val[128]; + memcpy(wrong_val, large_val, sizeof(wrong_val)); + wrong_val[64] ^= 0xff; /* Flip one byte in the middle. */ + + rc = ble_hs_test_util_rx_att_find_type_value_req( + conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE, + wrong_val, sizeof(wrong_val)); + TEST_ASSERT(rc != 0); + ble_hs_test_util_verify_tx_err_rsp( + BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 1, + BLE_ATT_ERR_ATTR_NOT_FOUND); + } + + /*** + * Find By Type Value with length mismatch: should not match. + */ + rc = ble_hs_test_util_rx_att_find_type_value_req( + conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE, + large_val, 64); + TEST_ASSERT(rc != 0); + ble_hs_test_util_verify_tx_err_rsp( + BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 1, + BLE_ATT_ERR_ATTR_NOT_FOUND); + + ble_att_svr_test_assert_mbufs_freed(); +} + TEST_SUITE(ble_att_svr_suite) { ble_att_svr_test_mtu(); @@ -2143,4 +2279,5 @@ TEST_SUITE(ble_att_svr_suite) ble_att_svr_test_indicate(); ble_att_svr_test_oom(); ble_att_svr_test_unsupported_req(); + ble_att_svr_test_large_value(); } diff --git a/nimble/host/test/src/ble_hs_test_util.c b/nimble/host/test/src/ble_hs_test_util.c index c38eeecd8..a31a4ef3e 100644 --- a/nimble/host/test/src/ble_hs_test_util.c +++ b/nimble/host/test/src/ble_hs_test_util.c @@ -777,10 +777,10 @@ ble_hs_test_util_rx_att_find_type_value_req(uint16_t conn_handle, uint16_t attr_len) { struct ble_att_find_type_value_req req; - uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + 16]; + uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + BLE_ATT_ATTR_MAX_LEN]; int rc; - TEST_ASSERT(attr_len <= 16); + TEST_ASSERT(attr_len <= BLE_ATT_ATTR_MAX_LEN); req.bavq_start_handle = start_handle; req.bavq_end_handle = end_handle;
