Skip to content

Commit a06e960

Browse files
committed
refactor: add fuzzing test for new feature
1 parent af082e0 commit a06e960

File tree

13 files changed

+269
-1
lines changed

13 files changed

+269
-1
lines changed

.version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.3.836
1+
0.3.839

runtime/fuzzing/fuzz.templ

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package fuzzing
2+
3+
templ String(v any) {
4+
<script>
5+
function logValue() {
6+
console.log("{{ v }}")
7+
return "result_ok"
8+
}
9+
</script>
10+
}
11+
12+
templ Any(v any) {
13+
<script>
14+
function logValue() {
15+
console.log({{ v }})
16+
return "result_ok"
17+
}
18+
</script>
19+
}

runtime/fuzzing/fuzz_templ.go

+92
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

runtime/fuzzing/fuzz_test.go

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package fuzzing
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"strings"
7+
"testing"
8+
9+
"golang.org/x/net/html"
10+
11+
v8 "rogchap.com/v8go"
12+
)
13+
14+
var iso = v8.NewIsolate()
15+
16+
var testcases = []string{
17+
"hello",
18+
"<script>console.log('hello')</script>",
19+
"text data\n can contain all sorts of \"characters\" & symbols",
20+
"123",
21+
"</script>",
22+
}
23+
24+
func FuzzComponentString(f *testing.F) {
25+
for _, tc := range testcases {
26+
f.Add([]byte(tc))
27+
}
28+
f.Fuzz(func(t *testing.T, v []byte) {
29+
// Render template.
30+
buf := new(strings.Builder)
31+
32+
values := []any{
33+
string(v),
34+
[]string{string(v)},
35+
map[string]string{"value": string(v)},
36+
}
37+
for _, value := range values {
38+
buf.Reset()
39+
if err := String(value).Render(context.Background(), buf); err != nil {
40+
t.Skip(err)
41+
}
42+
runTest(t, buf.String())
43+
}
44+
})
45+
}
46+
47+
func FuzzComponentAny(f *testing.F) {
48+
for _, tc := range testcases {
49+
jsonValue, err := json.Marshal(tc)
50+
if err != nil {
51+
panic(err)
52+
}
53+
f.Add(jsonValue)
54+
}
55+
f.Fuzz(func(t *testing.T, v []byte) {
56+
// Render template.
57+
buf := new(strings.Builder)
58+
59+
values := []any{
60+
string(v),
61+
[]string{string(v)},
62+
map[string]string{"value": string(v)},
63+
}
64+
for _, value := range values {
65+
buf.Reset()
66+
if err := Any(value).Render(context.Background(), buf); err != nil {
67+
t.Skip(err)
68+
}
69+
runTest(t, buf.String())
70+
}
71+
})
72+
}
73+
74+
func getFirstScript(n *html.Node) *html.Node {
75+
if n.Data == "script" {
76+
return n
77+
}
78+
for c := n.FirstChild; c != nil; c = c.NextSibling {
79+
if s := getFirstScript(c); s != nil {
80+
return s
81+
}
82+
}
83+
return nil
84+
}
85+
86+
func runTest(t *testing.T, templateOutput string) {
87+
// Parse HTML.
88+
n, err := html.Parse(strings.NewReader(templateOutput))
89+
if err != nil {
90+
t.Fatalf("failed to parse HTML: %v", err)
91+
}
92+
sn := getFirstScript(n)
93+
if sn == nil {
94+
t.Fatalf("no script tag found")
95+
}
96+
97+
// Extract JavaScript.
98+
script := sn.FirstChild.Data
99+
100+
// Run JavaScript.
101+
v8ctx := v8.NewContext(iso)
102+
if _, err = v8ctx.RunScript(script, "component.js"); err != nil {
103+
t.Fatalf("failed to parse script: %v", err)
104+
}
105+
if _, err = v8ctx.RunScript("const result = logValue()", "component.js"); err != nil {
106+
t.Fatalf("failed to get value: %v", err)
107+
}
108+
actual, err := v8ctx.RunScript("result", "component.js")
109+
if err != nil {
110+
t.Fatalf("failed to get result: %v", err)
111+
}
112+
defer v8ctx.Close()
113+
114+
// Assert.
115+
if !actual.IsString() {
116+
t.Fatalf("expected boolean, got %T", actual.Object().Value)
117+
}
118+
if actual.String() != "result_ok" {
119+
t.Fatalf("expected 'result_ok', got %v", actual.Boolean())
120+
}
121+
}

runtime/fuzzing/go.mod

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module github.com/a-h/templ/runtime/fuzzing
2+
3+
go 1.23.3
4+
5+
require (
6+
github.com/a-h/templ v0.3.833
7+
golang.org/x/net v0.34.0
8+
)
9+
10+
require rogchap.com/v8go v0.9.0
11+
12+
require github.com/brianvoe/gofakeit/v7 v7.2.1 // indirect
13+
14+
replace github.com/a-h/templ => ../..

runtime/fuzzing/go.sum

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
2+
github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
3+
github.com/brianvoe/gofakeit/v7 v7.2.1 h1:AGojgaaCdgq4Adzrd2uWdbGNDyX6MWNhHdQBraNfOHI=
4+
github.com/brianvoe/gofakeit/v7 v7.2.1/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
5+
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
6+
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
7+
rogchap.com/v8go v0.9.0 h1:wYbUCO4h6fjTamziHrzyrPnpFNuzPpjZY+nfmZjNaew=
8+
rogchap.com/v8go v0.9.0/go.mod h1:MxgP3pL2MW4dpme/72QRs8sgNMmM0pRc8DPhcuLWPAs=
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]byte("{\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaluex")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]byte("{\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaluex")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]byte("{\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxalue\"x")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]byte("000000000000000000000000000000000000000000000\x128\x06\xef\x01\xb40000000")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]byte("&&&&\"0&&&&&00&00&&&0&00&0&8&&&")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]byte("\"\xf5\x9a\xb7\"\x8a\"\"\x9a\x9a\xf5\x9a\xb7\"\x8a\x8a\"\"\"\"\"\"")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
go test fuzz v1
2+
[]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 commit comments

Comments
 (0)