Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| ... | ... |
@@ -4,18 +4,22 @@ import ( |
| 4 | 4 |
"bufio" |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"os" |
| 7 |
- "regexp" |
|
| 8 | 7 |
"strings" |
| 9 | 8 |
) |
| 10 | 9 |
|
| 11 |
-var ( |
|
| 12 |
- // EnvironmentVariableRegexp is a regexp to validate correct environment variables |
|
| 13 |
- // Environment variables set by the user must have a name consisting solely of |
|
| 14 |
- // alphabetics, numerics, and underscores - the first of which must not be numeric. |
|
| 15 |
- EnvironmentVariableRegexp = regexp.MustCompile("^[[:alpha:]_][[:alpha:][:digit:]_]*$")
|
|
| 16 |
-) |
|
| 17 |
- |
|
| 18 | 10 |
// ParseEnvFile reads a file with environment variables enumerated by lines |
| 11 |
+// |
|
| 12 |
+// ``Environment variable names used by the utilities in the Shell and |
|
| 13 |
+// Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase |
|
| 14 |
+// letters, digits, and the '_' (underscore) from the characters defined in |
|
| 15 |
+// Portable Character Set and do not begin with a digit. *But*, other |
|
| 16 |
+// characters may be permitted by an implementation; applications shall |
|
| 17 |
+// tolerate the presence of such names.'' |
|
| 18 |
+// -- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html |
|
| 19 |
+// |
|
| 20 |
+// As of #16585, it's up to application inside docker to validate or not |
|
| 21 |
+// environment variables, that's why we just strip leading whitespace and |
|
| 22 |
+// nothing more. |
|
| 19 | 23 |
func ParseEnvFile(filename string) ([]string, error) {
|
| 20 | 24 |
fh, err := os.Open(filename) |
| 21 | 25 |
if err != nil {
|
| ... | ... |
@@ -31,11 +35,13 @@ func ParseEnvFile(filename string) ([]string, error) {
|
| 31 | 31 |
// line is not empty, and not starting with '#' |
| 32 | 32 |
if len(line) > 0 && !strings.HasPrefix(line, "#") {
|
| 33 | 33 |
data := strings.SplitN(line, "=", 2) |
| 34 |
- variable := data[0] |
|
| 35 | 34 |
|
| 36 |
- if !EnvironmentVariableRegexp.MatchString(variable) {
|
|
| 37 |
- return []string{}, ErrBadEnvVariable{fmt.Sprintf("variable '%s' is not a valid environment variable", variable)}
|
|
| 35 |
+ // trim the front of a variable, but nothing else |
|
| 36 |
+ variable := strings.TrimLeft(data[0], whiteSpaces) |
|
| 37 |
+ if strings.ContainsAny(variable, whiteSpaces) {
|
|
| 38 |
+ return []string{}, ErrBadEnvVariable{fmt.Sprintf("variable '%s' has white spaces", variable)}
|
|
| 38 | 39 |
} |
| 40 |
+ |
|
| 39 | 41 |
if len(data) > 1 {
|
| 40 | 42 |
|
| 41 | 43 |
// pass the value through, no trimming |
| ... | ... |
@@ -28,6 +28,8 @@ func TestParseEnvFileGoodFile(t *testing.T) {
|
| 28 | 28 |
# comment |
| 29 | 29 |
|
| 30 | 30 |
_foobar=foobaz |
| 31 |
+with.dots=working |
|
| 32 |
+and_underscore=working too |
|
| 31 | 33 |
` |
| 32 | 34 |
// Adding a newline + a line with pure whitespace. |
| 33 | 35 |
// This is being done like this instead of the block above |
| ... | ... |
@@ -47,6 +49,8 @@ _foobar=foobaz |
| 47 | 47 |
"foo=bar", |
| 48 | 48 |
"baz=quux", |
| 49 | 49 |
"_foobar=foobaz", |
| 50 |
+ "with.dots=working", |
|
| 51 |
+ "and_underscore=working too", |
|
| 50 | 52 |
} |
| 51 | 53 |
|
| 52 | 54 |
if !reflect.DeepEqual(lines, expectedLines) {
|
| ... | ... |
@@ -96,7 +100,7 @@ func TestParseEnvFileBadlyFormattedFile(t *testing.T) {
|
| 96 | 96 |
if _, ok := err.(ErrBadEnvVariable); !ok {
|
| 97 | 97 |
t.Fatalf("Expected a ErrBadEnvVariable, got [%v]", err)
|
| 98 | 98 |
} |
| 99 |
- expectedMessage := "poorly formatted environment: variable 'f ' is not a valid environment variable" |
|
| 99 |
+ expectedMessage := "poorly formatted environment: variable 'f ' has white spaces" |
|
| 100 | 100 |
if err.Error() != expectedMessage {
|
| 101 | 101 |
t.Fatalf("Expected [%v], got [%v]", expectedMessage, err.Error())
|
| 102 | 102 |
} |
| ... | ... |
@@ -131,7 +135,7 @@ another invalid line` |
| 131 | 131 |
if _, ok := err.(ErrBadEnvVariable); !ok {
|
| 132 | 132 |
t.Fatalf("Expected a ErrBadEnvvariable, got [%v]", err)
|
| 133 | 133 |
} |
| 134 |
- expectedMessage := "poorly formatted environment: variable 'first line' is not a valid environment variable" |
|
| 134 |
+ expectedMessage := "poorly formatted environment: variable 'first line' has white spaces" |
|
| 135 | 135 |
if err.Error() != expectedMessage {
|
| 136 | 136 |
t.Fatalf("Expected [%v], got [%v]", expectedMessage, err.Error())
|
| 137 | 137 |
} |
| ... | ... |
@@ -256,16 +256,16 @@ func validatePath(val string, validator func(string) bool) (string, error) {
|
| 256 | 256 |
} |
| 257 | 257 |
|
| 258 | 258 |
// ValidateEnv validates an environment variable and returns it. |
| 259 |
-// It uses EnvironmentVariableRegexp to ensure the name of the environment variable is valid. |
|
| 260 | 259 |
// If no value is specified, it returns the current value using os.Getenv. |
| 260 |
+// |
|
| 261 |
+// As on ParseEnvFile and related to #16585, environment variable names |
|
| 262 |
+// are not validate what so ever, it's up to application inside docker |
|
| 263 |
+// to validate them or not. |
|
| 261 | 264 |
func ValidateEnv(val string) (string, error) {
|
| 262 | 265 |
arr := strings.Split(val, "=") |
| 263 | 266 |
if len(arr) > 1 {
|
| 264 | 267 |
return val, nil |
| 265 | 268 |
} |
| 266 |
- if !EnvironmentVariableRegexp.MatchString(arr[0]) {
|
|
| 267 |
- return val, ErrBadEnvVariable{fmt.Sprintf("variable '%s' is not a valid environment variable", val)}
|
|
| 268 |
- } |
|
| 269 | 269 |
if !doesEnvExist(val) {
|
| 270 | 270 |
return val, nil |
| 271 | 271 |
} |
| ... | ... |
@@ -377,35 +377,23 @@ func TestValidateDevice(t *testing.T) {
|
| 377 | 377 |
} |
| 378 | 378 |
|
| 379 | 379 |
func TestValidateEnv(t *testing.T) {
|
| 380 |
- invalids := map[string]string{
|
|
| 381 |
- "some spaces": "poorly formatted environment: variable 'some spaces' is not a valid environment variable", |
|
| 382 |
- "asd!qwe": "poorly formatted environment: variable 'asd!qwe' is not a valid environment variable", |
|
| 383 |
- "1asd": "poorly formatted environment: variable '1asd' is not a valid environment variable", |
|
| 384 |
- "123": "poorly formatted environment: variable '123' is not a valid environment variable", |
|
| 385 |
- } |
|
| 386 | 380 |
valids := map[string]string{
|
| 387 |
- "a": "a", |
|
| 388 |
- "something": "something", |
|
| 389 |
- "_=a": "_=a", |
|
| 390 |
- "env1=value1": "env1=value1", |
|
| 391 |
- "_env1=value1": "_env1=value1", |
|
| 392 |
- "env2=value2=value3": "env2=value2=value3", |
|
| 393 |
- "env3=abc!qwe": "env3=abc!qwe", |
|
| 394 |
- "env_4=value 4": "env_4=value 4", |
|
| 395 |
- "PATH": fmt.Sprintf("PATH=%v", os.Getenv("PATH")),
|
|
| 396 |
- "PATH=something": "PATH=something", |
|
| 397 |
- } |
|
| 398 |
- for value, expectedError := range invalids {
|
|
| 399 |
- _, err := ValidateEnv(value) |
|
| 400 |
- if err == nil {
|
|
| 401 |
- t.Fatalf("Expected ErrBadEnvVariable, got nothing")
|
|
| 402 |
- } |
|
| 403 |
- if _, ok := err.(ErrBadEnvVariable); !ok {
|
|
| 404 |
- t.Fatalf("Expected ErrBadEnvVariable, got [%s]", err)
|
|
| 405 |
- } |
|
| 406 |
- if err.Error() != expectedError {
|
|
| 407 |
- t.Fatalf("Expected ErrBadEnvVariable with message [%s], got [%s]", expectedError, err.Error())
|
|
| 408 |
- } |
|
| 381 |
+ "a": "a", |
|
| 382 |
+ "something": "something", |
|
| 383 |
+ "_=a": "_=a", |
|
| 384 |
+ "env1=value1": "env1=value1", |
|
| 385 |
+ "_env1=value1": "_env1=value1", |
|
| 386 |
+ "env2=value2=value3": "env2=value2=value3", |
|
| 387 |
+ "env3=abc!qwe": "env3=abc!qwe", |
|
| 388 |
+ "env_4=value 4": "env_4=value 4", |
|
| 389 |
+ "PATH": fmt.Sprintf("PATH=%v", os.Getenv("PATH")),
|
|
| 390 |
+ "PATH=something": "PATH=something", |
|
| 391 |
+ "asd!qwe": "asd!qwe", |
|
| 392 |
+ "1asd": "1asd", |
|
| 393 |
+ "123": "123", |
|
| 394 |
+ "some space": "some space", |
|
| 395 |
+ " some space before": " some space before", |
|
| 396 |
+ "some space after ": "some space after ", |
|
| 409 | 397 |
} |
| 410 | 398 |
for value, expected := range valids {
|
| 411 | 399 |
actual, err := ValidateEnv(value) |