Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 01:30 UTC
templates: fix inconsistent nested includes (#4452)
Tim Culverhouse committed
Nov 29, 2021 at 11:29 UTC
ec14ccdd4075e46dd0235cc99ecfd92ed131c10a
3 files changed
+109
-12
modules/caddyhttp/templates/frontmatter_fuzz.go
+1
@@ -12,6 +12,7 @@
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
+//go:build gofuzz
16
// +build gofuzz
17
18
package templates
modules/caddyhttp/templates/tplcontext.go
+18
-12
@@ -91,7 +91,12 @@ func (c TemplateContext) OriginalReq() http.Request {
91
// trusted files. If it is not trusted, be sure to use escaping functions
92
// in your template.
93
func (c TemplateContext) funcInclude(filename string, args ...interface{}) (string, error) {
94
- bodyBuf, err := c.readFileToBuffer(filename)
94
+
95
+ bodyBuf := bufPool.Get().(*bytes.Buffer)
96
+ bodyBuf.Reset()
97
+ defer bufPool.Put(bodyBuf)
98
+
99
+ err := c.readFileToBuffer(filename, bodyBuf)
100
101
if err != nil {
102
return "", err
@@ -107,28 +112,24 @@ func (c TemplateContext) funcInclude(filename string, args ...interface{}) (stri
112
return bodyBuf.String(), nil
113
}
114
110
-// readFileToBuffer returns the contents of filename relative to root as a buffer
111
-func (c TemplateContext) readFileToBuffer(filename string) (*bytes.Buffer, error) {
115
+// readFileToBuffer reads a file into a buffer
116
+func (c TemplateContext) readFileToBuffer(filename string, bodyBuf *bytes.Buffer) error {
117
if c.Root == nil {
113
- return nil, fmt.Errorf("root file system not specified")
118
+ return fmt.Errorf("root file system not specified")
119
}
120
121
file, err := c.Root.Open(filename)
122
if err != nil {
118
- return nil, err
123
+ return err
124
}
125
defer file.Close()
126
122
- bodyBuf := bufPool.Get().(*bytes.Buffer)
123
- bodyBuf.Reset()
124
- defer bufPool.Put(bodyBuf)
125
-
127
_, err = io.Copy(bodyBuf, file)
128
if err != nil {
128
- return nil, err
129
+ return err
130
}
131
131
- return bodyBuf, nil
132
+ return nil
133
}
134
135
// funcHTTPInclude returns the body of a virtual (lightweight) request
@@ -185,7 +186,12 @@ func (c TemplateContext) funcHTTPInclude(uri string) (string, error) {
186
// {{ template }} from the standard template library. If the imported file has
187
// no {{ define }} blocks, the name of the import will be the path
188
func (c *TemplateContext) funcImport(filename string) (string, error) {
188
- bodyBuf, err := c.readFileToBuffer(filename)
189
+
190
+ bodyBuf := bufPool.Get().(*bytes.Buffer)
191
+ bodyBuf.Reset()
192
+ defer bufPool.Put(bodyBuf)
193
+
194
+ err := c.readFileToBuffer(filename, bodyBuf)
195
if err != nil {
196
return "", err
197
}
modules/caddyhttp/templates/tplcontext_test.go
+90
@@ -18,6 +18,7 @@ import (
18
"bytes"
19
"context"
20
"fmt"
21
+ "io/ioutil"
22
"net/http"
23
"os"
24
"path/filepath"
@@ -187,6 +188,95 @@ func TestImport(t *testing.T) {
188
}
189
}
190
191
+func TestNestedInclude(t *testing.T) {
192
+ for i, test := range []struct {
193
+ child string
194
+ childFile string
195
+ parent string
196
+ parentFile string
197
+ shouldErr bool
198
+ expect string
199
+ child2 string
200
+ child2File string
201
+ }{
202
+ {
203
+ // include in parent
204
+ child: `{{ include "file1" }}`,
205
+ childFile: "file0",
206
+ parent: `{{ $content := "file2" }}{{ $p := include $content}}`,
207
+ parentFile: "file1",
208
+ shouldErr: false,
209
+ expect: ``,
210
+ child2: `This shouldn't show`,
211
+ child2File: "file2",
212
+ },
213
+ } {
214
+ context := getContextOrFail(t)
215
+ var absFilePath string
216
+ var absFilePath0 string
217
+ var absFilePath1 string
218
+ var buf *bytes.Buffer
219
+ var err error
220
+
221
+ // create files and for test case
222
+ if test.parentFile != "" {
223
+ absFilePath = filepath.Join(fmt.Sprintf("%s", context.Root), test.parentFile)
224
+ if err := ioutil.WriteFile(absFilePath, []byte(test.parent), os.ModePerm); err != nil {
225
+ os.Remove(absFilePath)
226
+ t.Fatalf("Test %d: Expected no error creating file, got: '%s'", i, err.Error())
227
+ }
228
+ }
229
+ if test.childFile != "" {
230
+ absFilePath0 = filepath.Join(fmt.Sprintf("%s", context.Root), test.childFile)
231
+ if err := ioutil.WriteFile(absFilePath0, []byte(test.child), os.ModePerm); err != nil {
232
+ os.Remove(absFilePath0)
233
+ t.Fatalf("Test %d: Expected no error creating file, got: '%s'", i, err.Error())
234
+ }
235
+ }
236
+ if test.child2File != "" {
237
+ absFilePath1 = filepath.Join(fmt.Sprintf("%s", context.Root), test.child2File)
238
+ if err := ioutil.WriteFile(absFilePath1, []byte(test.child2), os.ModePerm); err != nil {
239
+ os.Remove(absFilePath0)
240
+ t.Fatalf("Test %d: Expected no error creating file, got: '%s'", i, err.Error())
241
+ }
242
+ }
243
+
244
+ buf = bufPool.Get().(*bytes.Buffer)
245
+ buf.Reset()
246
+ defer bufPool.Put(buf)
247
+ buf.WriteString(test.child)
248
+ err = context.executeTemplateInBuffer(test.childFile, buf)
249
+
250
+ if err != nil {
251
+ if !test.shouldErr {
252
+ t.Errorf("Test %d: Expected no error, got: '%s'", i, err)
253
+ }
254
+ } else if test.shouldErr {
255
+ t.Errorf("Test %d: Expected error but had none", i)
256
+ } else if buf.String() != test.expect {
257
+ //
258
+ t.Errorf("Test %d: Expected '%s' but got '%s'", i, test.expect, buf.String())
259
+
260
+ }
261
+
262
+ if absFilePath != "" {
263
+ if err := os.Remove(absFilePath); err != nil && !os.IsNotExist(err) {
264
+ t.Fatalf("Test %d: Expected no error removing temporary test file, got: %v", i, err)
265
+ }
266
+ }
267
+ if absFilePath0 != "" {
268
+ if err := os.Remove(absFilePath0); err != nil && !os.IsNotExist(err) {
269
+ t.Fatalf("Test %d: Expected no error removing temporary test file, got: %v", i, err)
270
+ }
271
+ }
272
+ if absFilePath1 != "" {
273
+ if err := os.Remove(absFilePath1); err != nil && !os.IsNotExist(err) {
274
+ t.Fatalf("Test %d: Expected no error removing temporary test file, got: %v", i, err)
275
+ }
276
+ }
277
+ }
278
+}
279
+
280
func TestInclude(t *testing.T) {
281
for i, test := range []struct {
282
fileContent string