Skip to content

Commit

Permalink
refactor: add fuzzing test for new feature
Browse files Browse the repository at this point in the history
  • Loading branch information
a-h committed Feb 23, 2025
1 parent 8057d1a commit d87fc9b
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.3.834
0.3.839
19 changes: 19 additions & 0 deletions runtime/fuzzing/fuzz.templ
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fuzzing

templ String(v any) {
<script>
function logValue() {
console.log("{{ v }}")
return "result_ok"
}
</script>
}

templ Any(v any) {
<script>
function logValue() {
console.log({{ v }})
return "result_ok"
}
</script>
}
92 changes: 92 additions & 0 deletions runtime/fuzzing/fuzz_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

121 changes: 121 additions & 0 deletions runtime/fuzzing/fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package fuzzing

import (
"context"
"encoding/json"
"strings"
"testing"

"golang.org/x/net/html"

v8 "rogchap.com/v8go"
)

var iso = v8.NewIsolate()

var testcases = []string{
"hello",
"<script>console.log('hello')</script>",
"text data\n can contain all sorts of \"characters\" & symbols",
"123",
"</script>",
}

func FuzzComponentString(f *testing.F) {
for _, tc := range testcases {
f.Add([]byte(tc))
}
f.Fuzz(func(t *testing.T, v []byte) {
// Render template.
buf := new(strings.Builder)

values := []any{
string(v),
[]string{string(v)},
map[string]string{"value": string(v)},
}
for _, value := range values {
buf.Reset()
if err := String(value).Render(context.Background(), buf); err != nil {
t.Skip(err)
}
runTest(t, buf.String())
}
})
}

func FuzzComponentAny(f *testing.F) {
for _, tc := range testcases {
jsonValue, err := json.Marshal(tc)
if err != nil {
panic(err)
}
f.Add(jsonValue)
}
f.Fuzz(func(t *testing.T, v []byte) {
// Render template.
buf := new(strings.Builder)

values := []any{
string(v),
[]string{string(v)},
map[string]string{"value": string(v)},
}
for _, value := range values {
buf.Reset()
if err := Any(value).Render(context.Background(), buf); err != nil {
t.Skip(err)
}
runTest(t, buf.String())
}
})
}

func getFirstScript(n *html.Node) *html.Node {
if n.Data == "script" {
return n
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
if s := getFirstScript(c); s != nil {
return s
}
}
return nil
}

func runTest(t *testing.T, templateOutput string) {
// Parse HTML.
n, err := html.Parse(strings.NewReader(templateOutput))
if err != nil {
t.Fatalf("failed to parse HTML: %v", err)
}
sn := getFirstScript(n)
if sn == nil {
t.Fatalf("no script tag found")
}

// Extract JavaScript.
script := sn.FirstChild.Data

// Run JavaScript.
v8ctx := v8.NewContext(iso)
if _, err = v8ctx.RunScript(script, "component.js"); err != nil {
t.Fatalf("failed to parse script: %v", err)
}
if _, err = v8ctx.RunScript("const result = logValue()", "component.js"); err != nil {
t.Fatalf("failed to get value: %v", err)
}
actual, err := v8ctx.RunScript("result", "component.js")
if err != nil {
t.Fatalf("failed to get result: %v", err)
}
defer v8ctx.Close()

// Assert.
if !actual.IsString() {
t.Fatalf("expected boolean, got %T", actual.Object().Value)
}
if actual.String() != "result_ok" {
t.Fatalf("expected 'result_ok', got %v", actual.Boolean())
}
}
14 changes: 14 additions & 0 deletions runtime/fuzzing/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/a-h/templ/runtime/fuzzing

go 1.23.3

require (
github.com/a-h/templ v0.3.833
golang.org/x/net v0.34.0
)

require rogchap.com/v8go v0.9.0

require github.com/brianvoe/gofakeit/v7 v7.2.1 // indirect

replace github.com/a-h/templ => ../..
8 changes: 8 additions & 0 deletions runtime/fuzzing/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
github.com/brianvoe/gofakeit/v7 v7.2.1 h1:AGojgaaCdgq4Adzrd2uWdbGNDyX6MWNhHdQBraNfOHI=
github.com/brianvoe/gofakeit/v7 v7.2.1/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
rogchap.com/v8go v0.9.0 h1:wYbUCO4h6fjTamziHrzyrPnpFNuzPpjZY+nfmZjNaew=
rogchap.com/v8go v0.9.0/go.mod h1:MxgP3pL2MW4dpme/72QRs8sgNMmM0pRc8DPhcuLWPAs=
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaluex")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaluex")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxalue\"x")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("000000000000000000000000000000000000000000000\x128\x06\xef\x01\xb40000000")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("&&&&\"0&&&&&00&00&&&0&00&0&8&&&")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("\"\xf5\x9a\xb7\"\x8a\"\"\x9a\x9a\xf5\x9a\xb7\"\x8a\x8a\"\"\"\"\"\"")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("\x00\xa5\x05\x93ϵ\xa0\xa0\xfe\xee\xcf\x1e\xa7\xcb\xde\x13\x1c\xb9\xb7\xc2\xca^\xb1\xb3\xc0\x1a\x01\xbb\xae\x89\x83\x87\x89\xbb\x1d\xbd\xb7\x95\x8e\\\x91\xe6\x10\xe4\xdf\xec\xf0\xcd\xe6\a\xea/\xa2\xbb\xbd\xef\xf9\v\x87\xd5\xc0\xe6\xa4\xdc\x02\xf8\xfc\x9dأ\xc2\\\xc4\xf3\x87\x04\x01\x18\x16\xc3\xe1\xbc\xc3\xc9\x12\xd5\xc3\xf9\r\x13\x1a\xdbx\xb6\xe8\xe2&\xbb\x81'\xea'\xc56\xb7\xf3;\xb3\xdb\xed\x8c.\xb8\xd4\xcc\xfe\xbcإ\xf0\xb6\xf3\xf1\xdeF\xb8\x12\b\x9f\xb9\xa5\xb4&\xa1\xea\a\x17ɕ\x0e\xe9\xf9\xe0\xb6K\x93\xdd\xee<\xf6\xda\t\xac\xa4\xb9\xb9ƽ\x98\xa6\xeb\xc5\xfe\v\xb9\xdb\xc7\xc4\x05\v\xf5\xb4߫\xd2\xc6\xe7\x0f⨍\xb5\xb4\xc3\xcb\x17\xc1\xf9\x95\x13\xfc\xd4\x1a\xcfԈ\xda\x17\xaa\xd1'\b\xe9\t\xb4\xec\xc2ɹ\xe0\v\x14\xd4h\xa6\x9c\x82\xf0\x06\xd8?\x8a\xf0\xc5\xed\xd1\xd2\xdf\xfb\x02\xab\x84\xf2M\xb5ò\xe9\xc8\xf3\x1c\xae\xfe\xee\xe5쪢\xf6\xe9[\x9e\xcc\x13\x1d\xea\xb5\x1e\xe7<\xc7\xf7\xac\v\xba\x15\xcd\xdd\xe0\x1e\xf7\xf9\x94\x83\xcd\xc7\xe5\xad\xc1\xca?\xb9\xe7\x06\xb1\xd5\x12")

0 comments on commit d87fc9b

Please sign in to comment.