+++ /dev/null
-From 950730313de994d191ba2d5be575e97690b355e8 Mon Sep 17 00:00:00 2001
-From: Wayne Davison <wayne@opencoder.net>
-Date: Mon, 12 Sep 2022 22:02:00 -0700
-Subject: [PATCH] Fix bug with validing remote filter rules.
-
----
- exclude.c | 35 +++++++++++++++++++++--------------
- flist.c | 2 +-
- rsync.h | 1 +
- 3 files changed, 23 insertions(+), 15 deletions(-)
-
---- a/exclude.c
-+++ b/exclude.c
-@@ -78,6 +78,10 @@ static filter_rule **mergelist_parents;
- static int mergelist_cnt = 0;
- static int mergelist_size = 0;
-
-+#define LOCAL_RULE 1
-+#define REMOTE_RULE 2
-+static uchar cur_elide_value = REMOTE_RULE;
-+
- /* Each filter_list_struct describes a singly-linked list by keeping track
- * of both the head and tail pointers. The list is slightly unusual in that
- * a parent-dir's content can be appended to the end of the local list in a
-@@ -220,6 +224,7 @@ static void add_rule(filter_rule_list *l
- slash_cnt++;
- }
- }
-+ rule->elide = 0;
- strlcpy(rule->pattern + pre_len, pat, pat_len + 1);
- pat_len += pre_len;
- if (suf_len) {
-@@ -900,7 +905,7 @@ static int rule_matches(const char *fnam
- const char *strings[16]; /* more than enough */
- const char *name = fname + (*fname == '/');
-
-- if (!*name)
-+ if (!*name || ex->elide == cur_elide_value)
- return 0;
-
- if (!(name_flags & NAME_IS_XATTR) ^ !(ex->rflags & FILTRULE_XATTR))
-@@ -1016,6 +1021,15 @@ int name_is_excluded(const char *fname,
- return 0;
- }
-
-+int check_server_filter(filter_rule_list *listp, enum logcode code, const char *name, int name_flags)
-+{
-+ int ret;
-+ cur_elide_value = LOCAL_RULE;
-+ ret = check_filter(listp, code, name, name_flags);
-+ cur_elide_value = REMOTE_RULE;
-+ return ret;
-+}
-+
- /* Return -1 if file "name" is defined to be excluded by the specified
- * exclude list, 1 if it is included, and 0 if it was not matched. */
- int check_filter(filter_rule_list *listp, enum logcode code,
-@@ -1571,7 +1585,7 @@ char *get_rule_prefix(filter_rule *rule,
-
- static void send_rules(int f_out, filter_rule_list *flp)
- {
-- filter_rule *ent, *prev = NULL;
-+ filter_rule *ent;
-
- for (ent = flp->head; ent; ent = ent->next) {
- unsigned int len, plen, dlen;
-@@ -1586,21 +1600,15 @@ static void send_rules(int f_out, filter
- * merge files as an optimization (since they can only have
- * include/exclude rules). */
- if (ent->rflags & FILTRULE_SENDER_SIDE)
-- elide = am_sender ? 1 : -1;
-+ elide = am_sender ? LOCAL_RULE : REMOTE_RULE;
- if (ent->rflags & FILTRULE_RECEIVER_SIDE)
-- elide = elide ? 0 : am_sender ? -1 : 1;
-+ elide = elide ? 0 : am_sender ? REMOTE_RULE : LOCAL_RULE;
- else if (delete_excluded && !elide
- && (!(ent->rflags & FILTRULE_PERDIR_MERGE)
- || ent->rflags & FILTRULE_NO_PREFIXES))
-- elide = am_sender ? 1 : -1;
-- if (elide < 0) {
-- if (prev)
-- prev->next = ent->next;
-- else
-- flp->head = ent->next;
-- } else
-- prev = ent;
-- if (elide > 0)
-+ elide = am_sender ? LOCAL_RULE : REMOTE_RULE;
-+ ent->elide = elide;
-+ if (elide == LOCAL_RULE)
- continue;
- if (ent->rflags & FILTRULE_CVS_IGNORE
- && !(ent->rflags & FILTRULE_MERGE_FILE)) {
-@@ -1628,7 +1636,6 @@ static void send_rules(int f_out, filter
- if (dlen)
- write_byte(f_out, '/');
- }
-- flp->tail = prev;
- }
-
- /* This is only called by the client. */
---- a/flist.c
-+++ b/flist.c
-@@ -989,7 +989,7 @@ static struct file_struct *recv_file_ent
- if (*thisname != '.' || thisname[1] != '\0') {
- int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE;
- if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */
-- && filter_list.head && check_filter(&filter_list, FINFO, thisname, filt_flags) < 0) {
-+ && filter_list.head && check_server_filter(&filter_list, FINFO, thisname, filt_flags) < 0) {
- rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname);
- exit_cleanup(RERR_PROTOCOL);
- }
---- a/rsync.h
-+++ b/rsync.h
-@@ -1023,6 +1023,7 @@ typedef struct filter_struct {
- int slash_cnt;
- struct filter_list_struct *mergelist;
- } u;
-+ uchar elide;
- } filter_rule;
-
- typedef struct filter_list_struct {