From d9222578eebc31715950b18b17d8234393941608 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sat, 16 May 2020 22:59:54 +0200 Subject: [PATCH] lib/model: Don't crash when taking rename shortcut (fixes #6654) If we fail to take the rename shortcut we may crash on a later loop, because we do trickiness with the indexes but the original buckets[key] in "range buckets[key]" isn't re-evaluated so i exceeds the max index. --- lib/model/folder_sendrecv.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index f50c0bea29c..add5d1dd6c7 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -460,12 +460,7 @@ nextFile: // Check our list of files to be removed for a match, in which case // we can just do a rename instead. key := string(fi.BlocksHash) - for i, candidate := range buckets[key] { - // Remove the candidate from the bucket - lidx := len(buckets[key]) - 1 - buckets[key][i] = buckets[key][lidx] - buckets[key] = buckets[key][:lidx] - + for candidate, ok := popCandidate(buckets, key); ok; candidate, ok = popCandidate(buckets, key) { // candidate is our current state of the file, where as the // desired state with the delete bit set is in the deletion // map. @@ -498,6 +493,16 @@ nextFile: return changed, fileDeletions, dirDeletions, nil } +func popCandidate(buckets map[string][]protocol.FileInfo, key string) (protocol.FileInfo, bool) { + cands := buckets[key] + if len(cands) == 0 { + return protocol.FileInfo{}, false + } + + buckets[key] = cands[1:] + return cands[0], true +} + func (f *sendReceiveFolder) processDeletions(fileDeletions map[string]protocol.FileInfo, dirDeletions []protocol.FileInfo, snap *db.Snapshot, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string) { for _, file := range fileDeletions { select {