unimplemented! called
| Vulnerability potential | Low |
| DDoS potential | Medium |
unimplemented! marks unfinished code and aborts at runtime
Impact
unimplemented!() expands to a panic! with the message not implemented. It
is used to fill in trait methods or match arms that a type deliberately does not
support, so the code compiles. Like todo!, it produces no compiler warning, so
if execution ever reaches it the thread panics: it unwinds to thread death, or
under panic = "abort" aborts the whole process with SIGABRT; a main-thread
panic exits with code 101.
A frequent source is implementing a large trait and stubbing the methods a given
type “shouldn’t” need with unimplemented!(). If a caller — or a generic code
path — invokes one of those methods, the program crashes instead of returning a
meaningful error.
Vulnerability potential
- Denial of service. An
unimplemented!on a reachable path is a guaranteed crash when hit. If an attacker or an unusual valid input can drive execution to the unsupported method/branch, they crash the request or, underpanic = "abort"/ on a critical thread, the process — a repeatable DoS.
No memory unsafety is involved (the panic is well-defined), so the vulnerability rating is Low; the real exposure is availability and unsupported-but-reachable code paths.
Technical details
unimplemented! and todo! are functionally the same: both expand to a panic
and both evaluate to the never type !, so they type-check in any position. The
distinction is intent and message — unimplemented! (not implemented) signals
“intentionally not provided”, whereas todo! (not yet implemented) signals
“to be done”. Both crash through the standard panic machinery and obey the
crate’s panic = "unwind"/"abort" strategy.
Trait stubs are the classic case
Because unimplemented!() satisfies any return type, it is commonly used to stub
trait-method bodies. The compiler cannot tell that such a method is reachable, so
it issues no warning; correctness depends entirely on the assumption that the
method is never actually called — an assumption that breaks when the type is used
through a generic bound or a trait object.
Catching the issue
Lint
clippy::unimplemented (restriction lint) flags every unimplemented!. For
release builds, #![deny(clippy::unimplemented)] (and clippy::todo) prevents
shipping such stubs; a CI grep is a simple additional gate.
Design alternatives
If a method genuinely cannot be supported, prefer a typed error: return
Result<_, E> with a “not supported” variant, or redesign the trait so
unsupported operations are not expressible (split traits, narrower bounds) rather
than panicking at runtime. Ensure tests cover the paths that reach stubs so a
reachable unimplemented! fails in CI.
How to reproduce
Run the following; observe the not implemented panic when the stubbed trait
method is called.
trait Storage {
fn read(&self) -> i32;
fn write(&self, value: i32);
}
struct ReadOnly;
impl Storage for ReadOnly {
fn read(&self) -> i32 { 7 }
fn write(&self, _value: i32) {
unimplemented!() // panics if anyone calls write on a read-only store
}
}
fn main() {
let s = ReadOnly;
s.write(1); // panic: not implemented
}