mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-09 14:50:56 +00:00
bug fix: allow folder names up to length 64 in leveldb
When extracting a folder name from the byte slices used as database keys, bytes.IndexByte() is used to find and remove trailing 0 bytes. In case the folder name is 64 bytes long, bytes.IndexByte() returns -1. Before this change, syncthing crashed in this case with an out-of-bounds slice access. The commit fixes the problem and also introduces a test case which checks for the presence of the bug.
This commit is contained in:
parent
30aabf1da9
commit
d297f9e032
@ -82,52 +82,55 @@ type dbWriter interface {
|
||||
Delete([]byte)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
keyTypeDevice (1 byte)
|
||||
folder (64 bytes)
|
||||
device (32 bytes)
|
||||
name (variable size)
|
||||
|
|
||||
scanner.File
|
||||
|
||||
keyTypeGlobal (1 byte)
|
||||
folder (64 bytes)
|
||||
name (variable size)
|
||||
|
|
||||
[]fileVersion (sorted)
|
||||
|
||||
*/
|
||||
|
||||
// deviceKey returns a byte slice encoding the following information:
|
||||
// keyTypeDevice (1 byte)
|
||||
// folder (64 bytes)
|
||||
// device (32 bytes)
|
||||
// name (variable size)
|
||||
func deviceKey(folder, device, file []byte) []byte {
|
||||
k := make([]byte, 1+64+32+len(file))
|
||||
k[0] = keyTypeDevice
|
||||
if len(folder) > 64 {
|
||||
panic("folder name too long")
|
||||
}
|
||||
copy(k[1:], []byte(folder))
|
||||
copy(k[1+64:], device[:])
|
||||
copy(k[1+64+32:], []byte(file))
|
||||
return k
|
||||
}
|
||||
|
||||
func globalKey(folder, file []byte) []byte {
|
||||
k := make([]byte, 1+64+len(file))
|
||||
k[0] = keyTypeGlobal
|
||||
copy(k[1:], []byte(folder))
|
||||
copy(k[1+64:], []byte(file))
|
||||
return k
|
||||
}
|
||||
|
||||
func deviceKeyName(key []byte) []byte {
|
||||
return key[1+64+32:]
|
||||
}
|
||||
|
||||
func deviceKeyFolder(key []byte) []byte {
|
||||
folder := key[1 : 1+64]
|
||||
izero := bytes.IndexByte(folder, 0)
|
||||
if izero < 0 {
|
||||
return folder
|
||||
}
|
||||
return folder[:izero]
|
||||
}
|
||||
|
||||
func deviceKeyDevice(key []byte) []byte {
|
||||
return key[1+64 : 1+64+32]
|
||||
}
|
||||
|
||||
// globalKey returns a byte slice encoding the following information:
|
||||
// keyTypeGlobal (1 byte)
|
||||
// folder (64 bytes)
|
||||
// name (variable size)
|
||||
func globalKey(folder, file []byte) []byte {
|
||||
k := make([]byte, 1+64+len(file))
|
||||
k[0] = keyTypeGlobal
|
||||
if len(folder) > 64 {
|
||||
panic("folder name too long")
|
||||
}
|
||||
copy(k[1:], []byte(folder))
|
||||
copy(k[1+64:], []byte(file))
|
||||
return k
|
||||
}
|
||||
|
||||
func globalKeyName(key []byte) []byte {
|
||||
return key[1+64:]
|
||||
}
|
||||
@ -135,6 +138,9 @@ func globalKeyName(key []byte) []byte {
|
||||
func globalKeyFolder(key []byte) []byte {
|
||||
folder := key[1 : 1+64]
|
||||
izero := bytes.IndexByte(folder, 0)
|
||||
if izero < 0 {
|
||||
return folder
|
||||
}
|
||||
return folder[:izero]
|
||||
}
|
||||
|
||||
|
58
internal/files/leveldb_test.go
Normal file
58
internal/files/leveldb_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package files
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDeviceKey(t *testing.T) {
|
||||
fld := []byte("folder6789012345678901234567890123456789012345678901234567890123")
|
||||
dev := []byte("device67890123456789012345678901")
|
||||
name := []byte("name")
|
||||
|
||||
key := deviceKey(fld, dev, name)
|
||||
|
||||
fld2 := deviceKeyFolder(key)
|
||||
if bytes.Compare(fld2, fld) != 0 {
|
||||
t.Errorf("wrong folder %q != %q", fld2, fld)
|
||||
}
|
||||
dev2 := deviceKeyDevice(key)
|
||||
if bytes.Compare(dev2, dev) != 0 {
|
||||
t.Errorf("wrong device %q != %q", dev2, dev)
|
||||
}
|
||||
name2 := deviceKeyName(key)
|
||||
if bytes.Compare(name2, name) != 0 {
|
||||
t.Errorf("wrong name %q != %q", name2, name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGlobalKey(t *testing.T) {
|
||||
fld := []byte("folder6789012345678901234567890123456789012345678901234567890123")
|
||||
name := []byte("name")
|
||||
|
||||
key := globalKey(fld, name)
|
||||
|
||||
fld2 := globalKeyFolder(key)
|
||||
if bytes.Compare(fld2, fld) != 0 {
|
||||
t.Errorf("wrong folder %q != %q", fld2, fld)
|
||||
}
|
||||
name2 := globalKeyName(key)
|
||||
if bytes.Compare(name2, name) != 0 {
|
||||
t.Errorf("wrong name %q != %q", name2, name)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user