Skip to content

Commit 9507303

Browse files
committed
Fix bug with validing remote filter rules.
1 parent 81c5c81 commit 9507303

3 files changed

Lines changed: 23 additions & 15 deletions

File tree

exclude.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ static filter_rule **mergelist_parents;
7878
static int mergelist_cnt = 0;
7979
static int mergelist_size = 0;
8080

81+
#define LOCAL_RULE 1
82+
#define REMOTE_RULE 2
83+
static uchar cur_elide_value = REMOTE_RULE;
84+
8185
/* Each filter_list_struct describes a singly-linked list by keeping track
8286
* of both the head and tail pointers. The list is slightly unusual in that
8387
* 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 *listp, const char *pat, unsigned int pat_
220224
slash_cnt++;
221225
}
222226
}
227+
rule->elide = 0;
223228
strlcpy(rule->pattern + pre_len, pat, pat_len + 1);
224229
pat_len += pre_len;
225230
if (suf_len) {
@@ -900,7 +905,7 @@ static int rule_matches(const char *fname, filter_rule *ex, int name_flags)
900905
const char *strings[16]; /* more than enough */
901906
const char *name = fname + (*fname == '/');
902907

903-
if (!*name)
908+
if (!*name || ex->elide == cur_elide_value)
904909
return 0;
905910

906911
if (!(name_flags & NAME_IS_XATTR) ^ !(ex->rflags & FILTRULE_XATTR))
@@ -1016,6 +1021,15 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level)
10161021
return 0;
10171022
}
10181023

1024+
int check_server_filter(filter_rule_list *listp, enum logcode code, const char *name, int name_flags)
1025+
{
1026+
int ret;
1027+
cur_elide_value = LOCAL_RULE;
1028+
ret = check_filter(listp, code, name, name_flags);
1029+
cur_elide_value = REMOTE_RULE;
1030+
return ret;
1031+
}
1032+
10191033
/* Return -1 if file "name" is defined to be excluded by the specified
10201034
* exclude list, 1 if it is included, and 0 if it was not matched. */
10211035
int check_filter(filter_rule_list *listp, enum logcode code,
@@ -1571,7 +1585,7 @@ char *get_rule_prefix(filter_rule *rule, const char *pat, int for_xfer,
15711585

15721586
static void send_rules(int f_out, filter_rule_list *flp)
15731587
{
1574-
filter_rule *ent, *prev = NULL;
1588+
filter_rule *ent;
15751589

15761590
for (ent = flp->head; ent; ent = ent->next) {
15771591
unsigned int len, plen, dlen;
@@ -1586,21 +1600,15 @@ static void send_rules(int f_out, filter_rule_list *flp)
15861600
* merge files as an optimization (since they can only have
15871601
* include/exclude rules). */
15881602
if (ent->rflags & FILTRULE_SENDER_SIDE)
1589-
elide = am_sender ? 1 : -1;
1603+
elide = am_sender ? LOCAL_RULE : REMOTE_RULE;
15901604
if (ent->rflags & FILTRULE_RECEIVER_SIDE)
1591-
elide = elide ? 0 : am_sender ? -1 : 1;
1605+
elide = elide ? 0 : am_sender ? REMOTE_RULE : LOCAL_RULE;
15921606
else if (delete_excluded && !elide
15931607
&& (!(ent->rflags & FILTRULE_PERDIR_MERGE)
15941608
|| ent->rflags & FILTRULE_NO_PREFIXES))
1595-
elide = am_sender ? 1 : -1;
1596-
if (elide < 0) {
1597-
if (prev)
1598-
prev->next = ent->next;
1599-
else
1600-
flp->head = ent->next;
1601-
} else
1602-
prev = ent;
1603-
if (elide > 0)
1609+
elide = am_sender ? LOCAL_RULE : REMOTE_RULE;
1610+
ent->elide = elide;
1611+
if (elide == LOCAL_RULE)
16041612
continue;
16051613
if (ent->rflags & FILTRULE_CVS_IGNORE
16061614
&& !(ent->rflags & FILTRULE_MERGE_FILE)) {
@@ -1628,7 +1636,6 @@ static void send_rules(int f_out, filter_rule_list *flp)
16281636
if (dlen)
16291637
write_byte(f_out, '/');
16301638
}
1631-
flp->tail = prev;
16321639
}
16331640

16341641
/* This is only called by the client. */

flist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
991991
if (*thisname != '.' || thisname[1] != '\0') {
992992
int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE;
993993
if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */
994-
&& filter_list.head && check_filter(&filter_list, FINFO, thisname, filt_flags) < 0) {
994+
&& filter_list.head && check_server_filter(&filter_list, FINFO, thisname, filt_flags) < 0) {
995995
rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname);
996996
exit_cleanup(RERR_PROTOCOL);
997997
}

rsync.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,7 @@ typedef struct filter_struct {
10241024
int slash_cnt;
10251025
struct filter_list_struct *mergelist;
10261026
} u;
1027+
uchar elide;
10271028
} filter_rule;
10281029

10291030
typedef struct filter_list_struct {

0 commit comments

Comments
 (0)