linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v5 02/21] client/gatt: Fix setting descriptor value from scripts
Date: Mon, 28 Sep 2026 13:32:21 -0400	[thread overview]
Message-ID: <20260928173243.1073509-3-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260928173243.1073509-1-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

gatt.register-descriptor completed the command right after prompting
for the value, so when run from a script the line with the value was
executed as a command instead of being passed to the prompt, causing
the descriptor to be unregistered.

Complete the command once the value is set, as done for
characteristics, and parse a copy of the value so the input line is
not truncated by strsep while still in use by the shell.

As invalid values can now come from scripts, fix handling them: the
attribute is no longer used once unregistered, which frees it, nor kept
in the list of its parent, and the command fails. Also stop counting
the empty entries between the values, which left bytes uninitialized,
and reject negative values.

Assisted-by: OpenCode:claude-opus-5.5
---
 client/gatt.c | 39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/client/gatt.c b/client/gatt.c
index 6dc80e2a31cd..a85f6003d9b8 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -700,13 +700,21 @@ void gatt_read_local_attribute(char *data, int argc, char *argv[])
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
-static uint8_t *str2bytearray(char *arg, size_t *val_len)
+static uint8_t *str2bytearray(const char *arg, size_t *val_len)
 {
 	uint8_t value[MAX_ATTR_VAL_LEN];
-	char *entry;
+	char *str, *next, *entry;
 	unsigned int i;
 
-	for (i = 0; (entry = strsep(&arg, " \t")) != NULL; i++) {
+	/* Parse a copy as strsep modifies the string, which may still be
+	 * in use by the caller, e.g. the shell printing the input line.
+	 */
+	str = next = strdup(arg);
+	if (!str)
+		return NULL;
+
+	/* Only count the values, not the empty entries in between */
+	for (i = 0; (entry = strsep(&next, " \t")) != NULL;) {
 		long val;
 		char *endptr = NULL;
 
@@ -715,18 +723,22 @@ static uint8_t *str2bytearray(char *arg, size_t *val_len)
 
 		if (i >= G_N_ELEMENTS(value)) {
 			bt_shell_printf("Too much data\n");
+			free(str);
 			return NULL;
 		}
 
 		val = strtol(entry, &endptr, 0);
-		if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
+		if (!endptr || *endptr != '\0' || val < 0 || val > UINT8_MAX) {
 			bt_shell_printf("Invalid value at index %d\n", i);
+			free(str);
 			return NULL;
 		}
 
-		value[i] = val;
+		value[i++] = val;
 	}
 
+	free(str);
+
 	*val_len = i;
 
 	return util_memdup(value, i);
@@ -2788,11 +2800,14 @@ static void chrc_set_value(const char *input, void *user_data)
 
 	g_free(chrc->value);
 
-	chrc->value = str2bytearray((char *) input, &chrc->value_len);
+	chrc->value = str2bytearray(input, &chrc->value_len);
 
 	if (!chrc->value) {
-		print_chrc(chrc, COLORED_DEL);
+		/* Unregistering frees chrc, so it is removed first */
+		chrc->service->chrcs = g_list_remove(chrc->service->chrcs,
+									chrc);
 		chrc_unregister(chrc);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
 	chrc->max_val_len = chrc->value_len;
@@ -3078,14 +3093,18 @@ static void desc_set_value(const char *input, void *user_data)
 
 	g_free(desc->value);
 
-	desc->value = str2bytearray((char *) input, &desc->value_len);
+	desc->value = str2bytearray(input, &desc->value_len);
 
 	if (!desc->value) {
-		print_desc(desc, COLORED_DEL);
+		/* Unregistering frees desc, so it is removed first */
+		desc->chrc->descs = g_list_remove(desc->chrc->descs, desc);
 		desc_unregister(desc);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
 	desc->max_val_len = desc->value_len;
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 void gatt_register_desc(DBusConnection *conn, GDBusProxy *proxy,
@@ -3134,8 +3153,6 @@ void gatt_register_desc(DBusConnection *conn, GDBusProxy *proxy,
 	print_desc(desc, COLORED_NEW);
 
 	bt_shell_prompt_input(desc->path, "Enter value:", desc_set_value, desc);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static struct desc *desc_find(const char *pattern)
-- 
2.55.0


  parent reply	other threads:[~2026-09-28 17:32 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-28 17:32 [PATCH BlueZ v5 00/21] Add HoG functional tests and shared/hog Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 01/21] shared/gatt-client: Fix calling destroy after unregistering notify Luiz Augusto von Dentz
2026-09-28 17:32 ` Luiz Augusto von Dentz [this message]
2026-09-28 17:32 ` [PATCH BlueZ v5 03/21] client/mgmt: Print Connection Subrate event Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 04/21] emulator: Default to the latest BR/EDR+LE version Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 05/21] client/scripts: Add HoG device scripts Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 06/21] doc: Add functional-hog documentation Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 07/21] test: functional: add HoG tests Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 08/21] test: functional: limit the workers by the memory available Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 09/21] client/agent: Fix crash on Cancel with no pending request Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 10/21] shared/uhid: Fix size of Get Report reply with a Report ID Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 11/21] shared/uhid: Keep reading when an event is not available Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 12/21] shared/tester: Allow expecting a PDU with no response Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 13/21] shared/hog: Add initial implementation Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 14/21] unit/test-hog: Use shared/hog Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 15/21] test: functional: change the HoG SCI mode with the HID Control Point Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 16/21] input/hog: Use shared/hog Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 17/21] doc: Add CONFIG_HIDRAW to the tester kernel config Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 18/21] unit/test-uhid: Add Get Report tests Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 19/21] device: Use bt_att instead of GAttrib Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 20/21] attrib: Remove GAttrib and gatttool Luiz Augusto von Dentz
2026-09-28 17:32 ` [PATCH BlueZ v5 21/21] attrib: Remove directory Luiz Augusto von Dentz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260928173243.1073509-3-luiz.dentz@gmail.com \
    --to=luiz.dentz@gmail.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).