lib/config: Reject empty folder IDs

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4698
LGTM: imsodin
This commit is contained in:
Jakob Borg 2018-01-27 09:06:37 +00:00
parent 20e05cdcd0
commit e0931e201e
2 changed files with 47 additions and 5 deletions

View File

@ -260,6 +260,10 @@ func (cfg *Configuration) clean() error {
folder := &cfg.Folders[i] folder := &cfg.Folders[i]
folder.prepare() folder.prepare()
if folder.ID == "" {
return fmt.Errorf("folder with empty ID in configuration")
}
if _, ok := seenFolders[folder.ID]; ok { if _, ok := seenFolders[folder.ID]; ok {
return fmt.Errorf("duplicate folder ID %q in configuration", folder.ID) return fmt.Errorf("duplicate folder ID %q in configuration", folder.ID)
} }

View File

@ -872,7 +872,7 @@ func TestIssue4219(t *testing.T) {
func TestInvalidDeviceIDRejected(t *testing.T) { func TestInvalidDeviceIDRejected(t *testing.T) {
// This test verifies that we properly reject invalid device IDs when // This test verifies that we properly reject invalid device IDs when
// deserializing a JSON config from the API. // deserializing a JSON config.
cases := []struct { cases := []struct {
id string id string
@ -894,7 +894,7 @@ func TestInvalidDeviceIDRejected(t *testing.T) {
cfg := defaultConfigAsMap() cfg := defaultConfigAsMap()
// Change the device ID of the first device to "invalid". Fast and loose // Change the device ID of the first device to "invalid". Fast and loose
// with the type assertions as we know what the JSON decoder does. // with the type assertions as we know what the JSON decoder returns.
devs := cfg["devices"].([]interface{}) devs := cfg["devices"].([]interface{})
dev0 := devs[0].(map[string]interface{}) dev0 := devs[0].(map[string]interface{})
dev0["deviceID"] = tc.id dev0["deviceID"] = tc.id
@ -907,21 +907,59 @@ func TestInvalidDeviceIDRejected(t *testing.T) {
_, err = ReadJSON(bytes.NewReader(invalidJSON), device1) _, err = ReadJSON(bytes.NewReader(invalidJSON), device1)
if tc.ok && err != nil { if tc.ok && err != nil {
if err != nil { t.Errorf("unexpected error for device ID %q: %v", tc.id, err)
t.Errorf("unexpected error for device ID %q: %v", tc.id, err)
}
} else if !tc.ok && err == nil { } else if !tc.ok && err == nil {
t.Errorf("device ID %q, expected error but got nil", tc.id) t.Errorf("device ID %q, expected error but got nil", tc.id)
} }
} }
} }
func TestInvalidFolderIDRejected(t *testing.T) {
// This test verifies that we properly reject invalid folder IDs when
// deserializing a JSON config.
cases := []struct {
id string
ok bool
}{
// a reasonable folder ID
{"foo", true},
// empty is not OK
{"", false},
}
for _, tc := range cases {
cfg := defaultConfigAsMap()
// Change the folder ID of the first folder to the empty string.
// Fast and loose with the type assertions as we know what the JSON
// decoder returns.
devs := cfg["folders"].([]interface{})
dev0 := devs[0].(map[string]interface{})
dev0["id"] = tc.id
devs[0] = dev0
invalidJSON, err := json.Marshal(cfg)
if err != nil {
t.Fatal(err)
}
_, err = ReadJSON(bytes.NewReader(invalidJSON), device1)
if tc.ok && err != nil {
t.Errorf("unexpected error for folder ID %q: %v", tc.id, err)
} else if !tc.ok && err == nil {
t.Errorf("folder ID %q, expected error but got nil", tc.id)
}
}
}
// defaultConfigAsMap returns a valid default config as a JSON-decoded // defaultConfigAsMap returns a valid default config as a JSON-decoded
// map[string]interface{}. This is useful to override random elements and // map[string]interface{}. This is useful to override random elements and
// re-encode into JSON. // re-encode into JSON.
func defaultConfigAsMap() map[string]interface{} { func defaultConfigAsMap() map[string]interface{} {
cfg := New(device1) cfg := New(device1)
cfg.Devices = append(cfg.Devices, NewDeviceConfiguration(device2, "name")) cfg.Devices = append(cfg.Devices, NewDeviceConfiguration(device2, "name"))
cfg.Folders = append(cfg.Folders, NewFolderConfiguration(device1, "default", "default", fs.FilesystemTypeBasic, "/tmp"))
bs, err := json.Marshal(cfg) bs, err := json.Marshal(cfg)
if err != nil { if err != nil {
// can't happen // can't happen