Hey HN! For the past few months, I've been working really hard on a static analysis tool called gohawk, and have successfully used it to find bugs in Caddy / Docker / k8s (links in the README). It's meant to catch resource leaks and concurrency errors in Go code, such as the following example:
I built this tool after realizing that Staticcheck and other linters don't really cover this ground yet. It works by building a symbolic heap model of the program under analysis, so that it can track object references with a high degree of accuracy. (I took this idea from Meta's Infer tool, which is developed exclusively for C++/Objective-C/Java, and generalized it to fit Go.) For example, it's able to tell in this case that r1 and r2 are the same.
type fileBox struct {
slots [2]*os.File
}
func example(path string, replacement *os.File) error {
r1, err := os.Open(path)
if err != nil {
return err
}
original := fileBox{slots: [2]*os.File{replacement, r1}}
copied := original
alias := &original
alias.slots[1] = replacement
window := copied.slots[1:]
r2 := window[0]
return r2.Close()
}
It's also capable of detecting certain types of goroutine leaks / lock inversions. For example, the following code gets flagged:
I'll be up front with y'all and say I used AI a lot to help me in the process of writing gohawk. However, I will stand by the fact that it's not just AI slop -- I'm a clean code fanatic, and the pipeline has been deliberately engineered.
I really wanted the user experience to be buttery smooth when downloading and using this, so I had an AI agent continuously download hundreds of repos from the Internet, run gohawk on them, and report back if there were any false positives. (Yes, I know, slightly overkill :^) ) It's at a point where I think false positives on new code should be fairly rare.
OTHER FEATURES
- Really rich diagnostics (I took inspo from rustc -- the full lineage of the error gets reported, including error spans)
- Documentation website (https://gohawk.dev) -- Contains detailed overview of all the supported analyzers. The diagnostic messages link out to the website
- Custom analysis runner -- I found `go vet` to be really slow because it would spend a lot of time serializing and deserializing facts across packages, so I rolled my own runner to replace it.
- Performant -- From a cold cache, it's able to analyze Docker in around 13s, and the whole of Kubernetes around 76s.
Building this out was a really awesome learning experience for me, and I'm planning to make a blog post about it soon -- stay tuned. Also hoping to get it integrated directly into GolangCI but gotta ask the maintainer first, so fingers crossed.
I genuinely hope you guys can download and enjoy the effort I put into this project. Feedback and contributions are welcome, and I'm planning to set up a Discord or IRC channel in the near future.
its-malbolge-ti•9m ago
I'll be up front with y'all and say I used AI a lot to help me in the process of writing gohawk. However, I will stand by the fact that it's not just AI slop -- I'm a clean code fanatic, and the pipeline has been deliberately engineered.
I really wanted the user experience to be buttery smooth when downloading and using this, so I had an AI agent continuously download hundreds of repos from the Internet, run gohawk on them, and report back if there were any false positives. (Yes, I know, slightly overkill :^) ) It's at a point where I think false positives on new code should be fairly rare.
OTHER FEATURES
- Really rich diagnostics (I took inspo from rustc -- the full lineage of the error gets reported, including error spans) - Documentation website (https://gohawk.dev) -- Contains detailed overview of all the supported analyzers. The diagnostic messages link out to the website - Custom analysis runner -- I found `go vet` to be really slow because it would spend a lot of time serializing and deserializing facts across packages, so I rolled my own runner to replace it. - Performant -- From a cold cache, it's able to analyze Docker in around 13s, and the whole of Kubernetes around 76s.
Building this out was a really awesome learning experience for me, and I'm planning to make a blog post about it soon -- stay tuned. Also hoping to get it integrated directly into GolangCI but gotta ask the maintainer first, so fingers crossed.
I genuinely hope you guys can download and enjoy the effort I put into this project. Feedback and contributions are welcome, and I'm planning to set up a Discord or IRC channel in the near future.