summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2021-11-15 14:41:19 -0700
committerMatthew Holt <mholt@users.noreply.github.com>2021-11-15 14:41:19 -0700
commitb47af6ef04f818f41932e4152836d43a9be8fe07 (patch)
treecb765ed2842b58ef954f741e95174b0053021ec0
parente81369e2208e47d9650f9699ad8bc7692640b275 (diff)
caddyfile: Copy input before parsing (fix #4422)
-rw-r--r--caddyconfig/caddyfile/formatter_test.go5
-rwxr-xr-xcaddyconfig/caddyfile/parse.go39
2 files changed, 28 insertions, 16 deletions
diff --git a/caddyconfig/caddyfile/formatter_test.go b/caddyconfig/caddyfile/formatter_test.go
index 64cf6d2..8e5b368 100644
--- a/caddyconfig/caddyfile/formatter_test.go
+++ b/caddyconfig/caddyfile/formatter_test.go
@@ -180,6 +180,11 @@ d {
}`,
},
{
+ description: "env var placeholders with port",
+ input: `:{$PORT}`,
+ expect: `:{$PORT}`,
+ },
+ {
description: "comments",
input: `#a "\n"
diff --git a/caddyconfig/caddyfile/parse.go b/caddyconfig/caddyfile/parse.go
index 8591759..1e694f9 100755
--- a/caddyconfig/caddyfile/parse.go
+++ b/caddyconfig/caddyfile/parse.go
@@ -37,7 +37,13 @@ import (
// Environment variables in {$ENVIRONMENT_VARIABLE} notation
// will be replaced before parsing begins.
func Parse(filename string, input []byte) ([]ServerBlock, error) {
- tokens, err := allTokens(filename, input)
+ // unfortunately, we must copy the input because parsing must
+ // remain a read-only operation, but we have to expand environment
+ // variables before we parse, which changes the underlying array (#4422)
+ inputCopy := make([]byte, len(input))
+ copy(inputCopy, input)
+
+ tokens, err := allTokens(filename, inputCopy)
if err != nil {
return nil, err
}
@@ -51,7 +57,23 @@ func Parse(filename string, input []byte) ([]ServerBlock, error) {
return p.parseAll()
}
+// allTokens lexes the entire input, but does not parse it.
+// It returns all the tokens from the input, unstructured
+// and in order. It may mutate input as it expands env vars.
+func allTokens(filename string, input []byte) ([]Token, error) {
+ inputCopy, err := replaceEnvVars(input)
+ if err != nil {
+ return nil, err
+ }
+ tokens, err := Tokenize(inputCopy, filename)
+ if err != nil {
+ return nil, err
+ }
+ return tokens, nil
+}
+
// replaceEnvVars replaces all occurrences of environment variables.
+// It mutates the underlying array and returns the updated slice.
func replaceEnvVars(input []byte) ([]byte, error) {
var offset int
for {
@@ -96,21 +118,6 @@ func replaceEnvVars(input []byte) ([]byte, error) {
return input, nil
}
-// allTokens lexes the entire input, but does not parse it.
-// It returns all the tokens from the input, unstructured
-// and in order.
-func allTokens(filename string, input []byte) ([]Token, error) {
- input, err := replaceEnvVars(input)
- if err != nil {
- return nil, err
- }
- tokens, err := Tokenize(input, filename)
- if err != nil {
- return nil, err
- }
- return tokens, nil
-}
-
type parser struct {
*Dispenser
block ServerBlock // current server block being parsed