CWE-763 is a parent weakness for release mistakes. The product tries to return a memory resource to the system but calls the wrong release function, or calls the appropriate one incorrectly.
It affects C and C++ on memory unsafe platforms, wherever developers release memory by hand.
How it happens
MITRE describes two forms, each with its own entry:
- The memory was allocated by one management method and released by a different, incompatible function. That is CWE-762.
- The right routines were chosen but used incorrectly. A common case is CWE-761, freeing a pointer that is not at the start of its buffer.
A real case from the record is CVE-2019-11930. A function internally called calloc and returned a pointer at an index inside the allocated buffer. Callers then released that interior pointer, which freed invalid memory. The lesson is that the caller cannot always tell. An API that hands back a pointer into the middle of an allocation invites the caller to free it.
// Vulnerable API: returns an interior pointer from a heap block
char *get_payload(void) {
char *block = calloc(1, 128);
return block + 16; // caller later calls free() on this
}
What an attacker gains
Per the record, the weakness may corrupt memory, and perhaps instructions, possibly leading to a crash. If the corrupted memory can be effectively controlled, it may be possible to execute arbitrary code. The listed consequences are memory modification, crash, exit or restart, and execution of unauthorized code, spanning integrity, availability and confidentiality.
How to find it
MITRE names two techniques.
- Fuzzing. Generating many diverse inputs, random or algorithmic, and running the code is good at provoking crashes and memory corruption. It can find release errors that no reviewer spotted.
- Automated dynamic analysis. Use compile time instrumentation that adds runtime memory checks, such as AddressSanitizer for C and C++ or valgrind. MITRE notes this needs crafted inputs that reach the vulnerable code, so combine it with fuzzing for coverage.
Build a debug configuration with ASan enabled and run your whole test suite under it. It is among the cheapest checks available, and it reports the file and line of the bad release.
For code that comes from third parties, a vulnerable library function can sit in your dependency tree. Whether your application actually calls it is the question that reachability analysis answers, and it helps rank which memory bugs in dependencies need attention first. The free scanner at gold.safeguard.sh/scan checks up to 100 dependencies in your browser without a login, and the file stays on your machine.
How to fix it
- Only call matching memory management functions. Do not mix and match. A buffer allocated with malloc() is released with free() on the original pointer.
- Preserve the original pointer. Track progress through a buffer with a separate variable instead of advancing the allocation pointer.
- Use smart pointers in C++. MITRE mentions those provided by the boost library, and the standard library has equivalents.
- Rely on vetted libraries or frameworks that do not allow the weakness, or that provide constructs making it easier to avoid. MITRE cites glibc on Linux, which provides protection against freeing invalid pointers.
- Prefer a language with allocation abstractions if a new component allows the choice.
- Design APIs so ownership is clear. Return the start of an allocation, or provide a dedicated release function so callers never decide.
// Fix: the library owns release, callers never free interior pointers
typedef struct { char *block; } Payload;
char *payload_data(Payload *p) { return p->block + 16; }
void payload_free(Payload *p) { free(p->block); free(p); }
Quick check
How does CWE-763 relate to CWE-762 and CWE-761?
It is the broader category. CWE-762 is the incompatible function case, and CWE-761 is the case where the right function gets a pointer that is not at the start of the buffer.
Why is an API returning an interior pointer risky?
Callers may pass that pointer to free(). Offer a release function, or return the allocation start.
Which two checks does MITRE highlight for detection?
Fuzzing, and automated dynamic analysis with tools such as AddressSanitizer or valgrind.