[openssh-commits] [openssh] 03/04: upstream: When tab-completing a filename, ensure that the completed

git+noreply at mindrot.org git+noreply at mindrot.org
Thu Oct 9 10:09:08 AEDT 2025


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 0f3b8fd68a29766697d7a709bae8b0a61da6cff2
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Wed Oct 8 21:48:40 2025 +0000

    upstream: When tab-completing a filename, ensure that the completed
    
    string does not end up mid-way through a multibyte character, as this will
    cause a fatal() later on.
    
    based on GHPR#587 from @TaoistBrickscarrier; feedback tb@ kevlo@
    ok dtucker@
    
    OpenBSD-Commit-ID: efb977164b4e20d61204a66201a7592ba8291362
---
 sftp.c | 52 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 34 insertions(+), 18 deletions(-)

diff --git a/sftp.c b/sftp.c
index 3b505eea2..57516a73a 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.245 2025/10/02 04:23:11 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.246 2025/10/08 21:48:40 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm at openbsd.org>
  *
@@ -1863,29 +1863,44 @@ complete_display(char **list, u_int len)
 static char *
 complete_ambiguous(const char *word, char **list, size_t count)
 {
+	size_t i, j, matchlen;
+	char *tmp;
+	int len;
+
 	if (word == NULL)
 		return NULL;
 
-	if (count > 0) {
-		u_int y, matchlen = strlen(list[0]);
+	if (count == 0)
+		return xstrdup(word); /* no options to complete */
 
-		/* Find length of common stem */
-		for (y = 1; list[y]; y++) {
-			u_int x;
+	/* Find length of common stem across list */
+	matchlen = strlen(list[0]);
+	for (i = 1; i < count && list[i] != NULL; i++) {
+		for (j = 0; j < matchlen; j++)
+			if (list[0][j] != list[i][j])
+				break;
+		matchlen = j;
+	}
 
-			for (x = 0; x < matchlen; x++)
-				if (list[0][x] != list[y][x])
-					break;
+	/*
+	 * Now check that the common stem doesn't finish in the middle of
+	 * a multibyte character.
+	 */
+	mblen(NULL, 0);
+	for (i = 0; i < matchlen;) {
+		len = mblen(list[0] + i, matchlen - i);
+		if (len <= 0 || i + (size_t)len > matchlen)
+			break;
+		i += (size_t)len;
+	}
+	/* If so, truncate */
+	if (i < matchlen)
+		matchlen = i;
 
-			matchlen = x;
-		}
-
-		if (matchlen > strlen(word)) {
-			char *tmp = xstrdup(list[0]);
-
-			tmp[matchlen] = '\0';
-			return tmp;
-		}
+	if (matchlen > strlen(word)) {
+		tmp = xstrdup(list[0]);
+		tmp[matchlen] = '\0';
+		return tmp;
 	}
 
 	return xstrdup(word);
@@ -2065,6 +2080,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
 		tmp2 = tmp + filelen - cesc;
 		len = strlen(tmp2);
 		/* quote argument on way out */
+		mblen(NULL, 0);
 		for (i = 0; i < len; i += clen) {
 			if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
 			    (size_t)clen > sizeof(ins) - 2)

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list