Merge pull request #16692 from vdemeester/16690-fix-etc-osrelease-panic

Fix panic in parsing /etc/os-release
This commit is contained in:
David Calavera 2015-11-05 15:11:02 -08:00
commit 5ecd79236b
2 changed files with 131 additions and 36 deletions

View file

@ -3,9 +3,14 @@
package operatingsystem package operatingsystem
import ( import (
"bufio"
"bytes" "bytes"
"errors" "fmt"
"io/ioutil" "io/ioutil"
"os"
"strings"
"github.com/mattn/go-shellwords"
) )
var ( var (
@ -18,15 +23,34 @@ var (
// GetOperatingSystem gets the name of the current operating system. // GetOperatingSystem gets the name of the current operating system.
func GetOperatingSystem() (string, error) { func GetOperatingSystem() (string, error) {
b, err := ioutil.ReadFile(etcOsRelease) osReleaseFile, err := os.Open(etcOsRelease)
if err != nil { if err != nil {
return "", err return "", err
} }
if i := bytes.Index(b, []byte("PRETTY_NAME")); i >= 0 { defer osReleaseFile.Close()
b = b[i+13:]
return string(b[:bytes.IndexByte(b, '"')]), nil var prettyName string
scanner := bufio.NewScanner(osReleaseFile)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "PRETTY_NAME=") {
data := strings.SplitN(line, "=", 2)
prettyNames, err := shellwords.Parse(data[1])
if err != nil {
return "", fmt.Errorf("PRETTY_NAME is invalid: %s", err.Error())
}
if len(prettyNames) != 1 {
return "", fmt.Errorf("PRETTY_NAME needs to be enclosed by quotes if they have spaces: %s", data[1])
}
prettyName = prettyNames[0]
}
} }
return "", errors.New("PRETTY_NAME not found") if prettyName != "" {
return prettyName, nil
}
// If not set, defaults to PRETTY_NAME="Linux"
// c.f. http://www.freedesktop.org/software/systemd/man/os-release.html
return "Linux", nil
} }
// IsContainerized returns true if we are running inside a container. // IsContainerized returns true if we are running inside a container.

View file

@ -10,9 +10,74 @@ import (
) )
func TestGetOperatingSystem(t *testing.T) { func TestGetOperatingSystem(t *testing.T) {
var ( var backup = etcOsRelease
backup = etcOsRelease
ubuntuTrusty = []byte(`NAME="Ubuntu" invalids := []struct {
content string
errorExpected string
}{
{
`PRETTY_NAME=Source Mage GNU/Linux
PRETTY_NAME=Ubuntu 14.04.LTS`,
"PRETTY_NAME needs to be enclosed by quotes if they have spaces: Source Mage GNU/Linux",
},
{
`PRETTY_NAME="Ubuntu Linux
PRETTY_NAME=Ubuntu 14.04.LTS`,
"PRETTY_NAME is invalid: invalid command line string",
},
{
`PRETTY_NAME=Ubuntu'
PRETTY_NAME=Ubuntu 14.04.LTS`,
"PRETTY_NAME is invalid: invalid command line string",
},
{
`PRETTY_NAME'
PRETTY_NAME=Ubuntu 14.04.LTS`,
"PRETTY_NAME needs to be enclosed by quotes if they have spaces: Ubuntu 14.04.LTS",
},
}
valids := []struct {
content string
expected string
}{
{
`NAME="Ubuntu"
PRETTY_NAME_AGAIN="Ubuntu 14.04.LTS"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
"Linux",
},
{
`NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
"Linux",
},
{
`NAME=Gentoo
ID=gentoo
PRETTY_NAME="Gentoo/Linux"
ANSI_COLOR="1;32"
HOME_URL="http://www.gentoo.org/"
SUPPORT_URL="http://www.gentoo.org/main/en/support.xml"
BUG_REPORT_URL="https://bugs.gentoo.org/"
`,
"Gentoo/Linux",
},
{
`NAME="Ubuntu"
VERSION="14.04, Trusty Tahr" VERSION="14.04, Trusty Tahr"
ID=ubuntu ID=ubuntu
ID_LIKE=debian ID_LIKE=debian
@ -20,24 +85,28 @@ PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04" VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/" HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`) BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
gentoo = []byte(`NAME=Gentoo "Ubuntu 14.04 LTS",
ID=gentoo },
PRETTY_NAME="Gentoo/Linux" {
ANSI_COLOR="1;32" `NAME="Ubuntu"
HOME_URL="http://www.gentoo.org/"
SUPPORT_URL="http://www.gentoo.org/main/en/support.xml"
BUG_REPORT_URL="https://bugs.gentoo.org/"
`)
noPrettyName = []byte(`NAME="Ubuntu"
VERSION="14.04, Trusty Tahr" VERSION="14.04, Trusty Tahr"
ID=ubuntu ID=ubuntu
ID_LIKE=debian ID_LIKE=debian
VERSION_ID="14.04" PRETTY_NAME='Ubuntu 14.04 LTS'`,
HOME_URL="http://www.ubuntu.com/" "Ubuntu 14.04 LTS",
SUPPORT_URL="http://help.ubuntu.com/" },
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`) {
) `PRETTY_NAME=Source
NAME="Source Mage"`,
"Source",
},
{
`PRETTY_NAME=Source
PRETTY_NAME="Source Mage"`,
"Source Mage",
},
}
dir := os.TempDir() dir := os.TempDir()
etcOsRelease = filepath.Join(dir, "etcOsRelease") etcOsRelease = filepath.Join(dir, "etcOsRelease")
@ -47,21 +116,23 @@ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
etcOsRelease = backup etcOsRelease = backup
}() }()
for expect, osRelease := range map[string][]byte{ for _, elt := range invalids {
"Ubuntu 14.04 LTS": ubuntuTrusty, if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil {
"Gentoo/Linux": gentoo,
"": noPrettyName,
} {
if err := ioutil.WriteFile(etcOsRelease, osRelease, 0600); err != nil {
t.Fatalf("failed to write to %s: %v", etcOsRelease, err) t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
} }
s, err := GetOperatingSystem() s, err := GetOperatingSystem()
if s != expect { if err == nil || err.Error() != elt.errorExpected {
if expect == "" { t.Fatalf("Expected an error %q, got %q (err: %v)", elt.errorExpected, s, err)
t.Fatalf("Expected error 'PRETTY_NAME not found', but got %v", err) }
} else { }
t.Fatalf("Expected '%s', but got '%s'. Err=%v", expect, s, err)
} for _, elt := range valids {
if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil {
t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
}
s, err := GetOperatingSystem()
if err != nil || s != elt.expected {
t.Fatalf("Expected %q, got %q (err: %v)", elt.expected, s, err)
} }
} }
} }