From dadecc8e1ea5dd360e220f2320f84a78fc284b65 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jun 2026 16:28:19 +1000 Subject: [PATCH] exclude: count trailing backslash in add_implied_include Phase 1 of add_implied_include() decides whether a '\' is escaping a wildcard via !strchr("*[?", cp[1]). strchr() returns a pointer to the string literal's NUL terminator when cp[1]=='\0', so a trailing backslash matches neither branch: it is emitted into new_pat via the fall-through but backslash_cnt is not incremented. The phase-2 recurse/xfer_dirs '/**' rule then allocates arg_len + backslash_cnt + 3 + 1 and doubles every '\' in new_pat, including the uncounted trailing one, so the closing '*p = '\0'' lands one byte past the heap buffer. Reachable on a standard 'rsync --daemon' deployment (am_server==0 at the per-module parse_arguments(), so trust_sender_args stays 0) by a remote unauthenticated client that sends '-r --files-from=-' and a files-from name with both an interior and a trailing backslash (e.g. 'a\b\'). Count the trailing backslash so the allocation reserves the doubled slot. (cherry picked from commit e377e7dc4f3e752723e5fbf9623a8315034e49ab) (cherry picked from commit 355c115e8072620f89c11addc99ff55a89feb509) --- exclude.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exclude.c b/exclude.c index 95912242..8bcdec3c 100644 --- a/exclude.c +++ b/exclude.c @@ -430,7 +430,7 @@ void add_implied_include(const char *arg, int skip_daemon_module) if (cp[1] == ']') { if (!saw_wild) cp++; /* A \] in a non-wild filter causes a problem, so drop the \ . */ - } else if (!strchr("*[?", cp[1])) { + } else if (!cp[1] || !strchr("*[?", cp[1])) { backslash_cnt++; if (saw_wild) *p++ = '\\';