From 52459de4583c15f2caf5d5d21b0fb03ed16f7850 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Mon, 27 Mar 2023 18:02:07 -0400 Subject: [PATCH] Read into a buffer of 1MB to limit reading huge files --- replacer.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/replacer.go b/replacer.go index 7fc1eabab43..fd2f67b71be 100644 --- a/replacer.go +++ b/replacer.go @@ -16,6 +16,7 @@ package caddy import ( "fmt" + "io" "net/http" "os" "path/filepath" @@ -303,14 +304,11 @@ func globalDefaultReplacements(key string) (any, bool) { } // check files - // TODO: We may want to cache the file contents in case - // this is used in a hot path in a config. But for now, - // we'll just read the file every time, the kernel will - // tend to cache the file contents for us. const filePrefix = "file." if strings.HasPrefix(key, filePrefix) { filename := key[len(filePrefix):] - body, err := os.ReadFile(filename) + maxSize := 1024 * 1024 + body, err := readFileIntoBuffer(filename, maxSize) if err != nil { wd, _ := os.Getwd() Log().Error("placeholder: failed to read file", @@ -354,6 +352,24 @@ func globalDefaultReplacements(key string) (any, bool) { return nil, false } +// readFileIntoBuffer reads the file at filePath into a size limited buffer. +func readFileIntoBuffer(filename string, size int) ([]byte, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + buffer := make([]byte, size) + n, err := file.Read(buffer) + if err != nil && err != io.EOF { + return nil, err + } + + // slice the buffer to the actual size + return buffer[:n], nil +} + // ReplacementFunc is a function that is called when a // replacement is being performed. It receives the // variable (i.e. placeholder name) and the value that