--- rsync-2.6.9/generator.c~ 2006-10-23 08:06:36.000000000 +0930 +++ rsync-2.6.9/generator.c 2007-08-02 15:52:33.000000000 +0930 @@ -226,8 +226,13 @@ int dlen, i; if (!flist) { - while (cur_depth >= min_depth) - pop_local_filters(filt_array[cur_depth--]); + while (cur_depth >= min_depth) { + if (filt_array[cur_depth]) { /* check (a) */ + pop_local_filters(filt_array[cur_depth]); + filt_array[cur_depth]=NULL; + } + cur_depth--; + } min_depth = MAXPATHLEN; cur_depth = -1; return; @@ -251,8 +256,26 @@ return; } - while (cur_depth >= file->dir.depth && cur_depth >= min_depth) - pop_local_filters(filt_array[cur_depth--]); + while (cur_depth >= file->dir.depth && cur_depth >= min_depth) { + if (filt_array[cur_depth]) { /* check (b) */ + pop_local_filters(filt_array[cur_depth]); + filt_array[cur_depth]=NULL; + } + cur_depth--; + } + + /* If checks (a) and (b) above were absent, the following invariant + must hold so proper cleanup can be performed in pop_local_filters. + However, this is a dirty fix, since this invariant being violated + implies that local filters in some parent directories of dname/dlen + have been skipped. */ + if(cur_depth >= 0 && file->dir.depth > cur_depth+1) { + rprintf(FINFO, + "Some local filters may have been skipped -- skipping file deletion\n"); + return; + } + /* assume: cur_depth < 0 || file->dir.depth <= cur_depth+1 */ + cur_depth = file->dir.depth; if (min_depth > cur_depth) min_depth = cur_depth;