File: falloc.c

package info (click to toggle)
librecast 0.11.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,760 kB
  • sloc: ansic: 31,144; asm: 28,570; sh: 3,164; makefile: 713; python: 70
file content (67 lines) | stat: -rw-r--r-- 1,524 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2021-2022 Brett Sheffield <bacs@librecast.net> */

#define _GNU_SOURCE
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static volatile int allock;
static size_t stackptr;
static char stackbuf[1024];
static void *(*_malloc)(size_t);
static void (*_free)(void *);
static int falloc_fail = -1; /* *alloc fails when zero - decremented each allocation */

static void *falloc_enomem(void)
{
	fprintf(stderr, "falloc forcing ENOMEM\n");
	errno = ENOMEM;
	return NULL;
}

void *malloc(size_t size)
{
	if (allock) {
		/* thanks to FatalFlaw for the idea
		 * https://stackoverflow.com/questions/6083337/overriding-malloc-using-the-ld-preload-mechanism */
		/* dlsym calls calloc() - hand it a block from our stack */
		void *p;
		p = stackbuf + stackptr;
		stackptr += size;
		return p;
	}
	else if (!_malloc) {
		allock = 1;
		*(void **)&_malloc = dlsym(RTLD_NEXT, "malloc");
		*(void **)&_free = dlsym(RTLD_NEXT, "free");
		allock = 0;
	}
	if (falloc_fail > 0) falloc_fail--;
	if (!falloc_fail) return falloc_enomem();
	return _malloc(size);
}

void *calloc(size_t nmemb, size_t size)
{
	void *ptr;
	size_t sz = nmemb * size;
	ptr = malloc(sz);
	if (!ptr) return NULL;
	memset(ptr, 0, sz);
	return ptr;
}

void free(void *ptr)
{
	if (!ptr) return;
	if ((char *)ptr < stackbuf || (char *)ptr > stackbuf + sizeof stackbuf)
		_free(ptr);
}

void falloc_setfail(int failafter)
{
	falloc_fail = failafter;
}