ipn: make LoadPrefs return os.ErrNotExist when reading corrupted files

It appears some users have corrupted pref.conf files. Have LoadPrefs
treat these files as non-existent. This way tailscale will make user
login, and not crash.

Fixes #954

Signed-off-by: Alex Brainman <alex.brainman@gmail.com>
josh/no-goroutine-per-udp-read-2
Alex Brainman 2020-11-22 11:34:26 +11:00 committed by Brad Fitzpatrick
parent 2c48b4ee14
commit 72e082aaf5
2 changed files with 27 additions and 0 deletions

View File

@ -5,6 +5,7 @@
package ipn package ipn
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -276,6 +277,9 @@ func LoadPrefs(filename string) (*Prefs, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("LoadPrefs open: %w", err) // err includes path return nil, fmt.Errorf("LoadPrefs open: %w", err) // err includes path
} }
if bytes.Contains(data, jsonEscapedZero) {
return nil, os.ErrNotExist
}
p, err := PrefsFromBytes(data, false) p, err := PrefsFromBytes(data, false)
if err != nil { if err != nil {
return nil, fmt.Errorf("LoadPrefs(%q) decode: %w", filename, err) return nil, fmt.Errorf("LoadPrefs(%q) decode: %w", filename, err)

View File

@ -7,6 +7,7 @@ package ipn
import ( import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"reflect" "reflect"
"testing" "testing"
@ -371,3 +372,25 @@ func TestLoadPrefsNotExist(t *testing.T) {
} }
t.Fatalf("unexpected prefs=%#v, err=%v", p, err) t.Fatalf("unexpected prefs=%#v, err=%v", p, err)
} }
// TestLoadPrefsFileWithZeroInIt verifies that LoadPrefs hanldes corrupted input files.
// See issue #954 for details.
func TestLoadPrefsFileWithZeroInIt(t *testing.T) {
f, err := ioutil.TempFile("", "TestLoadPrefsFileWithZeroInIt")
if err != nil {
t.Fatal(err)
}
path := f.Name()
if _, err := f.Write(jsonEscapedZero); err != nil {
t.Fatal(err)
}
f.Close()
defer os.Remove(path)
p, err := LoadPrefs(path)
if errors.Is(err, os.ErrNotExist) {
// expected.
return
}
t.Fatalf("unexpected prefs=%#v, err=%v", p, err)
}