Fuzzing, per a current Wikipedia definition is defined the following way:
Fuzzing or fuzz testing is an automated software testing technique that involves providing invalid, unexpected, or random data as inputs to a computer program. The program is then monitored for exceptions such as crashes, failing built-in code assertions, or potential memory leaks. Typically, fuzzers are used to test programs that take structured inputs.
Symbolic execution, by contrast, is defined the following way, also pulling from Wikipedia:
In computer science, symbolic execution (also symbolic evaluation) is a means of analyzing a program to determine what inputs cause each part of a program to execute. An interpreter follows the program, assuming symbolic values for inputs rather than obtaining actual inputs as normal execution of the program would, a case of abstract interpretation.
What I am trying to understand is the functional difference between these two methods. I see the line that says symbolic execution determines "what inputs cause each part of a program to execute," so you might differentiate each method by the "goal" a security researcher has in mind. Papers I have read recently differentiate symbolic execution from fuzzing by saying the former has significantly more overhead / runs more slowly.
From my perspective, symbolic execution utilizes a form of "targeted fuzzing" that specifically hits certain symbolic values. I've also heard it said that symbolic execution is just "more sophisticated fuzzing."
Can someone clarify what the real difference is between the two and why or when we should prefer one method over the other?