tinygo
tinygo copied to clipboard
io/fs test fails with Go 1.18.4
It appears that all CI that uses Go 1.18 is still pinned on 1.18.1, but with 1.18.4, there is a new failure that did not occur in 1.18.3, with make tinygo-test. However, it doesn't appear that -v does anything, so i can't get much more info than FAIL io/fs 2.363s.
Looking at the diff for 1.18.3 to 1.18.4, I think the failure is the new CVE-related test.
It fails on both 0.24.0 and 0.23.0.
Using -run TestCVE202230630, I can confirm that it is the new CVE-related test, which could mean that tinygo-built programs may be vulnerable to CVE-2022-30630. But I'm not sure why, as there does not appear to be a Glob implementation anywhere in tinygo.
Extracting the test into a separate program:
package main
import (
"io/fs"
"log"
"os"
"strconv"
"strings"
)
func main() {
count := 10001
if len(os.Args) > 1 {
var err error
count, err = strconv.Atoi(os.Args[1])
if err != nil {
log.Fatalf("Failed to parse count: %v", err)
}
}
// Prior to CVE-2022-30630, a stack exhaustion would occur given a large
// number of separators. There is now a limit of 10,000.
_, err := fs.Glob(os.DirFS("."), "/*"+strings.Repeat("/", count))
log.Fatalf("Glob returned err=%v", err)
}
then shows a segfault in gdb
#0 0x000000000020ee02 in path.matchChunk (chunk=..., s=...)
failed = <optimized out>
r = <optimized out>
n = <optimized out>
negated = <optimized out>
n = <optimized out>
match = <optimized out>
nrange = <optimized out>
lo = <optimized out>
hi = <optimized out>
err = <optimized out>
ErrBadPattern = <optimized out>
#1 0x000000000020ebf5 in path.Match (pattern=..., name=...) at /usr/lib/golang/src/path/match.go:49
star = false
chunk = {ptr = 0x7fffb800b960 "/*", '/' <repeats 198 times>..., len = 1}
err = <optimized out>
t = <optimized out>
i = <optimized out>
t = <optimized out>
err = <optimized out>
err = <optimized out>
ok = <optimized out>
ok = <optimized out>
#2 0x000000000021727a in io/fs.globWithLimit (fsys=..., pattern=..., depth=0) at /usr/lib/golang/src/io/fs/glob.go:49
ok = false
err = <optimized out>
dir = <optimized out>
m = <optimized out>
err = <optimized out>
matches = <optimized out>
fsys = <optimized out>
file = <optimized out>
d = <optimized out>
...
#273 0x000000000021150f in io/fs.Glob (pattern=..., fsys=...) at /usr/lib/golang/src/io/fs/glob.go:34
No locals.
#274 main.main () at /builddir/build/BUILD/tinygo-0.24.0/check.go:14
err = <optimized out>
#275 runtime.run$1 () at /builddir/build/BUILDROOT/tinygo-0.24.0-1.fc37.x86_64/usr/lib64/tinygo/src/runtime/scheduler_any.go:25
schedulerDone = <optimized out>
#276 <goroutine wrapper> () at /builddir/build/BUILDROOT/tinygo-0.24.0-1.fc37.x86_64/usr/lib64/tinygo/src/runtime/scheduler_any.go:23
No locals.
#277 0x000000000020c8fe in tinygo_startTask () at /builddir/build/BUILDROOT/tinygo-0.24.0-1.fc37.x86_64/usr/lib64/tinygo/src/internal/task/task_stack_amd64.S:29
No locals.
Playing around with the count shows that it works for 268, but crashes on 269. Is it simply running out of stack space due to the recursive io/fs.globWithLimit?
Using
-run TestCVE202230630, I can confirm that it is the new CVE-related test, which could mean thattinygo-built programs may be vulnerable to CVE-2022-30630. But I'm not sure why, as there does not appear to be aGlobimplementation anywhere in tinygo.
Most of the standard library packages (including glob) are from the Go installation so updating the Go toolchain should also fix this specific bug for TinyGo.
Playing around with the count shows that it works for 268, but crashes on 269. Is it simply running out of stack space due to the recursive
io/fs.globWithLimit?
Probably. While the Go runtime normally uses a stack of 1GB or so (they start out small and grow on demand), TinyGo will use a relatively small stack by default. Therefore, it can in fact run out of stack space, and corrupt memory when this happens. (I'd like to move to threads in the future but for now there is no check on stack overflows like OS threads normally have).
This was fixed by #3143.