Skip to content

Commit

Permalink
caddyfile: Copy input before parsing (fix #4422)
Browse files Browse the repository at this point in the history
  • Loading branch information
mholt committed Nov 15, 2021
1 parent e81369e commit b47af6e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 16 deletions.
5 changes: 5 additions & 0 deletions caddyconfig/caddyfile/formatter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ d {
{$F}
}`,
},
{
description: "env var placeholders with port",
input: `:{$PORT}`,
expect: `:{$PORT}`,
},
{
description: "comments",
input: `#a "\n"
Expand Down
39 changes: 23 additions & 16 deletions caddyconfig/caddyfile/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit b47af6e

Please sign in to comment.