From e7a534d0a311d9fa75b5981879c755281c4c9fba Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Sun, 11 Feb 2024 13:30:14 -0500 Subject: [PATCH] caddyfile: Reject long heredoc markers (#6098) Co-authored-by: Mohammed Al Sahaf --- caddyconfig/caddyfile/formatter.go | 5 +++ caddyconfig/caddyfile/formatter_test.go | 41 +++++++++++++----- caddyconfig/caddyfile/lexer.go | 4 ++ ...ase-minimized-fuzz-format-5806400649363456 | Bin 0 -> 139348 bytes 4 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 caddyconfig/caddyfile/testdata/clusterfuzz-testcase-minimized-fuzz-format-5806400649363456 diff --git a/caddyconfig/caddyfile/formatter.go b/caddyconfig/caddyfile/formatter.go index 764f79118..423de542a 100644 --- a/caddyconfig/caddyfile/formatter.go +++ b/caddyconfig/caddyfile/formatter.go @@ -16,6 +16,7 @@ package caddyfile import ( "bytes" + "fmt" "io" "unicode" @@ -118,6 +119,10 @@ func Format(input []byte) []byte { heredoc = heredocClosed } else { heredocMarker = append(heredocMarker, ch) + if len(heredocMarker) > 32 { + errorString := fmt.Sprintf("heredoc marker too long: <<%s", string(heredocMarker)) + panic(errorString) + } write(ch) continue } diff --git a/caddyconfig/caddyfile/formatter_test.go b/caddyconfig/caddyfile/formatter_test.go index 6eec822fe..5ea29c335 100644 --- a/caddyconfig/caddyfile/formatter_test.go +++ b/caddyconfig/caddyfile/formatter_test.go @@ -15,6 +15,8 @@ package caddyfile import ( + "fmt" + "os" "strings" "testing" ) @@ -24,6 +26,7 @@ func TestFormatter(t *testing.T) { description string input string expect string + panics bool }{ { description: "very simple", @@ -434,18 +437,36 @@ block2 { } `, }, + { + description: "very long heredoc from fuzzer", + input: func() string { + bs, _ := os.ReadFile("testdata/clusterfuzz-testcase-minimized-fuzz-format-5806400649363456") + return string(bs) + }(), + panics: true, + }, } { - // the formatter should output a trailing newline, - // even if the tests aren't written to expect that - if !strings.HasSuffix(tc.expect, "\n") { - tc.expect += "\n" - } + t.Run(fmt.Sprintf("test case %d: %s", i, tc.description), func(t *testing.T) { + if tc.panics { + defer func() { + if r := recover(); r == nil { + t.Errorf("[TEST %d: %s] Expected panic, but got none", i, tc.description) + } + }() + } - actual := Format([]byte(tc.input)) + // the formatter should output a trailing newline, + // even if the tests aren't written to expect that + if !strings.HasSuffix(tc.expect, "\n") { + tc.expect += "\n" + } - if string(actual) != tc.expect { - t.Errorf("\n[TEST %d: %s]\n====== EXPECTED ======\n%s\n====== ACTUAL ======\n%s^^^^^^^^^^^^^^^^^^^^^", - i, tc.description, string(tc.expect), string(actual)) - } + actual := Format([]byte(tc.input)) + + if !tc.panics && string(actual) != tc.expect { + t.Errorf("\n[TEST %d: %s]\n====== EXPECTED ======\n%s\n====== ACTUAL ======\n%s^^^^^^^^^^^^^^^^^^^^^", + i, tc.description, string(tc.expect), string(actual)) + } + }) } } diff --git a/caddyconfig/caddyfile/lexer.go b/caddyconfig/caddyfile/lexer.go index 4db63749b..a59f0fc46 100644 --- a/caddyconfig/caddyfile/lexer.go +++ b/caddyconfig/caddyfile/lexer.go @@ -149,6 +149,10 @@ func (l *lexer) next() (bool, error) { continue } + if len(val) > 32 { + return false, fmt.Errorf("heredoc marker too long on line #%d: %s", l.line, string(val)) + } + // after hitting a newline, we know that the heredoc marker // is the characters after the two << and the newline. // we reset the val because the heredoc is syntax we don't diff --git a/caddyconfig/caddyfile/testdata/clusterfuzz-testcase-minimized-fuzz-format-5806400649363456 b/caddyconfig/caddyfile/testdata/clusterfuzz-testcase-minimized-fuzz-format-5806400649363456 new file mode 100644 index 0000000000000000000000000000000000000000..94b70919c4b59df0f1fa3740aa6f20577ac3d74a GIT binary patch literal 139348 zcmeI*J8s)R5CBlt3tz!U2*CY_Tn2lSRH=Og-NivJ=_ZB3k7N;!3pYj}>!}!xM%>xm zr(V-qd<>zr{9}prPk4D~Ep<;Vuam6 zN$ReZeZDn}ySDo+mbK^ZYx6n(=|zA50RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXFd|81ITC2w;=3QJXU-r%} zMt}eT0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZ;7$a7JwN}xldHNW0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZ;3D8J87~sv2@oJafB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ;HCw>-}LDno&W&? z1PBlyK!5-N0-q)jLTmN7#Jr1JWsBt)T4?q4!?NHMULIOY-P7CUsk>J8`F@LC^G~~$ z#smluAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBngF#*#fZ|nziTml3L5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5O`m}^vL&JR0$9uK!5-N0t5&UxO;)?u*d%~J@P!ba+@ca*7234 zrm2=VPN(H)^XSTLTIKQ<$3B)AYc4}yhAHJZ<~Y&mRpW4=LUEhwt z{J;#%T>4Z~9_F3;Dc3U0`{q2(n~!DQdZ;PJav0bC|4zz$ec-S@@U7M%ma!kEG7UAZ Jm+QOG{RP*)&zS%K literal 0 HcmV?d00001