Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
alloc.h
Go to the documentation of this file.
1
14
15#pragma once
16
17#include <assert.h>
18#include <limits.h>
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <util/exit.h>
24#include <util/prisize_t.h>
25
26static inline void *gv_calloc(size_t nmemb, size_t size) {
27
28 if (nmemb > 0 && SIZE_MAX / nmemb < size) {
29 fprintf(stderr,
30 "integer overflow when trying to allocate "
31 "%" PRISIZE_T " * %" PRISIZE_T " bytes\n",
32 nmemb, size);
33 graphviz_exit(EXIT_FAILURE);
34 }
35
36 void *p = calloc(nmemb, size);
37 if (nmemb > 0 && size > 0 && p == NULL) {
38 fprintf(stderr,
39 "out of memory when trying to allocate %" PRISIZE_T " bytes\n",
40 nmemb * size);
41 graphviz_exit(EXIT_FAILURE);
42 }
43
44 return p;
45}
46
47static inline void *gv_alloc(size_t size) { return gv_calloc(1, size); }
48
49static inline void *gv_realloc(void *ptr, size_t old_size, size_t new_size) {
50
51 // make realloc with 0 size equivalent to free, even under C23 rules
52 if (new_size == 0) {
53 free(ptr);
54 return NULL;
55 }
56
57 void *p = realloc(ptr, new_size);
58 if (p == NULL) {
59 fprintf(stderr,
60 "out of memory when trying to allocate %" PRISIZE_T " bytes\n",
61 new_size);
62 graphviz_exit(EXIT_FAILURE);
63 }
64
65 // if this was an expansion, zero the new memory
66 if (new_size > old_size) {
67 memset((char *)p + old_size, 0, new_size - old_size);
68 }
69
70 return p;
71}
72
73static inline void *gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb,
74 size_t size) {
75
76 assert(size > 0 && "attempt to allocate array of 0-sized elements");
77 assert(old_nmemb < SIZE_MAX / size && "claimed previous extent is too large");
78
79 // will multiplication overflow?
80 if (new_nmemb > SIZE_MAX / size) {
81 fprintf(stderr,
82 "integer overflow when trying to allocate %" PRISIZE_T
83 " * %" PRISIZE_T " bytes\n",
84 new_nmemb, size);
85 graphviz_exit(EXIT_FAILURE);
86 }
87
88 return gv_realloc(ptr, old_nmemb * size, new_nmemb * size);
89}
90
91// when including this header in a C++ source, G++ under Cygwin chooses to be
92// pedantic and hide the prototypes of `strdup` and `strndup` when not
93// compiling with a GNU extension standard, so re-prototype them
94#if defined(__cplusplus) && defined(__CYGWIN__)
95extern "C" {
96extern char *strdup(const char *s1);
97extern char *strndup(const char *s1, size_t n);
98}
99#endif
100
101static inline char *gv_strdup(const char *original) {
102
103 char *copy = strdup(original);
104 if (copy == NULL) {
105 fprintf(stderr,
106 "out of memory when trying to allocate %" PRISIZE_T " bytes\n",
107 strlen(original) + 1);
108 graphviz_exit(EXIT_FAILURE);
109 }
110
111 return copy;
112}
113
114static inline char *gv_strndup(const char *original, size_t length) {
115
116 char *copy;
117
118// non-Cygwin Windows environments do not provide strndup
119#if defined(_MSC_VER) || defined(__MINGW32__)
120
121 // does the string end before the given length?
122 {
123 const char *end = (const char *)memchr(original, '\0', length);
124 if (end != NULL) {
125 length = (size_t)(end - original);
126 }
127 }
128
129 // will our calculation to include the NUL byte below overflow?
130 if (SIZE_MAX - length < 1) {
131 fprintf(stderr,
132 "integer overflow when trying to allocate %" PRISIZE_T
133 " + 1 bytes\n",
134 length);
135 graphviz_exit(EXIT_FAILURE);
136 }
137
138 copy = (char *)gv_alloc(length + 1);
139 memcpy(copy, original, length);
140
141 // `gv_alloc` has already zeroed the backing memory, so no need to manually
142 // add a NUL terminator
143
144#else
145 copy = strndup(original, length);
146#endif
147
148 if (copy == NULL) {
149 fprintf(stderr,
150 "out of memory when trying to allocate %" PRISIZE_T " bytes\n",
151 length + 1);
152 graphviz_exit(EXIT_FAILURE);
153 }
154
155 return copy;
156}
Agobj_t * copy(Agraph_t *g, Agobj_t *obj)
Definition actions.c:156
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
static char * gv_strdup(const char *original)
Definition alloc.h:101
static void * gv_realloc(void *ptr, size_t old_size, size_t new_size)
Definition alloc.h:49
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static char * gv_strndup(const char *original, size_t length)
Definition alloc.h:114
static void * gv_alloc(size_t size)
Definition alloc.h:47
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
void free(void *)
#define SIZE_MAX
Definition gmlscan.c:347
node NULL
Definition grammar.y:163
NEATOPROCS_API void s1(graph_t *, node_t *)
Definition stuff.c:671
#define PRISIZE_T
PRIu64 alike for printing size_t
Definition prisize_t.h:27