Skip to content

Commit b58fdb1

Browse files
suhasravi7suhravis
andauthored
Add custom memory allocator support (#178)
- Implement global function pointers for memory allocation - Add jose_set_alloc(), jose_get_alloc(), jose_reset_alloc() - Add comprehensive test suite in api_mem.c - Remove cfg dependencies from io.c structs - All tests passing (26/26) Co-authored-by: suhasr07 <suhravis@cisco.com>
1 parent 95d3c02 commit b58fdb1

File tree

19 files changed

+549
-73
lines changed

19 files changed

+549
-73
lines changed

include/jose/cfg.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <stddef.h>
2727
#include <stdarg.h>
2828
#include <stdint.h>
29+
#include <stdlib.h>
2930

3031
enum {
3132
_JOSE_CFG_ERR_BASE = 0x1053000000000000ULL,
@@ -57,6 +58,23 @@ typedef struct jose_cfg jose_cfg_t;
5758
typedef void (jose_cfg_err_t)(void *misc, const char *file, int line,
5859
uint64_t err, const char *fmt, va_list ap);
5960

61+
/**
62+
* Custom allocator function type signatures
63+
*/
64+
typedef void* (*jose_malloc_t)(size_t size);
65+
typedef void* (*jose_realloc_t)(void *ptr, size_t size);
66+
typedef void* (*jose_calloc_t)(size_t nmemb, size_t size);
67+
typedef void (*jose_free_t)(void *ptr);
68+
69+
/**
70+
* Global memory allocator function pointers
71+
* These can be overridden using jose_set_alloc()
72+
*/
73+
extern jose_malloc_t jose_malloc;
74+
extern jose_realloc_t jose_realloc;
75+
extern jose_calloc_t jose_calloc;
76+
extern jose_free_t jose_free;
77+
6078
/**
6179
* Creates a new configuration instance.
6280
*
@@ -134,4 +152,42 @@ jose_cfg_err(jose_cfg_t *cfg, const char *file, int line, uint64_t err,
134152
jose_cfg_err(cfg, __FILE__, __LINE__, err, __VA_ARGS__)
135153
#endif
136154

155+
/**
156+
* Set custom memory allocator functions for JOSE operations globally.
157+
*
158+
* This allows you to override the default malloc/realloc/free used
159+
* throughout the JOSE library. All JOSE operations will use these
160+
* custom allocators once set. Useful for:
161+
* - Memory debugging and tracking
162+
* - Custom memory pools
163+
* - Secure memory allocation
164+
* - Cross-DLL memory management on Windows
165+
*
166+
* @param pmalloc Custom malloc function
167+
* @param prealloc Custom realloc function
168+
* @param pcalloc Custom calloc function
169+
* @param pfree Custom free function
170+
* @return 0 on success, errno on error
171+
*/
172+
int
173+
jose_set_alloc(jose_malloc_t pmalloc, jose_realloc_t prealloc, jose_free_t pfree, jose_calloc_t pcalloc);
174+
175+
/**
176+
* Get current memory allocator functions.
177+
*
178+
* @param pmalloc Pointer to store current malloc function
179+
* @param prealloc Pointer to store current realloc function
180+
* @param pcalloc Pointer to store current calloc function
181+
* @param pfree Pointer to store current free function
182+
*/
183+
void
184+
jose_get_alloc(jose_malloc_t *pmalloc, jose_realloc_t *prealloc, jose_free_t *pfree, jose_calloc_t *pcalloc);
185+
186+
/**
187+
* Reset global allocators to system defaults.
188+
* Useful for testing or when you want to stop using custom allocators.
189+
*/
190+
void
191+
jose_reset_alloc(void);
192+
137193
/** @} */

lib/b64.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ io_free(jose_io_t *io)
6464
io_t *i = containerof(io, io_t, io);
6565
jose_io_decref(i->next);
6666
zero(i, sizeof(*i));
67-
free(i);
67+
jose_free(i);
6868
}
6969

7070
static size_t
@@ -198,7 +198,7 @@ jose_b64_dec_io(jose_io_t *next)
198198
jose_io_auto_t *io = NULL;
199199
io_t *i = NULL;
200200

201-
i = calloc(1, sizeof(*i));
201+
i = jose_calloc(1, sizeof(*i));
202202
if (!i)
203203
return NULL;
204204

@@ -277,19 +277,19 @@ jose_b64_dec_load(const json_t *i)
277277
if (size == SIZE_MAX)
278278
return NULL;
279279

280-
buf = calloc(1, size);
280+
buf = jose_calloc(1, size);
281281
if (!buf)
282282
return NULL;
283283

284284
if (jose_b64_dec(i, buf, size) != size) {
285285
zero(buf, size);
286-
free(buf);
286+
jose_free(buf);
287287
return NULL;
288288
}
289289

290290
out = json_loadb((char *) buf, size, JSON_DECODE_ANY, NULL);
291291
zero(buf, size);
292-
free(buf);
292+
jose_free(buf);
293293
return out;
294294
}
295295

@@ -304,15 +304,15 @@ jose_b64_enc(const void *i, size_t il)
304304
if (elen == SIZE_MAX)
305305
return NULL;
306306

307-
enc = calloc(1, elen);
307+
enc = jose_calloc(1, elen);
308308
if (!enc)
309309
return NULL;
310310

311311
if (jose_b64_enc_buf(i, il, enc, elen) == elen)
312312
out = json_stringn(enc, elen);
313313

314314
zero(enc, elen);
315-
free(enc);
315+
jose_free(enc);
316316
return out;
317317
}
318318

@@ -322,7 +322,7 @@ jose_b64_enc_io(jose_io_t *next)
322322
jose_io_auto_t *io = NULL;
323323
io_t *i = NULL;
324324

325-
i = calloc(1, sizeof(*i));
325+
i = jose_calloc(1, sizeof(*i));
326326
if (!i)
327327
return NULL;
328328

@@ -385,6 +385,6 @@ jose_b64_enc_dump(const json_t *i)
385385

386386
out = jose_b64_enc((const uint8_t *) buf, strlen(buf));
387387
zero(buf, strlen(buf));
388-
free(buf);
388+
jose_free(buf);
389389
return out;
390390
}

lib/cfg.c

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <stdlib.h>
2323
#include <string.h>
2424
#include <errno.h>
25+
#include <jansson.h>
2526

2627
struct jose_cfg {
2728
size_t refs;
@@ -30,6 +31,11 @@ struct jose_cfg {
3031
void *misc;
3132
};
3233

34+
jose_malloc_t jose_malloc = malloc;
35+
jose_realloc_t jose_realloc = realloc;
36+
jose_free_t jose_free = free;
37+
jose_calloc_t jose_calloc = calloc;
38+
3339
static struct {
3440
uint64_t nmbr;
3541
const char *name;
@@ -78,7 +84,7 @@ jose_cfg_t *
7884
jose_cfg(void)
7985
{
8086
jose_cfg_t *cfg = NULL;
81-
cfg = calloc(1, sizeof(*cfg));
87+
cfg = jose_calloc(1, sizeof(*cfg));
8288
if (cfg)
8389
*cfg = dflt;
8490
return jose_cfg_incref(cfg);
@@ -104,7 +110,7 @@ void
104110
jose_cfg_decref(jose_cfg_t *cfg)
105111
{
106112
if (cfg->refs-- == 1)
107-
free(cfg);
113+
jose_free(cfg);
108114
}
109115

110116
void
@@ -131,3 +137,41 @@ jose_cfg_err(jose_cfg_t *cfg, const char *file, int line, uint64_t err,
131137
c->err(c->misc, file, line, err, fmt, ap);
132138
va_end(ap);
133139
}
140+
141+
int
142+
jose_set_alloc(jose_malloc_t pmalloc, jose_realloc_t prealloc, jose_free_t pfree, jose_calloc_t pcalloc)
143+
{
144+
/* all of the allocator functions must be set */
145+
if (pmalloc == NULL || prealloc == NULL || pfree == NULL || pcalloc == NULL)
146+
return EINVAL;
147+
148+
jose_malloc = pmalloc;
149+
jose_realloc = prealloc;
150+
jose_free = pfree;
151+
jose_calloc = pcalloc;
152+
153+
/* Configure Jansson to use the same allocators as JOSE */
154+
json_set_alloc_funcs(jose_malloc, jose_free);
155+
156+
return 0;
157+
}
158+
159+
void
160+
jose_get_alloc(jose_malloc_t *pmalloc, jose_realloc_t *prealloc, jose_free_t *pfree, jose_calloc_t *pcalloc)
161+
{
162+
if (pmalloc) *pmalloc = jose_malloc;
163+
if (prealloc) *prealloc = jose_realloc;
164+
if (pfree) *pfree = jose_free;
165+
if (pcalloc) *pcalloc = jose_calloc;
166+
}
167+
168+
void
169+
jose_reset_alloc(void)
170+
{
171+
jose_malloc = malloc;
172+
jose_realloc = realloc;
173+
jose_free = free;
174+
jose_calloc = calloc;
175+
/* Reset Jansson to use default allocators */
176+
json_set_alloc_funcs(malloc, free);
177+
}

lib/io.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ malloc_feed(jose_io_t *io, const void *in, size_t len)
8383
if (len == 0)
8484
return true;
8585

86-
tmp = realloc(*i->buf, *i->len + len);
86+
tmp = jose_realloc(*i->buf, *i->len + len);
8787
if (!tmp)
8888
return false;
8989

@@ -106,12 +106,12 @@ malloc_free(jose_io_t *io)
106106

107107
if (i->buf && *i->buf && i->len) {
108108
zero(*i->buf, *i->len);
109-
free(*i->buf);
109+
jose_free(*i->buf);
110110
*i->len = 0;
111111
}
112112

113113
zero(i, sizeof(*i));
114-
free(i);
114+
jose_free(i);
115115
}
116116

117117
jose_io_t *
@@ -123,10 +123,12 @@ jose_io_malloc(jose_cfg_t *cfg, void **buf, size_t *len)
123123
if (!buf || !len)
124124
return NULL;
125125

126-
i = calloc(1, sizeof(*i));
126+
i = jose_malloc(sizeof(*i));
127127
if (!i)
128128
return NULL;
129129

130+
memset(i, 0, sizeof(*i));
131+
130132
io = jose_io_incref(&i->io);
131133
io->feed = malloc_feed;
132134
io->done = malloc_done;
@@ -172,7 +174,7 @@ buffer_free(jose_io_t *io)
172174
{
173175
io_buffer_t *i = containerof(io, io_buffer_t, io);
174176
zero(i, sizeof(*i));
175-
free(i);
177+
jose_free(i);
176178
}
177179

178180
jose_io_t *
@@ -184,10 +186,12 @@ jose_io_buffer(jose_cfg_t *cfg, void *buf, size_t *len)
184186
if (!buf || !len)
185187
return NULL;
186188

187-
i = calloc(1, sizeof(*i));
189+
i = jose_malloc(sizeof(*i));
188190
if (!i)
189191
return NULL;
190192

193+
memset(i, 0, sizeof(*i));
194+
191195
io = jose_io_incref(&i->io);
192196
io->feed = buffer_feed;
193197
io->done = buffer_done;
@@ -219,7 +223,7 @@ file_free(jose_io_t *io)
219223
{
220224
io_file_t *i = containerof(io, io_file_t, io);
221225
zero(i, sizeof(*i));
222-
free(i);
226+
jose_free(i);
223227
}
224228

225229
jose_io_t *
@@ -231,10 +235,12 @@ jose_io_file(jose_cfg_t *cfg, FILE *file)
231235
if (!file)
232236
return NULL;
233237

234-
i = calloc(1, sizeof(*i));
238+
i = jose_malloc(sizeof(*i));
235239
if (!i)
236240
return NULL;
237241

242+
memset(i, 0, sizeof(*i));
243+
238244
io = jose_io_incref(&i->io);
239245
io->feed = file_feed;
240246
io->done = file_done;
@@ -301,7 +307,7 @@ plex_free(jose_io_t *io)
301307
jose_io_decref(i->nexts[j]);
302308

303309
zero(i, sizeof(*i));
304-
free(i);
310+
jose_free(i);
305311
}
306312

307313
jose_io_t *
@@ -314,10 +320,12 @@ jose_io_multiplex(jose_cfg_t *cfg, jose_io_t **nexts, bool all)
314320
while (nexts && nexts[nnexts])
315321
nnexts++;
316322

317-
i = calloc(1, sizeof(*i) + sizeof(jose_io_t *) * nnexts);
323+
i = jose_malloc(sizeof(*i) + sizeof(jose_io_t *) * nnexts);
318324
if (!i)
319325
return NULL;
320326

327+
memset(i, 0, sizeof(*i) + sizeof(jose_io_t *) * nnexts);
328+
321329
io = jose_io_incref(&i->io);
322330
io->feed = plex_feed;
323331
io->done = plex_done;

lib/jws.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ ios_auto(jose_io_t ***iosp)
9898
for (size_t i = 0; ios && ios[i]; i++)
9999
jose_io_auto(&ios[i]);
100100

101-
free(ios);
101+
jose_free(ios);
102102
}
103103

104104
static jose_io_t *
@@ -183,7 +183,7 @@ jose_jws_sig_io(jose_cfg_t *cfg, json_t *jws, json_t *sig, const json_t *jwk)
183183
if (json_is_array(sig) && json_array_size(sig) != json_array_size(jwk))
184184
return NULL;
185185

186-
ios = calloc(json_array_size(jwk) + 1, sizeof(*ios));
186+
ios = jose_calloc(json_array_size(jwk) + 1, sizeof(*ios));
187187
if (!ios)
188188
return NULL;
189189

@@ -256,7 +256,7 @@ jose_jws_ver_io(jose_cfg_t *cfg, const json_t *jws, const json_t *sig,
256256
if (json_is_array(sig) && json_array_size(sig) != json_array_size(jwk))
257257
return NULL;
258258

259-
ios = calloc(json_array_size(jwk) + 1, sizeof(*ios));
259+
ios = jose_calloc(json_array_size(jwk) + 1, sizeof(*ios));
260260
if (!ios)
261261
return NULL;
262262

@@ -284,7 +284,7 @@ jose_jws_ver_io(jose_cfg_t *cfg, const json_t *jws, const json_t *sig,
284284
if (!json_is_array(array))
285285
return jose_jws_ver_io(cfg, jws, jws, jwk, true);
286286

287-
ios = calloc(json_array_size(array) + 1, sizeof(*ios));
287+
ios = jose_calloc(json_array_size(array) + 1, sizeof(*ios));
288288
if (!ios)
289289
return NULL;
290290

lib/libjose.map

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ LIBJOSE_1.0 {
1515
jose_cfg_get_err_misc;
1616
jose_cfg_incref;
1717
jose_cfg_set_err_func;
18+
jose_set_alloc;
19+
jose_get_alloc;
20+
jose_malloc;
21+
jose_calloc;
22+
jose_realloc;
23+
jose_free;
24+
jose_reset_alloc;
1825
jose_hook_alg_find;
1926
jose_hook_alg_find_any;
2027
jose_hook_alg_list;

0 commit comments

Comments
 (0)