Skip to content

Instantly share code, notes, and snippets.

@Cyanoxygen
Last active April 2, 2021 09:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cyanoxygen/01a938f9bdd0682b0fc694b6ce027bd3 to your computer and use it in GitHub Desktop.
Save Cyanoxygen/01a938f9bdd0682b0fc694b6ce027bd3 to your computer and use it in GitHub Desktop.
A simple memory leaker, not portable and result may vary on different libc implementations. Meant to be run under Linux amd64 w/ glibc.
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#define BYTES 56
int actual;
char *p1;
u_int64_t bytes;
u_int64_t count;
char *somedata = "somedatasomedatasomedatasomedatasomedatasomedatasomedatasomedata";
void print() {
printf("Last pointer address: %p\n", p1);
printf("We have leaked %lld bytes of memory, with %lld allocations.\n", bytes, count);
exit(0);
}
int leak() {
if (bytes % 1073741824 == 0 && count > 0) {
printf("We just leaked %dGB of memory with %lld allocations!!!\n", bytes / 1073741824, count);
printf("Pointer location: %p\n", p1);
}
p1 = (char *) malloc(BYTES);
memcpy(p1, somedata, BYTES); // UNSAFE!
if (count == 0) printf("First malloc happened at %p.\n", p1);
bytes += actual;
count++;
return 0;
}
int main() {
p1 = NULL;
count = 0;
bytes = 0;
// Calculate actual bytes allocated.
// glibc's malloc() is chunk-based, and a chunk is at least 4*(sizeof (void *)) of size.
// if a chunk exceeds this size, each chunk have a 1*(sizeof (void*)) size of header.
// And there's an additional alignment, fmi it is 16-byte.
if (BYTES + 8 <= 32) {
actual = 32;
} else {
if ((BYTES + 8) % 16 == 0)
actual = 16 * ((BYTES + 8) / 16);
else
actual = 16 * ((BYTES + 8) / 16) + 1;
}
printf("Using %d byte per allocation.\n", BYTES);
printf("Chunk size is %d byte.\n", actual);
signal(SIGINT, print);
while(1) {
if (leak()) break;
}
print();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment