Linux bluetooth development
 help / color / mirror / Atom feed
From: Geraldo Netto <geraldonetto@gmail.com>
To: linux-bluetooth@vger.kernel.org
Cc: Geraldo Netto <geraldonetto@gmail.com>
Subject: [PATCH BlueZ 2/2] unit: split btsnoop pklg tests
Date: Sat, 20 Jun 2026 21:22:28 +0200	[thread overview]
Message-ID: <20260620192228.2692610-2-geraldonetto@gmail.com> (raw)
In-Reply-To: <20260620192228.2692610-1-geraldonetto@gmail.com>

---
 Makefile.am              |   3 +-
 unit/test-btsnoop-pklg.c | 266 ++++++++++++++++++++++
 unit/test-btsnoop.c      | 462 +++++++++------------------------------
 3 files changed, 374 insertions(+), 357 deletions(-)
 create mode 100644 unit/test-btsnoop-pklg.c

diff --git a/Makefile.am b/Makefile.am
index 4887934a9..db63f3b07 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -589,7 +589,8 @@ unit_test_textfile_LDADD = src/libshared-glib.la $(GLIB_LIBS)
 
 unit_tests += unit/test-btsnoop
 
-unit_test_btsnoop_SOURCES = unit/test-btsnoop.c \
+unit_test_btsnoop_SOURCES = unit/test-btsnoop.c unit/test-btsnoop.h \
+				unit/test-btsnoop-pklg.c \
 				src/shared/btsnoop.h src/shared/btsnoop.c
 unit_test_btsnoop_LDADD = src/libshared-glib.la $(GLIB_LIBS)
 
diff --git a/unit/test-btsnoop-pklg.c b/unit/test-btsnoop-pklg.c
new file mode 100644
index 000000000..ff3c24354
--- /dev/null
+++ b/unit/test-btsnoop-pklg.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <endian.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+
+#include "src/shared/att-types.h"
+#include "src/shared/btsnoop.h"
+#include "unit/test-btsnoop.h"
+
+#define PKLG_PAYLOAD_OFFSET 9
+
+struct test_pklg_pkt {
+	uint32_t len;
+	uint64_t ts;
+	uint8_t type;
+} __packed;
+
+struct read_result {
+	uint8_t data[BTSNOOP_MAX_PACKET_SIZE];
+	uint16_t size;
+	uint16_t index;
+	uint16_t opcode;
+	struct timeval tv;
+};
+
+static void read_result_init(struct read_result *result)
+{
+	memset(result->data, 0xa5, sizeof(result->data));
+	result->size = 0;
+	result->index = 0xffff;
+	result->opcode = 0xffff;
+	memset(&result->tv, 0, sizeof(result->tv));
+}
+
+static void append_bytes(GByteArray *array, const void *data, size_t size)
+{
+	if (size)
+		g_byte_array_append(array, data, size);
+}
+
+static void append_pklg_packet(GByteArray *array, bool little_endian,
+				uint32_t payload_len, uint64_t ts,
+				uint8_t type, const void *data, size_t data_len)
+{
+	struct test_pklg_pkt pkt;
+	uint32_t len = PKLG_PAYLOAD_OFFSET + payload_len;
+
+	pkt.len = little_endian ? htole32(len) : htobe32(len);
+	pkt.ts = little_endian ? htole64(ts) : htobe64(ts);
+	pkt.type = type;
+
+	append_bytes(array, &pkt, sizeof(pkt));
+	append_bytes(array, data, data_len);
+}
+
+static char *write_tmp_trace(const void *data, size_t size)
+{
+	char *path = NULL;
+	ssize_t written;
+	int fd;
+
+	fd = g_file_open_tmp("bluez-btsnoop-XXXXXX", &path, NULL);
+	g_assert(fd >= 0);
+	written = write(fd, data, size);
+	g_assert_cmpint(written, ==, (ssize_t) size);
+	g_assert_cmpint(close(fd), ==, 0);
+
+	return path;
+}
+
+static bool read_tmp_trace(const void *trace, size_t trace_len,
+				uint16_t data_size, struct read_result *result)
+{
+	struct btsnoop *btsnoop;
+	char *path;
+	bool ok;
+
+	read_result_init(result);
+	path = write_tmp_trace(trace, trace_len);
+	btsnoop = btsnoop_open(path, BTSNOOP_FLAG_PKLG_SUPPORT);
+	unlink(path);
+	g_free(path);
+
+	if (!btsnoop)
+		return false;
+
+	ok = btsnoop_read_hci(btsnoop, &result->tv, &result->index,
+				&result->opcode, result->data, data_size,
+				&result->size);
+	btsnoop_unref(btsnoop);
+
+	return ok;
+}
+
+static void test_pklg_big_endian_valid(void)
+{
+	GByteArray *trace = g_byte_array_new();
+	const uint8_t payload[] = { 0x0e, 0x01, 0x00 };
+	struct read_result result;
+
+	append_pklg_packet(trace, false, sizeof(payload),
+			((uint64_t) 123 << 32) | 456, 0x01, payload,
+			sizeof(payload));
+
+	g_assert_true(read_tmp_trace(trace->data, trace->len, sizeof(payload),
+								&result));
+	g_assert_cmpint(result.index, ==, 0);
+	g_assert_cmpint(result.opcode, ==, BTSNOOP_OPCODE_EVENT_PKT);
+	g_assert_cmpint(result.size, ==, sizeof(payload));
+	g_assert_cmpint(memcmp(result.data, payload, sizeof(payload)), ==, 0);
+	g_assert_cmpint(result.tv.tv_sec, ==, 123);
+	g_assert_cmpint(result.tv.tv_usec, ==, 456);
+
+	g_byte_array_unref(trace);
+}
+
+static void test_pklg_little_endian_valid(void)
+{
+	GByteArray *trace = g_byte_array_new();
+	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
+	struct read_result result;
+
+	append_pklg_packet(trace, true, sizeof(payload),
+			((uint64_t) 456 << 32) | 123, 0x00, payload,
+			sizeof(payload));
+
+	g_assert_true(read_tmp_trace(trace->data, trace->len, sizeof(payload),
+								&result));
+	g_assert_cmpint(result.index, ==, 0);
+	g_assert_cmpint(result.opcode, ==, BTSNOOP_OPCODE_COMMAND_PKT);
+	g_assert_cmpint(result.size, ==, sizeof(payload));
+	g_assert_cmpint(result.data[0], ==, payload[0]);
+	g_assert_cmpint(result.tv.tv_sec, ==, 123);
+	g_assert_cmpint(result.tv.tv_usec, ==, 456);
+
+	g_byte_array_unref(trace);
+}
+
+static void test_pklg_rejects_short_length(void)
+{
+	GByteArray *trace = g_byte_array_new();
+	struct test_pklg_pkt pkt;
+	const uint8_t padding[] = { 0x00, 0x00, 0x00 };
+	struct read_result result;
+
+	pkt.len = htobe32(PKLG_PAYLOAD_OFFSET - 1);
+	pkt.ts = 0;
+	pkt.type = 0x01;
+
+	append_bytes(trace, &pkt, sizeof(pkt));
+	append_bytes(trace, padding, sizeof(padding));
+
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, &result));
+
+	g_byte_array_unref(trace);
+}
+
+static void test_pklg_rejects_small_capacity(void)
+{
+	GByteArray *trace = g_byte_array_new();
+	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
+	struct read_result result;
+
+	append_pklg_packet(trace, false, sizeof(payload), 0, 0x01, payload,
+							sizeof(payload));
+
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 2, &result));
+	g_assert_cmpint(result.data[0], ==, 0xa5);
+	g_assert_cmpint(result.data[1], ==, 0xa5);
+	g_assert_cmpint(result.data[2], ==, 0xa5);
+	g_assert_cmpint(result.data[3], ==, 0xa5);
+
+	g_byte_array_unref(trace);
+}
+
+static void test_pklg_rejects_short_payload(void)
+{
+	GByteArray *trace = g_byte_array_new();
+	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
+	struct read_result result;
+
+	append_pklg_packet(trace, false, 4, 0, 0x01, payload,
+							sizeof(payload));
+
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 4, &result));
+
+	g_byte_array_unref(trace);
+}
+
+static void test_pklg_type_map(void)
+{
+	static const struct {
+		uint8_t type;
+		uint16_t index;
+		uint16_t opcode;
+	} cases[] = {
+		{ 0x02, 0x0000, BTSNOOP_OPCODE_ACL_TX_PKT },
+		{ 0x03, 0x0000, BTSNOOP_OPCODE_ACL_RX_PKT },
+		{ 0x08, 0x0000, BTSNOOP_OPCODE_SCO_TX_PKT },
+		{ 0x09, 0x0000, BTSNOOP_OPCODE_SCO_RX_PKT },
+		{ 0x12, 0x0000, BTSNOOP_OPCODE_ISO_TX_PKT },
+		{ 0x13, 0x0000, BTSNOOP_OPCODE_ISO_RX_PKT },
+		{ 0x0b, 0x0000, BTSNOOP_OPCODE_VENDOR_DIAG },
+		{ 0xfc, 0xffff, BTSNOOP_OPCODE_SYSTEM_NOTE },
+		{ 0xaa, 0xffff, 0xffff },
+	};
+	const uint8_t payload[] = { 0x00, 0x01, 0x02 };
+	unsigned int i;
+
+	for (i = 0; i < G_N_ELEMENTS(cases); i++) {
+		GByteArray *trace = g_byte_array_new();
+		struct read_result result;
+
+		append_pklg_packet(trace, false, sizeof(payload), 0,
+						cases[i].type, payload,
+						sizeof(payload));
+
+		g_assert_true(read_tmp_trace(trace->data, trace->len,
+						sizeof(payload), &result));
+		g_assert_cmpint(result.index, ==, cases[i].index);
+		g_assert_cmpint(result.opcode, ==, cases[i].opcode);
+		g_byte_array_unref(trace);
+	}
+}
+
+static void test_pklg_truncation_fuzz(void)
+{
+	GByteArray *trace = g_byte_array_new();
+	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
+	size_t len;
+
+	append_pklg_packet(trace, false, sizeof(payload), 0, 0x01, payload,
+							sizeof(payload));
+
+	for (len = 0; len < trace->len; len++) {
+		struct read_result result;
+
+		g_assert_false(read_tmp_trace(trace->data, len, sizeof(payload),
+								&result));
+	}
+
+	g_byte_array_unref(trace);
+}
+
+void add_pklg_tests(void)
+{
+	g_test_add_func("/pklg/big-endian/valid", test_pklg_big_endian_valid);
+	g_test_add_func("/pklg/little-endian/valid",
+			test_pklg_little_endian_valid);
+	g_test_add_func("/pklg/length/short", test_pklg_rejects_short_length);
+	g_test_add_func("/pklg/capacity/reject",
+			test_pklg_rejects_small_capacity);
+	g_test_add_func("/pklg/payload/short", test_pklg_rejects_short_payload);
+	g_test_add_func("/pklg/type-map", test_pklg_type_map);
+	g_test_add_func("/pklg/fuzz/truncation", test_pklg_truncation_fuzz);
+}
diff --git a/unit/test-btsnoop.c b/unit/test-btsnoop.c
index 710209097..fa7587d1a 100644
--- a/unit/test-btsnoop.c
+++ b/unit/test-btsnoop.c
@@ -18,7 +18,6 @@
 #include "unit/test-btsnoop.h"
 
 #define BTSNOOP_EPOCH_OFFSET 0x00E03AB44A676000ull
-#define PKLG_PAYLOAD_OFFSET 9
 
 struct test_btsnoop_hdr {
 	uint8_t id[8];
@@ -34,22 +33,31 @@ struct test_btsnoop_pkt {
 	uint64_t ts;
 } __packed;
 
-struct test_pklg_pkt {
-	uint32_t len;
-	uint64_t ts;
-	uint8_t type;
-} __packed;
+struct read_result {
+	uint8_t data[BTSNOOP_MAX_PACKET_SIZE];
+	uint16_t size;
+	uint16_t index;
+	uint16_t opcode;
+	struct timeval tv;
+};
 
 static const uint8_t btsnoop_id[] = {
 	0x62, 0x74, 0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00
 };
 
-static void append_bytes(GByteArray *array, const void *data, size_t size)
+static void read_result_init(struct read_result *result)
 {
-	if (!size)
-		return;
+	memset(result->data, 0xa5, sizeof(result->data));
+	result->size = 0;
+	result->index = 0xffff;
+	result->opcode = 0xffff;
+	memset(&result->tv, 0, sizeof(result->tv));
+}
 
-	g_byte_array_append(array, data, size);
+static void append_bytes(GByteArray *array, const void *data, size_t size)
+{
+	if (size)
+		g_byte_array_append(array, data, size);
 }
 
 static void append_btsnoop_header(GByteArray *array, uint32_t format)
@@ -79,21 +87,6 @@ static void append_btsnoop_packet(GByteArray *array, uint32_t len,
 	append_bytes(array, data, data_len);
 }
 
-static void append_pklg_packet(GByteArray *array, bool little_endian,
-				uint32_t payload_len, uint64_t ts,
-				uint8_t type, const void *data, size_t data_len)
-{
-	struct test_pklg_pkt pkt;
-	uint32_t len = PKLG_PAYLOAD_OFFSET + payload_len;
-
-	pkt.len = little_endian ? htole32(len) : htobe32(len);
-	pkt.ts = little_endian ? htole64(ts) : htobe64(ts);
-	pkt.type = type;
-
-	append_bytes(array, &pkt, sizeof(pkt));
-	append_bytes(array, data, data_len);
-}
-
 static char *write_tmp_trace(const void *data, size_t size)
 {
 	char *path = NULL;
@@ -127,9 +120,8 @@ static void unlink_rotated(const char *path, unsigned int count)
 	unsigned int i;
 
 	for (i = 0; i <= count; i++) {
-		char *name;
+		char *name = g_strdup_printf("%s.%u", path, i);
 
-		name = g_strdup_printf("%s.%u", path, i);
 		unlink(name);
 		g_free(name);
 	}
@@ -137,14 +129,13 @@ static void unlink_rotated(const char *path, unsigned int count)
 
 static bool read_tmp_trace(const void *trace, size_t trace_len,
 				unsigned long flags, uint16_t data_size,
-				uint8_t *data, uint16_t *size,
-				uint16_t *index, uint16_t *opcode,
-				struct timeval *tv)
+				struct read_result *result)
 {
 	struct btsnoop *btsnoop;
 	char *path;
-	bool result;
+	bool ok;
 
+	read_result_init(result);
 	path = write_tmp_trace(trace, trace_len);
 	btsnoop = btsnoop_open(path, flags);
 	unlink(path);
@@ -153,54 +144,51 @@ static bool read_tmp_trace(const void *trace, size_t trace_len,
 	if (!btsnoop)
 		return false;
 
-	result = btsnoop_read_hci(btsnoop, tv, index, opcode, data,
-							data_size, size);
+	ok = btsnoop_read_hci(btsnoop, &result->tv, &result->index,
+				&result->opcode, result->data, data_size,
+				&result->size);
 	btsnoop_unref(btsnoop);
 
-	return result;
+	return ok;
 }
 
 static bool read_trace_file(const char *path, unsigned long flags,
-				uint8_t *data, uint16_t data_size,
-				uint16_t *size, uint16_t *index,
-				uint16_t *opcode, struct timeval *tv)
+				uint16_t data_size, struct read_result *result)
 {
 	struct btsnoop *btsnoop;
-	bool result;
+	bool ok;
 
+	read_result_init(result);
 	btsnoop = btsnoop_open(path, flags);
 	g_assert_nonnull(btsnoop);
 
-	result = btsnoop_read_hci(btsnoop, tv, index, opcode, data,
-							data_size, size);
+	ok = btsnoop_read_hci(btsnoop, &result->tv, &result->index,
+				&result->opcode, result->data, data_size,
+				&result->size);
 	btsnoop_unref(btsnoop);
 
-	return result;
+	return ok;
 }
 
 static void test_btsnoop_hci_valid(void)
 {
 	GByteArray *trace = g_byte_array_new();
 	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
-	uint8_t data[sizeof(payload)];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0xffff;
-	uint16_t opcode = 0xffff;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_HCI);
 	append_btsnoop_packet(trace, sizeof(payload), 0x02,
 			BTSNOOP_EPOCH_OFFSET + 1234567, payload,
 			sizeof(payload));
 
-	g_assert_true(read_tmp_trace(trace->data, trace->len, 0, sizeof(data),
-					data, &size, &index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 0);
-	g_assert_cmpint(opcode, ==, BTSNOOP_OPCODE_COMMAND_PKT);
-	g_assert_cmpint(size, ==, sizeof(payload));
-	g_assert_cmpint(memcmp(data, payload, sizeof(payload)), ==, 0);
-	g_assert_cmpint(tv.tv_sec, ==, 946684801);
-	g_assert_cmpint(tv.tv_usec, ==, 234567);
+	g_assert_true(read_tmp_trace(trace->data, trace->len, 0,
+						sizeof(payload), &result));
+	g_assert_cmpint(result.index, ==, 0);
+	g_assert_cmpint(result.opcode, ==, BTSNOOP_OPCODE_COMMAND_PKT);
+	g_assert_cmpint(result.size, ==, sizeof(payload));
+	g_assert_cmpint(memcmp(result.data, payload, sizeof(payload)), ==, 0);
+	g_assert_cmpint(result.tv.tv_sec, ==, 946684801);
+	g_assert_cmpint(result.tv.tv_usec, ==, 234567);
 
 	g_byte_array_unref(trace);
 }
@@ -247,12 +235,9 @@ static void test_btsnoop_write_hci_roundtrip(void)
 {
 	const uint8_t command[] = { 0x01, 0x02, 0x03 };
 	const uint8_t event[] = { 0x04, 0x05 };
-	uint8_t data[sizeof(command)];
 	struct btsnoop *btsnoop;
+	struct read_result result;
 	struct timeval tv = { .tv_sec = 946684802, .tv_usec = 345678 };
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
 	char *path = new_tmp_path();
 
 	btsnoop = btsnoop_create(path, 0, 0, BTSNOOP_FORMAT_HCI);
@@ -272,24 +257,30 @@ static void test_btsnoop_write_hci_roundtrip(void)
 					command, sizeof(command)));
 	btsnoop_unref(btsnoop);
 
-	g_assert_true(read_trace_file(path, 0, data, sizeof(data), &size,
-						&index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 0);
-	g_assert_cmpint(opcode, ==, BTSNOOP_OPCODE_COMMAND_PKT);
-	g_assert_cmpint(size, ==, sizeof(command));
-	g_assert_cmpint(memcmp(data, command, sizeof(command)), ==, 0);
+	g_assert_true(read_trace_file(path, 0, sizeof(command), &result));
+	g_assert_cmpint(result.index, ==, 0);
+	g_assert_cmpint(result.opcode, ==, BTSNOOP_OPCODE_COMMAND_PKT);
+	g_assert_cmpint(result.size, ==, sizeof(command));
+	g_assert_cmpint(memcmp(result.data, command, sizeof(command)), ==, 0);
 
 	btsnoop = btsnoop_open(path, 0);
 	g_assert_nonnull(btsnoop);
-	g_assert_true(btsnoop_read_hci(btsnoop, &tv, &index, &opcode, data,
-							sizeof(data), &size));
-	g_assert_true(btsnoop_read_hci(btsnoop, &tv, &index, &opcode, data,
-							sizeof(data), &size));
-	g_assert_cmpint(opcode, ==, BTSNOOP_OPCODE_EVENT_PKT);
-	g_assert_cmpint(size, ==, sizeof(event));
-	g_assert_cmpint(memcmp(data, event, sizeof(event)), ==, 0);
-	g_assert_false(btsnoop_read_hci(btsnoop, &tv, &index, &opcode, data,
-							sizeof(data), &size));
+	read_result_init(&result);
+	g_assert_true(btsnoop_read_hci(btsnoop, &result.tv,
+				&result.index, &result.opcode,
+				result.data, sizeof(result.data),
+				&result.size));
+	g_assert_true(btsnoop_read_hci(btsnoop, &result.tv,
+				&result.index, &result.opcode,
+				result.data, sizeof(result.data),
+				&result.size));
+	g_assert_cmpint(result.opcode, ==, BTSNOOP_OPCODE_EVENT_PKT);
+	g_assert_cmpint(result.size, ==, sizeof(event));
+	g_assert_cmpint(memcmp(result.data, event, sizeof(event)), ==, 0);
+	g_assert_false(btsnoop_read_hci(btsnoop, &result.tv,
+				&result.index, &result.opcode,
+				result.data, sizeof(result.data),
+				&result.size));
 	btsnoop_unref(btsnoop);
 
 	unlink(path);
@@ -299,12 +290,9 @@ static void test_btsnoop_write_hci_roundtrip(void)
 static void test_btsnoop_write_monitor_roundtrip(void)
 {
 	const uint8_t payload[] = { 0xaa, 0xbb };
-	uint8_t data[sizeof(payload)];
 	struct btsnoop *btsnoop;
+	struct read_result result;
 	struct timeval tv = { .tv_sec = 946684800, .tv_usec = 0 };
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
 	char *path = new_tmp_path();
 
 	btsnoop = btsnoop_create(path, 0, 0, BTSNOOP_FORMAT_MONITOR);
@@ -313,12 +301,11 @@ static void test_btsnoop_write_monitor_roundtrip(void)
 						payload, sizeof(payload)));
 	btsnoop_unref(btsnoop);
 
-	g_assert_true(read_trace_file(path, 0, data, sizeof(data), &size,
-						&index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 7);
-	g_assert_cmpint(opcode, ==, 0x1234);
-	g_assert_cmpint(size, ==, sizeof(payload));
-	g_assert_cmpint(memcmp(data, payload, sizeof(payload)), ==, 0);
+	g_assert_true(read_trace_file(path, 0, sizeof(payload), &result));
+	g_assert_cmpint(result.index, ==, 7);
+	g_assert_cmpint(result.opcode, ==, 0x1234);
+	g_assert_cmpint(result.size, ==, sizeof(payload));
+	g_assert_cmpint(memcmp(result.data, payload, sizeof(payload)), ==, 0);
 
 	unlink(path);
 	g_free(path);
@@ -355,22 +342,18 @@ static void test_btsnoop_monitor_valid(void)
 {
 	GByteArray *trace = g_byte_array_new();
 	const uint8_t payload[] = { 0xaa, 0xbb };
-	uint8_t data[sizeof(payload)];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0xffff;
-	uint16_t opcode = 0xffff;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_MONITOR);
 	append_btsnoop_packet(trace, sizeof(payload), 0x00051234,
 			BTSNOOP_EPOCH_OFFSET, payload, sizeof(payload));
 
-	g_assert_true(read_tmp_trace(trace->data, trace->len, 0, sizeof(data),
-					data, &size, &index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 5);
-	g_assert_cmpint(opcode, ==, 0x1234);
-	g_assert_cmpint(size, ==, sizeof(payload));
-	g_assert_cmpint(memcmp(data, payload, sizeof(payload)), ==, 0);
+	g_assert_true(read_tmp_trace(trace->data, trace->len, 0,
+						sizeof(payload), &result));
+	g_assert_cmpint(result.index, ==, 5);
+	g_assert_cmpint(result.opcode, ==, 0x1234);
+	g_assert_cmpint(result.size, ==, sizeof(payload));
+	g_assert_cmpint(memcmp(result.data, payload, sizeof(payload)), ==, 0);
 
 	g_byte_array_unref(trace);
 }
@@ -379,22 +362,18 @@ static void test_btsnoop_uart_valid(void)
 {
 	GByteArray *trace = g_byte_array_new();
 	const uint8_t payload[] = { 0x04, 0x0e, 0x01, 0x00 };
-	uint8_t data[sizeof(payload) - 1];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0xffff;
-	uint16_t opcode = 0xffff;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_UART);
 	append_btsnoop_packet(trace, sizeof(payload), 0,
 			BTSNOOP_EPOCH_OFFSET, payload, sizeof(payload));
 
-	g_assert_true(read_tmp_trace(trace->data, trace->len, 0, sizeof(data),
-					data, &size, &index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 0);
-	g_assert_cmpint(opcode, ==, BTSNOOP_OPCODE_EVENT_PKT);
-	g_assert_cmpint(size, ==, sizeof(payload) - 1);
-	g_assert_cmpint(memcmp(data, payload + 1, sizeof(data)), ==, 0);
+	g_assert_true(read_tmp_trace(trace->data, trace->len, 0,
+						sizeof(payload) - 1, &result));
+	g_assert_cmpint(result.index, ==, 0);
+	g_assert_cmpint(result.opcode, ==, BTSNOOP_OPCODE_EVENT_PKT);
+	g_assert_cmpint(result.size, ==, sizeof(payload) - 1);
+	g_assert_cmpint(memcmp(result.data, payload + 1, result.size), ==, 0);
 
 	g_byte_array_unref(trace);
 }
@@ -420,20 +399,15 @@ static void test_btsnoop_uart_opcode_map(void)
 	for (i = 0; i < G_N_ELEMENTS(cases); i++) {
 		GByteArray *trace = g_byte_array_new();
 		const uint8_t payload[] = { cases[i].type, 0x00 };
-		uint8_t data[1];
-		struct timeval tv;
-		uint16_t size = 0;
-		uint16_t index = 0;
-		uint16_t opcode = 0;
+		struct read_result result;
 
 		append_btsnoop_header(trace, BTSNOOP_FORMAT_UART);
 		append_btsnoop_packet(trace, sizeof(payload), cases[i].flags,
 				BTSNOOP_EPOCH_OFFSET, payload, sizeof(payload));
 
-		g_assert_true(read_tmp_trace(trace->data, trace->len, 0,
-						sizeof(data), data, &size,
-						&index, &opcode, &tv));
-		g_assert_cmpint(opcode, ==, cases[i].opcode);
+		g_assert_true(read_tmp_trace(trace->data, trace->len, 0, 1,
+								&result));
+		g_assert_cmpint(result.opcode, ==, cases[i].opcode);
 		g_byte_array_unref(trace);
 	}
 }
@@ -442,22 +416,17 @@ static void test_btsnoop_rejects_small_capacity(void)
 {
 	GByteArray *trace = g_byte_array_new();
 	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
-	uint8_t data[4] = { 0xa5, 0xa5, 0xa5, 0xa5 };
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_HCI);
 	append_btsnoop_packet(trace, sizeof(payload), 0x02,
 			BTSNOOP_EPOCH_OFFSET, payload, sizeof(payload));
 
-	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 2, data,
-						&size, &index, &opcode, &tv));
-	g_assert_cmpint(data[0], ==, 0xa5);
-	g_assert_cmpint(data[1], ==, 0xa5);
-	g_assert_cmpint(data[2], ==, 0xa5);
-	g_assert_cmpint(data[3], ==, 0xa5);
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 2, &result));
+	g_assert_cmpint(result.data[0], ==, 0xa5);
+	g_assert_cmpint(result.data[1], ==, 0xa5);
+	g_assert_cmpint(result.data[2], ==, 0xa5);
+	g_assert_cmpint(result.data[3], ==, 0xa5);
 
 	g_byte_array_unref(trace);
 }
@@ -465,17 +434,13 @@ static void test_btsnoop_rejects_small_capacity(void)
 static void test_btsnoop_rejects_timestamp_underflow(void)
 {
 	GByteArray *trace = g_byte_array_new();
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_HCI);
 	append_btsnoop_packet(trace, 0, 0x02, BTSNOOP_EPOCH_OFFSET - 1,
 								NULL, 0);
 
-	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 0, NULL,
-						&size, &index, &opcode, &tv));
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 0, &result));
 
 	g_byte_array_unref(trace);
 }
@@ -483,16 +448,12 @@ static void test_btsnoop_rejects_timestamp_underflow(void)
 static void test_btsnoop_rejects_uart_zero_length(void)
 {
 	GByteArray *trace = g_byte_array_new();
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_UART);
 	append_btsnoop_packet(trace, 0, 0, BTSNOOP_EPOCH_OFFSET, NULL, 0);
 
-	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 0, NULL,
-						&size, &index, &opcode, &tv));
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 0, &result));
 
 	g_byte_array_unref(trace);
 }
@@ -500,16 +461,12 @@ static void test_btsnoop_rejects_uart_zero_length(void)
 static void test_btsnoop_rejects_uart_short_type(void)
 {
 	GByteArray *trace = g_byte_array_new();
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_UART);
 	append_btsnoop_packet(trace, 1, 0, BTSNOOP_EPOCH_OFFSET, NULL, 0);
 
-	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 0, NULL,
-						&size, &index, &opcode, &tv));
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 0, &result));
 
 	g_byte_array_unref(trace);
 }
@@ -518,187 +475,17 @@ static void test_btsnoop_rejects_short_payload(void)
 {
 	GByteArray *trace = g_byte_array_new();
 	const uint8_t payload[] = { 0x01, 0x02 };
-	uint8_t data[3];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
+	struct read_result result;
 
 	append_btsnoop_header(trace, BTSNOOP_FORMAT_HCI);
 	append_btsnoop_packet(trace, 3, 0x02, BTSNOOP_EPOCH_OFFSET,
 					payload, sizeof(payload));
 
-	g_assert_false(read_tmp_trace(trace->data, trace->len, 0,
-					sizeof(data), data, &size,
-					&index, &opcode, &tv));
-
-	g_byte_array_unref(trace);
-}
-
-static void test_pklg_big_endian_valid(void)
-{
-	GByteArray *trace = g_byte_array_new();
-	const uint8_t payload[] = { 0x0e, 0x01, 0x00 };
-	uint8_t data[sizeof(payload)];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0xffff;
-	uint16_t opcode = 0xffff;
-
-	append_pklg_packet(trace, false, sizeof(payload),
-			((uint64_t) 123 << 32) | 456, 0x01, payload,
-			sizeof(payload));
-
-	g_assert_true(read_tmp_trace(trace->data, trace->len,
-					BTSNOOP_FLAG_PKLG_SUPPORT, sizeof(data),
-					data, &size, &index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 0);
-	g_assert_cmpint(opcode, ==, BTSNOOP_OPCODE_EVENT_PKT);
-	g_assert_cmpint(size, ==, sizeof(payload));
-	g_assert_cmpint(memcmp(data, payload, sizeof(payload)), ==, 0);
-	g_assert_cmpint(tv.tv_sec, ==, 123);
-	g_assert_cmpint(tv.tv_usec, ==, 456);
-
-	g_byte_array_unref(trace);
-}
-
-static void test_pklg_little_endian_valid(void)
-{
-	GByteArray *trace = g_byte_array_new();
-	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
-	uint8_t data[sizeof(payload)];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0xffff;
-	uint16_t opcode = 0xffff;
-
-	append_pklg_packet(trace, true, sizeof(payload),
-			((uint64_t) 456 << 32) | 123, 0x00, payload,
-			sizeof(payload));
-
-	g_assert_true(read_tmp_trace(trace->data, trace->len,
-					BTSNOOP_FLAG_PKLG_SUPPORT, sizeof(data),
-					data, &size, &index, &opcode, &tv));
-	g_assert_cmpint(index, ==, 0);
-	g_assert_cmpint(opcode, ==, BTSNOOP_OPCODE_COMMAND_PKT);
-	g_assert_cmpint(size, ==, sizeof(payload));
-	g_assert_cmpint(data[0], ==, payload[0]);
-	g_assert_cmpint(tv.tv_sec, ==, 123);
-	g_assert_cmpint(tv.tv_usec, ==, 456);
-
-	g_byte_array_unref(trace);
-}
-
-static void test_pklg_rejects_short_length(void)
-{
-	GByteArray *trace = g_byte_array_new();
-	struct test_pklg_pkt pkt;
-	const uint8_t padding[] = { 0x00, 0x00, 0x00 };
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
-
-	pkt.len = htobe32(PKLG_PAYLOAD_OFFSET - 1);
-	pkt.ts = 0;
-	pkt.type = 0x01;
-
-	append_bytes(trace, &pkt, sizeof(pkt));
-	append_bytes(trace, padding, sizeof(padding));
-
-	g_assert_false(read_tmp_trace(trace->data, trace->len,
-					BTSNOOP_FLAG_PKLG_SUPPORT, 0, NULL,
-					&size, &index, &opcode, &tv));
-
-	g_byte_array_unref(trace);
-}
-
-static void test_pklg_rejects_small_capacity(void)
-{
-	GByteArray *trace = g_byte_array_new();
-	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
-	uint8_t data[4] = { 0xa5, 0xa5, 0xa5, 0xa5 };
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
-
-	append_pklg_packet(trace, false, sizeof(payload), 0, 0x01, payload,
-							sizeof(payload));
-
-	g_assert_false(read_tmp_trace(trace->data, trace->len,
-					BTSNOOP_FLAG_PKLG_SUPPORT, 2, data,
-					&size, &index, &opcode, &tv));
-	g_assert_cmpint(data[0], ==, 0xa5);
-	g_assert_cmpint(data[1], ==, 0xa5);
-	g_assert_cmpint(data[2], ==, 0xa5);
-	g_assert_cmpint(data[3], ==, 0xa5);
+	g_assert_false(read_tmp_trace(trace->data, trace->len, 0, 3, &result));
 
 	g_byte_array_unref(trace);
 }
 
-static void test_pklg_rejects_short_payload(void)
-{
-	GByteArray *trace = g_byte_array_new();
-	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
-	uint8_t data[4];
-	struct timeval tv;
-	uint16_t size = 0;
-	uint16_t index = 0;
-	uint16_t opcode = 0;
-
-	append_pklg_packet(trace, false, 4, 0, 0x01, payload,
-							sizeof(payload));
-
-	g_assert_false(read_tmp_trace(trace->data, trace->len,
-					BTSNOOP_FLAG_PKLG_SUPPORT, sizeof(data),
-					data, &size, &index, &opcode, &tv));
-
-	g_byte_array_unref(trace);
-}
-
-static void test_pklg_type_map(void)
-{
-	static const struct {
-		uint8_t type;
-		uint16_t index;
-		uint16_t opcode;
-	} cases[] = {
-		{ 0x02, 0x0000, BTSNOOP_OPCODE_ACL_TX_PKT },
-		{ 0x03, 0x0000, BTSNOOP_OPCODE_ACL_RX_PKT },
-		{ 0x08, 0x0000, BTSNOOP_OPCODE_SCO_TX_PKT },
-		{ 0x09, 0x0000, BTSNOOP_OPCODE_SCO_RX_PKT },
-		{ 0x12, 0x0000, BTSNOOP_OPCODE_ISO_TX_PKT },
-		{ 0x13, 0x0000, BTSNOOP_OPCODE_ISO_RX_PKT },
-		{ 0x0b, 0x0000, BTSNOOP_OPCODE_VENDOR_DIAG },
-		{ 0xfc, 0xffff, BTSNOOP_OPCODE_SYSTEM_NOTE },
-		{ 0xaa, 0xffff, 0xffff },
-	};
-	const uint8_t payload[] = { 0x00, 0x01, 0x02 };
-	unsigned int i;
-
-	for (i = 0; i < G_N_ELEMENTS(cases); i++) {
-		GByteArray *trace = g_byte_array_new();
-		uint8_t data[sizeof(payload)];
-		struct timeval tv;
-		uint16_t size = 0;
-		uint16_t index = 0;
-		uint16_t opcode = 0;
-
-		append_pklg_packet(trace, false, sizeof(payload), 0,
-						cases[i].type, payload,
-						sizeof(payload));
-
-		g_assert_true(read_tmp_trace(trace->data, trace->len,
-						BTSNOOP_FLAG_PKLG_SUPPORT,
-						sizeof(data), data, &size,
-						&index, &opcode, &tv));
-		g_assert_cmpint(index, ==, cases[i].index);
-		g_assert_cmpint(opcode, ==, cases[i].opcode);
-		g_byte_array_unref(trace);
-	}
-}
-
 static void test_btsnoop_truncation_fuzz(void)
 {
 	GByteArray *trace = g_byte_array_new();
@@ -710,40 +497,10 @@ static void test_btsnoop_truncation_fuzz(void)
 			BTSNOOP_EPOCH_OFFSET, payload, sizeof(payload));
 
 	for (len = 0; len < trace->len; len++) {
-		uint8_t data[sizeof(payload)];
-		struct timeval tv;
-		uint16_t size = 0;
-		uint16_t index = 0;
-		uint16_t opcode = 0;
+		struct read_result result;
 
 		g_assert_false(read_tmp_trace(trace->data, len, 0,
-						sizeof(data), data, &size,
-						&index, &opcode, &tv));
-	}
-
-	g_byte_array_unref(trace);
-}
-
-static void test_pklg_truncation_fuzz(void)
-{
-	GByteArray *trace = g_byte_array_new();
-	const uint8_t payload[] = { 0x01, 0x02, 0x03 };
-	size_t len;
-
-	append_pklg_packet(trace, false, sizeof(payload), 0, 0x01, payload,
-							sizeof(payload));
-
-	for (len = 0; len < trace->len; len++) {
-		uint8_t data[sizeof(payload)];
-		struct timeval tv;
-		uint16_t size = 0;
-		uint16_t index = 0;
-		uint16_t opcode = 0;
-
-		g_assert_false(read_tmp_trace(trace->data, len,
-						BTSNOOP_FLAG_PKLG_SUPPORT,
-						sizeof(data), data, &size,
-						&index, &opcode, &tv));
+						sizeof(payload), &result));
 	}
 
 	g_byte_array_unref(trace);
@@ -778,17 +535,10 @@ int main(int argc, char *argv[])
 			test_btsnoop_rejects_uart_short_type);
 	g_test_add_func("/btsnoop/payload/short",
 			test_btsnoop_rejects_short_payload);
-	g_test_add_func("/pklg/big-endian/valid", test_pklg_big_endian_valid);
-	g_test_add_func("/pklg/little-endian/valid",
-			test_pklg_little_endian_valid);
-	g_test_add_func("/pklg/length/short", test_pklg_rejects_short_length);
-	g_test_add_func("/pklg/capacity/reject",
-			test_pklg_rejects_small_capacity);
-	g_test_add_func("/pklg/payload/short", test_pklg_rejects_short_payload);
-	g_test_add_func("/pklg/type-map", test_pklg_type_map);
 	g_test_add_func("/btsnoop/fuzz/truncation",
 			test_btsnoop_truncation_fuzz);
-	g_test_add_func("/pklg/fuzz/truncation", test_pklg_truncation_fuzz);
+
+	add_pklg_tests();
 
 	return g_test_run();
 }
-- 
2.43.0


  reply	other threads:[~2026-06-20 19:22 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-20 19:22 [PATCH BlueZ 1/2] shared: harden btsnoop trace parsing Geraldo Netto
2026-06-20 19:22 ` Geraldo Netto [this message]
2026-06-20 21:09 ` [BlueZ,1/2] " bluez.test.bot

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=20260620192228.2692610-2-geraldonetto@gmail.com \
    --to=geraldonetto@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