Going down the rabbit hole with go-fuzz
mijailovic.net
mijailovic.net
I tried using Go Fuzz on a small parser I wrote, and was surprised that it found a bug. I was quite pleased, but the input was actually valid, my code was just wrong. One shortcoming of Fuzzing is that it doesn't find Type II errors. It can't find invalid inputs that do succeed. For example, if the input to my parser was actually invalid, but the code didn't crash, the fuzzer would happily continue on. I'm glad I fuzzed my code, but no errors found doesn't mean no errors present.
2. In Java, it's easy to tell whether, say, an IOException was working as intended or was an actual failure. Just check whether it was caught or not. Granted, that won't handle apps that try to catch wide swathes of exception types, but Go apps can abuse Go's "recover" facility in the same way.
[1] https://github.com/kisielk/errcheck [2] https://github.com/alecthomas/gometalinter
2. Apart from the few functions that are only called for side effects, the others must return something. Thus ignoring errors is an explicit action.
I have seen Java apps catch swathes of exceptions more often that Go apps abuse "recover". It is this way in a lot of short examples.
You could make the same argument about any errors being ignored. The fact is that syntax/semantics that allows any errors to be silently swallowed is suboptimal.
> 2. Apart from the few functions that are only called for side effects, the others must return something. Thus ignoring errors is an explicit action.
Ignoring errors is not always an explicit action, as you pointed out yourself. In Java, however, it is always an explicit action.
Java is simply more robust at making sure errors are handled than Go is.
But the main reason this is the case is because in Go, errors are things that can arise from correctly behaving functions. If someone passes you invalid input, it's correct to return an error. You wouldn't want this to show up in as bad input in a fuzzer. Most fuzz test cases after all will not be correct input.
One possible solution is to define all valid data by rules. That might be a laborious work. In this case a Fuzzer could check the returned error for valid or invalid input data.
> — Dmitry Vyukov
I would amend this slightly to state instead "If you didn't fuzz it, you can't say it's [robust]." To invoke correctness seems to suggest that you can do some amount of verification using fuzzing, but that's not really the case (unless you have a reference implementation).
But without fail, fuzzing often evokes a handful of shallow defects. And once those are addressed you can usually dig deeper and find more. I'd be astonished to find a library or program written in C/C++ that has never been fuzzed and undergo fuzzing without any newly discovered bugs.
Not necessarily. You just need to be able to verify correctness of the output and fuzz the following program:
y := f(x)
if (y,x) are not correct then crash
E.g. if you want to verify correctness of the compressor, try to check if a known-good decompressor can always decompress its output to its input. This is simpler than having a reference implementation.