Add Apache License version 2.0.
[pbc.git] / misc / memory.c
blob21d50ddf34574f0939ddefc640eb945630a6b8d4
1 #include <stdlib.h>
2 #include <stdint.h> // for intptr_t
3 #include <stdio.h>
4 #include <string.h>
5 #include "pbc_utils.h"
6 #include "pbc_memory.h"
8 #ifdef SAFE_CLEAN
9 /* guarantee zeroing the memory */
10 static void gmp_free(void *ptr, size_t size) {
11 if(ptr)
12 memset(ptr, 0, size);
13 free(ptr);
16 static void* gmp_malloc(size_t size) {
17 return malloc(size);
20 /* guarantee zeroing the memory
21 * realloc() is not suitable for use with secure memory
22 * because memory contents are not zeroed out. */
23 static void* gmp_realloc(void *old_ptr, size_t old_size, size_t new_size) {
24 void *new_ptr = malloc(new_size);
25 if(new_ptr && old_ptr)
26 memcpy(new_ptr, old_ptr, old_size);
27 gmp_free(old_ptr, old_size);
28 return new_ptr;
31 static void gmp_guarantee_zero_memory(void) {
32 __gmp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
35 __attribute__((constructor)) void init(void) {
36 gmp_guarantee_zero_memory();
39 /* pbc_mem is a continuous memory keeping track of its size */
40 static inline size_t pbc_mem_get_size(size_t *p) {
41 return *p;
44 static inline void pbc_mem_set_size(size_t *p, size_t size) {
45 *p = size;
48 static inline void *pbc_mem_to_ptr(size_t *p) {
49 return p + 1;
52 static inline void *pbc_ptr_to_mem(size_t *p) {
53 return p - 1;
56 static void *pbc_mem_malloc(size_t size) {
57 void *ptr = malloc(size + sizeof(size_t));
58 if(ptr)
59 pbc_mem_set_size(ptr, size);
60 return ptr;
63 static void pbc_mem_free(void *ptr) {
64 memset(ptr, 0, pbc_mem_get_size(ptr) + sizeof(size_t));
65 free(ptr);
68 static void *default_pbc_malloc(size_t size) {
69 void *ptr = pbc_mem_malloc(size);
70 if(!ptr) pbc_die("malloc() error");
71 return pbc_mem_to_ptr(ptr);
74 static void *default_pbc_realloc(void *old, size_t new_size) {
75 void *new = pbc_mem_malloc(new_size);
76 if(!new) pbc_die("realloc() error");
77 if(old) {
78 old = pbc_ptr_to_mem(old);
79 memcpy(pbc_mem_to_ptr(new), pbc_mem_to_ptr(old), pbc_mem_get_size(old));
80 pbc_mem_free(old);
82 return pbc_mem_to_ptr(new);
85 static void default_pbc_free(void *ptr) {
86 if(ptr)
87 pbc_mem_free(pbc_ptr_to_mem(ptr));
89 #else
90 static void *default_pbc_malloc(size_t size) {
91 void *res = malloc(size);
92 if (!res) pbc_die("malloc() error");
93 return res;
96 static void *default_pbc_realloc(void *ptr, size_t size) {
97 void *res = realloc(ptr, size);
98 if (!res) pbc_die("realloc() error");
99 return res;
102 static void default_pbc_free(void *ptr) { free(ptr); }
103 #endif
105 /* release memory got from pbc_malloc only by pbc_free(), do not use free() */
106 void *(*pbc_malloc)(size_t) = default_pbc_malloc;
107 /* pbc_realloc guarantees zeroing out the memory before moving old memory */
108 void *(*pbc_realloc)(void *, size_t) = default_pbc_realloc;
109 /* pbc_free guarantees zeroing out the memory */
110 void (*pbc_free)(void *) = default_pbc_free;
112 void pbc_set_memory_functions(void *(*malloc_fn)(size_t),
113 void *(*realloc_fn)(void *, size_t), void (*free_fn)(void *)) {
114 pbc_malloc = malloc_fn;
115 pbc_realloc = realloc_fn;
116 pbc_free = free_fn;
119 void *pbc_calloc(size_t nmemb, size_t size) {
120 void *res = pbc_malloc(nmemb * size);
121 if (!res) pbc_die("calloc() error");
122 memset(res, 0, nmemb * size);
123 return res;
126 char *pbc_strdup(const char *s) {
127 size_t len = strlen(s);
128 char *res = pbc_malloc(len + 1);
129 strcpy(res, s);
130 return res;