Commit 1d22f5a345 for asterisk.org

commit 1d22f5a345d092ca1711d2af71634418abff3d28
Author: Jasper Hafkenscheid <jasper.hafkenscheid@voys.nl>
Date:   Wed Jan 21 07:51:36 2026 +0100

    channelstorage_cpp_map_name_id: Fix get_by_name_prefix prefix match

    Lower bound filter did not ensure prefix match.

    Resolves: #1730

diff --git a/main/channelstorage.c b/main/channelstorage.c
index 63b551443e..de49f15f2e 100644
--- a/main/channelstorage.c
+++ b/main/channelstorage.c
@@ -265,6 +265,25 @@ static void *test_storage_thread(void *data)
 	elapsed = ast_tvdiff_us(end, start);
 	ast_test_status_update(test, "%*s: %8ld\n", collen, "by name prefix", elapsed);

+	/* Test negative cases - prefixes that should NOT match */
+	start = ast_tvnow();
+	for (i = 0; i < 10; i++) {
+		/* Search for non-existent prefix between existing channels
+		 * e.g., "TestChannel-{rand}-0000a" falls between 0000 and 0001
+		 */
+		sprintf(search1, "TestChannel-%ld-%04da", rand, i * 50);
+		mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, strlen(search1), 1);
+		ast_test_validate_cleanup_custom(test, mock_channel == NULL, res, done,
+			"Expected NULL for non-existent prefix '%s' but got '%s'\n",
+			search1, mock_channel ? ast_channel_name(mock_channel) : "NULL");
+		if (mock_channel) {
+			ast_channel_unref(mock_channel);
+		}
+	}
+	end = ast_tvnow();
+	elapsed = ast_tvdiff_us(end, start);
+	ast_test_status_update(test, "%*s: %8ld\n", collen, "prefix no-match", elapsed);
+
 	start = ast_tvnow();
 	for (i = 0; i < CHANNEL_COUNT; i++) {
 		sprintf(search1, "TestContext-%ld-%04d", rand, i % 100);
diff --git a/main/channelstorage_cpp_map_name_id.cc b/main/channelstorage_cpp_map_name_id.cc
index dfbfbb9a92..5862f9dc94 100644
--- a/main/channelstorage_cpp_map_name_id.cc
+++ b/main/channelstorage_cpp_map_name_id.cc
@@ -531,7 +531,10 @@ static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance
 	}
 	auto rtn = getdb(driver).lower_bound(l_name);
 	if (rtn != getdb(driver).end()) {
-		chan = ao2_bump((struct ast_channel *)rtn->second);
+		/* Check if the channel name actually starts with the requested prefix */
+		if (rtn->first.compare(0, name_len, l_name, name_len) == 0) {
+			chan = ao2_bump((struct ast_channel *)rtn->second);
+		}
 	}
 	if (lock) {
 		unlock(driver);