testing-debugging · intermediate · ~15 min

Safe Allocation Guard with Fallback

Enforce allocation size quotas defensively and handle memory allocation failures safely.

Challenge

Unchecked malloc calls can cause denial of service or remote code execution when memory limits are exceeded. Robust software applies memory quotas and checks for multiplication overflow (nmemb * size) before requesting memory.

Your Task

Implement:

void *safe_calloc_quota(size_t nmemb, size_t size, size_t *quota_remaining);
void safe_free_quota(void *ptr, size_t bytes, size_t *quota_remaining);

Rules

  1. In safe_calloc_quota:
    • If quota_remaining == NULL, nmemb == 0, or size == 0, return NULL.
    • Check for multiplication overflow: if nmemb > SIZE_MAX / size, return NULL.
    • Let total = nmemb * size.
    • If total > *quota_remaining, return NULL without modifying *quota_remaining.
    • Allocate memory using calloc(nmemb, size).
    • If allocation succeeds, subtract total from *quota_remaining and return the pointer.
    • If allocation fails, return NULL and do not modify *quota_remaining.
  2. In safe_free_quota:
    • If ptr != NULL and quota_remaining != NULL:
      • Free ptr.
      • Add bytes back to *quota_remaining.

Example

size_t quota = 1000;
int *p = safe_calloc_quota(10, sizeof(int), &quota); // 40 bytes deducted, quota == 960
safe_free_quota(p, 10 * sizeof(int), &quota); // 40 bytes restored, quota == 1000

Input format

nmemb: element count; size: element size; quota_remaining: pointer to available bytes.

Output format

Returns allocated pointer or NULL on quota/overflow error.

Constraints

Check size_t overflow before multiplication. Atomic quota update.

Starter code

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

/* Allocate zeroed memory within quota limits. Return NULL on error or quota exceeded. */
void *safe_calloc_quota(size_t nmemb, size_t size, size_t *quota_remaining) {
    (void)nmemb; (void)size; (void)quota_remaining;
    return NULL;
}

/* Free allocated memory and credit bytes back to quota. */
void safe_free_quota(void *ptr, size_t bytes, size_t *quota_remaining) {
    (void)ptr; (void)bytes; (void)quota_remaining;
}

Common mistakes

Deducting from quota before verifying allocation success; forgetting to check multiplication overflow.

Edge cases to handle

Overflowing nmemb * size returns NULL; exact quota match succeeds; freeing NULL does nothing.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.