1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
From 5be711b84f8aa1c2c1c3751d26adeb9e8fd6dcc6 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 9 Sep 2026 01:25:39 +0100
Subject: [PATCH] shared/gatt-helpers: Ignore invalid characteristic entries
The LG Magic Remote MR24 pads a Read By Type response for the
characteristic declaration with junk entries once its attribute table
is exhausted: handles outside the requested range and not ascending.
Using the last of them as the continuation point makes the next request
return the same junk, and the bogus handles break the database
insertion, so the whole discovery fails and no profile is probed.
Accept only the ascending, in-range prefix of the attribute data list
and treat a truncated list as the end of the discovery.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
src/shared/gatt-helpers.c | 42 ++++++++++++++++++++++++++++++---------
1 file changed, 33 insertions(+), 9 deletions(-)
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -1158,6 +1158,26 @@ struct bt_gatt_request *bt_gatt_discover
return bt_gatt_request_ref(op);
}
+static uint16_t chrc_list_valid_len(const uint8_t *list, uint16_t len,
+ size_t data_length, uint16_t start,
+ uint16_t end)
+{
+ uint16_t handle;
+ uint16_t valid = 0;
+ uint16_t prev = 0;
+
+ while (valid + data_length <= len) {
+ handle = get_le16(list + valid);
+ if (handle < start || handle > end || handle <= prev)
+ break;
+
+ prev = handle;
+ valid += data_length;
+ }
+
+ return valid;
+}
+
static void discover_chrcs_cb(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data)
{
@@ -1166,6 +1186,7 @@ static void discover_chrcs_cb(uint8_t op
uint8_t att_ecode = 0;
size_t data_length;
uint16_t last_handle;
+ uint16_t list_len;
if (opcode == BT_ATT_OP_ERROR_RSP) {
success = false;
@@ -1194,21 +1215,24 @@ static void discover_chrcs_cb(uint8_t op
goto done;
}
- if (!result_append(opcode, pdu + 1, length - 1,
- data_length, op)) {
- success = false;
+ list_len = chrc_list_valid_len(pdu + 1, length - 1, data_length,
+ op->start_handle, op->end_handle);
+ if (!list_len) {
+ success = true;
goto done;
}
- last_handle = get_le16(pdu + length - data_length);
- /*
- * If last handle is lower from previous start handle then it is smth
- * wrong. Let's stop search, otherwise we might enter infinite loop.
- */
- if (last_handle < op->start_handle) {
+ if (!result_append(opcode, pdu + 1, list_len, data_length, op)) {
success = false;
goto done;
}
+ last_handle = get_le16(pdu + 1 + list_len - data_length);
+
+ /* Junk after the valid entries means the remote table has ended */
+ if (list_len < length - 1) {
+ success = true;
+ goto done;
+ }
op->start_handle = last_handle + 1;
|