For completeness sake, there are C programs that never allocate memory dynamically, using press-allocated variables only. Your microwave likely runs one.
There are also programs that allocate but never we-allocate memory. They are fast-terminating programs, ranging from a CLI utility to onboard software that controls a surface-to-air rocket.
But many programs still need more complex memory management done safely.
Rust recently had an integer overflow in str::repeat permitting a buffer overflow. It was a classic bug, the kind that gave C a bad reputation. And the error(s) in arithmetic occurred outside any unsafe block.
If we want to be pedantic, all this talk of "fearless" wrt Rust is dangerous hyperbole. Once you move past juggling scalar values things get dicey, especially in C but also in so-called "safe" languages like Rust. And that, I think, was the previous poster's point--as you move away from dynamic allocation you tend to move toward using scalar (fixed-sized) objects.
One of the original points of emphasis of Rust was to favor scalar values rather than pointers and even references. To a limited but useful extent you can mimic this in C. Rust examples that simply use Vec miss the point--1) the str::repeat bug overflowed a Vec, and 2) just because C doesn't come with a built-in Vec doesn't mean you can't write one or use one.
>And the error(s) in arithmetic occurred outside any unsafe block.
This is completely misleading. The unsound check for integer overflow[0] was in 'safe' code but just because the code is not in an unsafe block does not absolve you of any potential bugs, and the subsequent writes to memory that were in an unsafe block clearly did not care about prior mistakes that were made. The PR that introduced the vulnerability[1] was due from switching a safe method to one that uses unsafe for performance reasons, I suggest checking out the commits for both the introduction of this bug as well as the commit that fixed it as they're both short and the actual bug only occurs on one short line.
It's also worth noting that the vulnerability could have been found using a fuzzer[2] that did not exist (for Rust) at the time but that does now exist, and that integer overflows are checked for on debug builds (but not for release builds by default, again due to performance reasons) but that in this particular vulnerability it would have been extremely unlikely that any legitimate code would have triggered this integer overflow.
The take away here isn't that 'even 'safe' languages get it wrong', but that unsafe operations are difficult to do correctly, and that's true in either C or Rust. There's further discussion[3] on this bug if anybody is interested.
Unfortunately, that does not completely prevent memory corruption bugs in C. But it's a step in the right direction. For example BearSSL is a C TLS library that does not use malloc.
There are also programs that allocate but never we-allocate memory. They are fast-terminating programs, ranging from a CLI utility to onboard software that controls a surface-to-air rocket.
But many programs still need more complex memory management done safely.