/src/graphicsmagick/magick/memory.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2025 GraphicsMagick Group |
3 | | % Copyright (C) 2002 ImageMagick Studio |
4 | | % Copyright 1991-1999 E. I. du Pont de Nemours and Company |
5 | | % |
6 | | % This program is covered by multiple licenses, which are described in |
7 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
8 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
9 | | % |
10 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
11 | | % % |
12 | | % % |
13 | | % % |
14 | | % M M EEEEE M M OOO RRRR Y Y % |
15 | | % MM MM E MM MM O O R R Y Y % |
16 | | % M M M EEE M M M O O RRRR Y % |
17 | | % M M E M M O O R R Y % |
18 | | % M M EEEEE M M OOO R R Y % |
19 | | % % |
20 | | % % |
21 | | % GraphicsMagick Memory Allocation Methods % |
22 | | % % |
23 | | % % |
24 | | % Software Design % |
25 | | % John Cristy % |
26 | | % July 1998 % |
27 | | % % |
28 | | % % |
29 | | % % |
30 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
31 | | % |
32 | | % |
33 | | % |
34 | | */ |
35 | | |
36 | | /* |
37 | | Include declarations. |
38 | | */ |
39 | | #include "magick/studio.h" |
40 | | #include "magick/resource.h" |
41 | | #include "magick/utility.h" |
42 | | |
43 | | #if defined(MAGICK_MEMORY_HARD_LIMIT) |
44 | | #define MEMORY_LIMIT_CHECK(func,size) \ |
45 | | do \ |
46 | | { \ |
47 | | if (0) fprintf(stderr,"%s: %zu\n", func, size); \ |
48 | | if (size > (size_t)MAGICK_MEMORY_HARD_LIMIT) \ |
49 | | { \ |
50 | | fprintf(stderr,"%s: Excessive allocation request %zu\n", func, size); \ |
51 | | abort(); \ |
52 | | } \ |
53 | | } while(0) |
54 | | #else |
55 | | #define MEMORY_LIMIT_CHECK(func,size) |
56 | | #endif /* MAGICK_MEMORY_HARD_LIMIT */ |
57 | | |
58 | | /* |
59 | | Static variables. |
60 | | */ |
61 | | static MagickFreeFunc FreeFunc = free; |
62 | | static MagickMallocFunc MallocFunc = malloc; |
63 | | static MagickReallocFunc ReallocFunc = realloc; |
64 | | |
65 | | /* |
66 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
67 | | % % |
68 | | % % |
69 | | % % |
70 | | % M a g i c k A l l o c F u n c t i o n s % |
71 | | % % |
72 | | % % |
73 | | % % |
74 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
75 | | % |
76 | | % MagickAllocFunctions() provides a way for the user to supply a preferred |
77 | | % free(), malloc(), and realloc() functions. Otherwise the default system |
78 | | % versions are used. If an alternative allocator is to be used, this |
79 | | % function should be invoked prior to invoking InitializeMagick(). |
80 | | % |
81 | | % The format of the MagickAllocFunctions method is: |
82 | | % |
83 | | % void MagickAllocFunctions(MagickFreeFunc free_func, |
84 | | % MagickMallocFunc malloc_func, |
85 | | % MagickReallocFunc realloc_func) |
86 | | % |
87 | | % A description of each parameter follows: |
88 | | % |
89 | | % o free_func: Function to free memory. |
90 | | % |
91 | | % o malloc_func: Function to allocate memory. |
92 | | % |
93 | | % o realloc_func: Function to reallocate memory. |
94 | | % |
95 | | */ |
96 | | MagickExport void MagickAllocFunctions(MagickFreeFunc free_func, |
97 | | MagickMallocFunc malloc_func, |
98 | | MagickReallocFunc realloc_func) |
99 | 0 | { |
100 | 0 | FreeFunc = free_func; |
101 | 0 | MallocFunc = malloc_func; |
102 | 0 | ReallocFunc = realloc_func; |
103 | 0 | } |
104 | | |
105 | | /* |
106 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
107 | | % % |
108 | | % % |
109 | | % % |
110 | | + M a g i c k A r r a y Si z e % |
111 | | % % |
112 | | % % |
113 | | % % |
114 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
115 | | % |
116 | | % MagickArraySize() returns the size of an array given two size_t arguments. |
117 | | % Zero is returned if the computed result overflows the size_t type. |
118 | | % |
119 | | % The format of the MagickArraySize method is: |
120 | | % |
121 | | % size_t MagickArraySize(const size_t count, const size_t size); |
122 | | % |
123 | | % A description of each parameter follows: |
124 | | % |
125 | | % o count: The number of elements in the array. |
126 | | % |
127 | | % o size: The size of one array element. |
128 | | % |
129 | | */ |
130 | | MagickExport size_t MagickArraySize(const size_t count, const size_t size) |
131 | 806M | { |
132 | 806M | size_t |
133 | 806M | allocation_size; |
134 | | |
135 | 806M | allocation_size = size * count; |
136 | 806M | if ((count != 0) && (size != allocation_size/count)) |
137 | 8 | allocation_size = 0; |
138 | | |
139 | 806M | return allocation_size; |
140 | 806M | } |
141 | | |
142 | | /* |
143 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
144 | | % % |
145 | | % % |
146 | | % % |
147 | | % M a g i c k M a l l o c % |
148 | | % % |
149 | | % % |
150 | | % % |
151 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
152 | | % |
153 | | % MagickMalloc() returns a pointer to a block of memory of at least size |
154 | | % bytes suitably aligned for any use. NULL is returned if insufficient |
155 | | % memory is available or the requested size is zero. |
156 | | % |
157 | | % The format of the MagickMalloc method is: |
158 | | % |
159 | | % void * MagickMalloc(const size_t size) |
160 | | % |
161 | | % A description of each parameter follows: |
162 | | % |
163 | | % o size: The size of the memory in bytes to allocate. |
164 | | % |
165 | | % |
166 | | */ |
167 | | MagickExport void * MagickMalloc(const size_t size) |
168 | 218M | { |
169 | 218M | if (size == 0) |
170 | 0 | return ((void *) NULL); |
171 | | |
172 | | /* fprintf(stderr,"%s %zu\n",__func__, size); */ |
173 | 218M | MEMORY_LIMIT_CHECK(GetCurrentFunction(),size); |
174 | | |
175 | 218M | return (MallocFunc)(size); |
176 | 218M | } |
177 | | |
178 | | /* |
179 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
180 | | % % |
181 | | % % |
182 | | % % |
183 | | % M a g i c k M a l l o c A l i g n e d % |
184 | | % % |
185 | | % % |
186 | | % % |
187 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
188 | | % |
189 | | % MagickMallocAligned() allocates memory and returns a pointer to a |
190 | | % block of memory capable of storing at least size bytes with the |
191 | | % allocation's base address being an even multiple of alignment. |
192 | | % The size of the buffer allocation is rounded up as required in |
193 | | % order to consume a block of memory starting at least at the requested |
194 | | % alignment and ending at at least the requested alignment. |
195 | | % |
196 | | % The requested alignment should be a power of 2 at least as large as |
197 | | % sizeof a void pointer. |
198 | | % |
199 | | % NULL is returned if insufficient memory is available, the requested |
200 | | % size is zero, or integer overflow was detected. |
201 | | % |
202 | | % This function is intended for allocating special-purpose buffers |
203 | | % which benefit from specific alignment. |
204 | | % |
205 | | % The allocated memory should only be freed using MagickFreeAligned() |
206 | | % and may not be reallocated. |
207 | | % |
208 | | % The format of the MagickMallocAligned method is: |
209 | | % |
210 | | % void * MagickMallocAligned(size_t alignment, const size_t size) |
211 | | % |
212 | | % A description of each parameter follows: |
213 | | % |
214 | | % |
215 | | % o alignment: The alignment of the base and size of the allocated |
216 | | % memory. |
217 | | % |
218 | | % o size: The size of the memory in bytes to allocate. |
219 | | % |
220 | | % |
221 | | */ |
222 | | MagickExport void * MagickMallocAligned(const size_t alignment,const size_t size) |
223 | 118M | { |
224 | 118M | size_t |
225 | 118M | alligned_size; |
226 | | |
227 | 118M | void |
228 | 118M | *alligned_p = 0; |
229 | | |
230 | | /* fprintf(stderr,"%s %zu\n",__func__, size); */ |
231 | 118M | MEMORY_LIMIT_CHECK(GetCurrentFunction(),size); |
232 | | |
233 | 118M | alligned_size=RoundUpToAlignment(size,alignment); |
234 | | |
235 | 118M | if ((size == 0) || (alignment < sizeof(void *)) || (alligned_size < size)) |
236 | 0 | return ((void *) NULL); |
237 | | |
238 | 118M | #if defined(HAVE_POSIX_MEMALIGN) |
239 | 118M | if (posix_memalign(&alligned_p, alignment, alligned_size) != 0) |
240 | 0 | alligned_p=0; |
241 | | #elif defined(HAVE__ALIGNED_MALLOC) |
242 | | alligned_p=_aligned_malloc(alligned_size,alignment); |
243 | | #else |
244 | | { |
245 | | void |
246 | | *alloc_p; |
247 | | |
248 | | size_t |
249 | | alloc_size; |
250 | | |
251 | | alloc_size=(size+alignment-1)+sizeof(void *); |
252 | | if (alloc_size > size) |
253 | | { |
254 | | if ((alloc_p = (MagickMalloc(alloc_size))) != NULL) |
255 | | { |
256 | | alligned_p=(void*) RoundUpToAlignment((magick_uintptr_t)alloc_p+ |
257 | | sizeof(void *),alignment); |
258 | | *((void **)alligned_p-1)=alloc_p; |
259 | | } |
260 | | } |
261 | | } |
262 | | #endif |
263 | | |
264 | 118M | return alligned_p; |
265 | 118M | } |
266 | | |
267 | | /* |
268 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
269 | | % % |
270 | | % % |
271 | | % % |
272 | | + M a g i c k M a l l o c A l i g n e d A r r a y % |
273 | | % % |
274 | | % % |
275 | | % % |
276 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
277 | | % |
278 | | % MagickMallocAlignedArray() returns a pointer to a block of memory of |
279 | | % sufficient size to support an array of elements of a specified size. |
280 | | % The allocation's base address is an even multiple of the specified |
281 | | % alignment. The size of the buffer allocation is rounded up as required |
282 | | % in order to consume a block of memory starting at least at the requested |
283 | | % alignment and ending at at least the requested alignment. |
284 | | % |
285 | | % NULL is returned if the required memory exceeds the range of size_t, |
286 | | % the computed size is zero, or there is insufficient memory available. |
287 | | % |
288 | | % This function is intended for allocating special-purpose buffers |
289 | | % which benefit from specific alignment. |
290 | | % |
291 | | % The allocated memory should only be freed using MagickFreeAligned() |
292 | | % and may not be reallocated. |
293 | | % |
294 | | % The format of the MagickMallocArray method is: |
295 | | % |
296 | | % void *MagickMallocAlignedArray(const size_t alignment, |
297 | | % const size_t count, |
298 | | % const size_t size); |
299 | | % |
300 | | % A description of each parameter follows: |
301 | | % |
302 | | % o alignment: The alignment of the base and size of the allocated |
303 | | % memory. |
304 | | % |
305 | | % o count: The number of elements in the array. |
306 | | % |
307 | | % o size: The size of one array element. |
308 | | % |
309 | | */ |
310 | | MagickExport void *MagickMallocAlignedArray(const size_t alignment, |
311 | | const size_t count, |
312 | | const size_t size) |
313 | 0 | { |
314 | 0 | size_t |
315 | 0 | allocation_size; |
316 | |
|
317 | 0 | void |
318 | 0 | *allocation; |
319 | |
|
320 | 0 | allocation = (void *) NULL; |
321 | 0 | allocation_size=MagickArraySize(count,size); |
322 | |
|
323 | 0 | if (allocation_size) |
324 | 0 | allocation = MagickMallocAligned(alignment,allocation_size); |
325 | |
|
326 | 0 | return allocation; |
327 | 0 | } |
328 | | |
329 | | /* |
330 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
331 | | % % |
332 | | % % |
333 | | % % |
334 | | + M a g i c k M a l l o c A r r a y % |
335 | | % % |
336 | | % % |
337 | | % % |
338 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
339 | | % |
340 | | % MagickMallocArray() returns a pointer to a block of memory of |
341 | | % sufficient size to support an array of elements of a specified size. |
342 | | % The returned memory is suitably aligned for any use. NULL is returned |
343 | | % if the required memory exceeds the range of size_t, the specified size |
344 | | % is zero, or there is insufficient memory available. |
345 | | % |
346 | | % The format of the MagickMallocArray method is: |
347 | | % |
348 | | % void *MagickMallocArray(const size_t count, const size_t size); |
349 | | % |
350 | | % A description of each parameter follows: |
351 | | % |
352 | | % o count: The number of elements in the array. |
353 | | % |
354 | | % o size: The size of one array element. |
355 | | % |
356 | | */ |
357 | | MagickExport void *MagickMallocArray(const size_t count,const size_t size) |
358 | 19.2M | { |
359 | 19.2M | size_t |
360 | 19.2M | allocation_size; |
361 | | |
362 | 19.2M | void |
363 | 19.2M | *allocation; |
364 | | |
365 | 19.2M | allocation = (void *) NULL; |
366 | 19.2M | allocation_size=MagickArraySize(count,size); |
367 | | |
368 | 19.2M | if (allocation_size) |
369 | 19.2M | allocation = MagickMalloc(allocation_size); |
370 | 19.2M | return allocation; |
371 | 19.2M | } |
372 | | |
373 | | /* |
374 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
375 | | % % |
376 | | % % |
377 | | % % |
378 | | % M a g i c k M a l l o c C l e a r e d % |
379 | | % % |
380 | | % % |
381 | | % % |
382 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
383 | | % |
384 | | % MagickMallocCleared() returns a pointer to a block of memory of at least |
385 | | % size bytes suitably aligned for any use. NULL is returned if insufficient |
386 | | % memory is available or the requested size is zero. This version differs |
387 | | % from MagickMalloc in that the allocated bytes are cleared to zero. |
388 | | % |
389 | | % The format of the MagickMallocCleared method is: |
390 | | % |
391 | | % void * MagickMallocCleared(const size_t size) |
392 | | % |
393 | | % A description of each parameter follows: |
394 | | % |
395 | | % o size: The size of the memory in bytes to allocate. |
396 | | % |
397 | | % |
398 | | */ |
399 | | MagickExport void * MagickMallocCleared(const size_t size) |
400 | 34.7M | { |
401 | 34.7M | void |
402 | 34.7M | *p = (void *) NULL; |
403 | | |
404 | 34.7M | if (size != 0) |
405 | 34.7M | { |
406 | 34.7M | p=MagickMalloc(size); |
407 | | |
408 | 34.7M | if (p != (void *) NULL) |
409 | 34.7M | (void) memset(p,0,size); |
410 | 34.7M | } |
411 | | |
412 | 34.7M | return p; |
413 | 34.7M | } |
414 | | |
415 | | /* |
416 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
417 | | % % |
418 | | % % |
419 | | % % |
420 | | % M a g i c k C l o n e M e m o r y % |
421 | | % % |
422 | | % % |
423 | | % % |
424 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
425 | | % |
426 | | % MagickCloneMemory() copies size bytes from memory area source to the |
427 | | % destination. Copying between objects that overlap will take place |
428 | | % correctly. It returns destination. |
429 | | % |
430 | | % The format of the MagickCloneMemory method is: |
431 | | % |
432 | | % void *MagickCloneMemory(void *destination,const void *source, |
433 | | % const size_t size) |
434 | | % |
435 | | % A description of each parameter follows: |
436 | | % |
437 | | % o size: The size of the memory in bytes to allocate. |
438 | | % |
439 | | % |
440 | | */ |
441 | | MagickExport void *MagickCloneMemory(void *destination,const void *source, |
442 | | const size_t size) |
443 | 0 | { |
444 | 0 | unsigned char |
445 | 0 | *d=(unsigned char*) destination; |
446 | |
|
447 | 0 | const unsigned char |
448 | 0 | *s=(const unsigned char*) source; |
449 | |
|
450 | 0 | assert(destination != (void *) NULL); |
451 | 0 | assert(source != (const void *) NULL); |
452 | |
|
453 | 0 | if (((d+size) < s) || (d > (s+size))) |
454 | 0 | return(memcpy(destination,source,size)); |
455 | | |
456 | 0 | return(memmove(destination,source,size)); |
457 | 0 | } |
458 | | |
459 | | /* |
460 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
461 | | % % |
462 | | % % |
463 | | % % |
464 | | % M a g i c k R e a l l o c % |
465 | | % % |
466 | | % % |
467 | | % % |
468 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
469 | | % |
470 | | % MagickRealloc() changes the size of the memory and returns a pointer to |
471 | | % the (possibly moved) block. The contents will be unchanged up to the |
472 | | % lesser of the new and old sizes. If size is zero, then the memory is |
473 | | % freed and a NULL value is returned. If the memory allocation fails, then |
474 | | % a NULL value is returned. |
475 | | % |
476 | | % Note that the behavior of this function is similar to ANSI C realloc(3). |
477 | | % If NULL is returned, then the original memory pointer value is still |
478 | | % valid. |
479 | | % |
480 | | % The behavor of this function has changed given that it used to free the |
481 | | % memory upon allocation failure. This dubious responsibility has now been |
482 | | % delegated to the MagickReallocMemory() macro. |
483 | | % |
484 | | % The format of the MagickRealloc method is: |
485 | | % |
486 | | % void *MagickRealloc(void *memory,const size_t size) |
487 | | % |
488 | | % A description of each parameter follows: |
489 | | % |
490 | | % o memory: A pointer to a memory allocation. |
491 | | % |
492 | | % o size: The new size of the allocated memory. |
493 | | % |
494 | | */ |
495 | | MagickExport void *MagickRealloc(void *memory,const size_t size) |
496 | 4.06M | { |
497 | 4.06M | void |
498 | 4.06M | *new_memory = (void *) NULL; |
499 | | |
500 | 4.06M | MEMORY_LIMIT_CHECK(GetCurrentFunction(),size); |
501 | | |
502 | 4.06M | if ((void *) NULL == memory) |
503 | 761k | new_memory = (MallocFunc)(size); |
504 | 3.29M | else |
505 | 3.29M | new_memory = (ReallocFunc)(memory,size); |
506 | 4.06M | if ((new_memory == 0) && (memory != 0) && (size != 0)) |
507 | 0 | MagickFree(memory); |
508 | | |
509 | 4.06M | return new_memory; |
510 | 4.06M | } |
511 | | |
512 | | /* |
513 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
514 | | % % |
515 | | % % |
516 | | % % |
517 | | % M a g i c k F r e e % |
518 | | % % |
519 | | % % |
520 | | % % |
521 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
522 | | % |
523 | | % MagickFree() frees memory that has already been allocated by |
524 | | % MagickMalloc() or other other other allocators directly compatible |
525 | | % with the currently defined memory allocator (which defaults to the |
526 | | % system malloc()). For convenience, a NULL argument is ignored. |
527 | | % |
528 | | % The format of the MagickFree method is: |
529 | | % |
530 | | % void MagickFree(void *memory) |
531 | | % |
532 | | % A description of each parameter follows: |
533 | | % |
534 | | % o memory: A pointer to a block of memory to free for reuse. |
535 | | % |
536 | | % |
537 | | */ |
538 | | MagickExport void MagickFree(void *memory) |
539 | 1.30G | { |
540 | 1.30G | if (memory != (void *) NULL) |
541 | 706M | (FreeFunc)(memory); |
542 | 1.30G | } |
543 | | |
544 | | /* |
545 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
546 | | % % |
547 | | % % |
548 | | % % |
549 | | % M a g i c k F r e e A l i g n e d % |
550 | | % % |
551 | | % % |
552 | | % % |
553 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
554 | | % |
555 | | % MagickFreeAligned() frees aligned memory that has previously been |
556 | | % allocated via MagickMallocAligned(). For convenience, a NULL argument is |
557 | | % ignored. |
558 | | % |
559 | | % This function exists in case the pointer allocated by |
560 | | % MagickMallocAligned() can not be used directly with MagickFree(). |
561 | | % |
562 | | % The format of the MagickFreeAligned method is: |
563 | | % |
564 | | % void MagickFreeAligned(void *memory) |
565 | | % |
566 | | % A description of each parameter follows: |
567 | | % |
568 | | % o memory: A pointer to a block of memory to free for reuse. |
569 | | % |
570 | | % |
571 | | */ |
572 | | MagickExport void MagickFreeAligned(void *memory) |
573 | 141M | { |
574 | 141M | if (memory != (void *) NULL) |
575 | 118M | { |
576 | 118M | #if defined (HAVE_POSIX_MEMALIGN) |
577 | 118M | MagickFree(memory); |
578 | | #elif defined(HAVE__ALIGNED_MALLOC) |
579 | | /* Windows Studio .NET 2003 or later */ |
580 | | _aligned_free(memory); |
581 | | #else |
582 | | MagickFree(*((void **)memory-1)); |
583 | | #endif |
584 | 118M | } |
585 | 141M | } |
586 | | |
587 | | /* |
588 | | Structure for tracking resource-limited memory allocation. |
589 | | */ |
590 | | typedef struct _MagickMemoryResource_T |
591 | | { |
592 | | void *memory; /* Pointer to memory allocation */ |
593 | | size_t alloc_size_initial; /* Initially requested allocation size */ |
594 | | size_t alloc_size; /* Requested allocation size */ |
595 | | size_t alloc_size_limit; /* Limit on maximum alloc_size */ |
596 | | size_t alloc_size_real; /* Real/underlying allocation size */ |
597 | | const char *alloc_module; /* Source file of first allocation */ |
598 | | const char *alloc_function; /* Name of function which made first allocation */ |
599 | | unsigned int alloc_line; /* Source file line of first allocation */ |
600 | | size_t num_realloc; /* Number of actual reallocations performed */ |
601 | | size_t num_realloc_limit; /* Limit on number of reallocations */ |
602 | | size_t num_realloc_moves; /* Number of reallocations which moved memory */ |
603 | | size_t num_realloc_moves_limit; /* Limit on number of reallocations which required move */ |
604 | | size_t realloc_octets_moved; /* Number of octets moved by reallocations */ |
605 | | size_t signature; /* Initialized to MagickSignature */ |
606 | | |
607 | | } MagickMemoryResource_T; |
608 | | |
609 | | #if !defined(MAGICK_DEBUG_RL_MEMORY) |
610 | | #define MAGICK_DEBUG_RL_MEMORY 0 |
611 | | #endif /* if !defined(MAGICK_DEBUG_RL_MEMORY) */ |
612 | | |
613 | | /* Return MemoryResource_T pointer given user-land pointer */ |
614 | | #define MagickAccessMemoryResource_T_From_Pub(p) \ |
615 | 377M | ((MagickMemoryResource_T *) ((char *) p-sizeof(MagickMemoryResource_T))) |
616 | | |
617 | | /* Return user-land pointer given private base allocation pointer */ |
618 | | #define UserLandPointerGivenBaseAlloc(p) \ |
619 | 377M | ((char *)p+sizeof(MagickMemoryResource_T)) |
620 | | |
621 | | /* Copy (or init) MagickMemoryResource_T based on provided user-land pointer */ |
622 | | #define MagickCopyMemoryResource_T_From_Pub(module,function,line,memory_resource, p) \ |
623 | 781M | do { \ |
624 | 781M | if (p != 0) \ |
625 | 781M | { \ |
626 | 377M | assert(((ptrdiff_t) p - sizeof(MagickMemoryResource_T)) > 0); \ |
627 | 377M | (void) memcpy(memory_resource, \ |
628 | 377M | (void *) MagickAccessMemoryResource_T_From_Pub(p), \ |
629 | 377M | sizeof(MagickMemoryResource_T)); \ |
630 | 377M | assert((memory_resource)->signature == MagickSignature); \ |
631 | 377M | } \ |
632 | 781M | else \ |
633 | 781M | { \ |
634 | 404M | (memory_resource)->memory = 0; \ |
635 | 404M | (memory_resource)->alloc_size_initial = 0; \ |
636 | 404M | (memory_resource)->alloc_size = 0; \ |
637 | 404M | (memory_resource)->alloc_size_limit = SIZE_MAX; \ |
638 | 404M | (memory_resource)->alloc_size_real = 0; \ |
639 | 404M | (memory_resource)->alloc_module = module; \ |
640 | 404M | (memory_resource)->alloc_function = function; \ |
641 | 404M | (memory_resource)->alloc_line = line; \ |
642 | 404M | (memory_resource)->num_realloc = 0; \ |
643 | 404M | (memory_resource)->num_realloc_limit = SIZE_MAX; \ |
644 | 404M | (memory_resource)->num_realloc_moves = 0; \ |
645 | 404M | (memory_resource)->num_realloc_moves_limit = SIZE_MAX; \ |
646 | 404M | (memory_resource)->realloc_octets_moved = 0; \ |
647 | 404M | (memory_resource)->signature = MagickSignature; \ |
648 | 404M | } \ |
649 | 781M | } while(0) |
650 | | |
651 | | /* Trace MemoryResource_T content given a pointer to it */ |
652 | | #if defined(MAGICK_DEBUG_RL_MEMORY) && MAGICK_DEBUG_RL_MEMORY |
653 | | #define TraceMagickAccessMemoryResource_T(module,function,line,operation,memory_resource) \ |
654 | | fprintf(stderr,"%s/%s/%u: - %s memory_resource: memory=%p (user %p)," \ |
655 | | " alloc_size_initial=%zu," \ |
656 | | " alloc_size=%zu," \ |
657 | | " alloc_size_real=%zu," \ |
658 | | " alloc_module=%s," \ |
659 | | " alloc_function=%s," \ |
660 | | " alloc_line=%u," \ |
661 | | " num_realloc=%zu," \ |
662 | | " num_realloc_moves=%zu," \ |
663 | | " realloc_octets_moved=%zu\n", \ |
664 | | module, \ |
665 | | function, \ |
666 | | line, \ |
667 | | operation, \ |
668 | | (memory_resource)->memory, \ |
669 | | (memory_resource)->memory ? UserLandPointerGivenBaseAlloc((memory_resource)->memory) : 0, \ |
670 | | (memory_resource)->alloc_size_initial, \ |
671 | | (memory_resource)->alloc_size, \ |
672 | | (memory_resource)->alloc_size_real, \ |
673 | | (memory_resource)->alloc_module, \ |
674 | | (memory_resource)->alloc_function, \ |
675 | | (memory_resource)->alloc_line, \ |
676 | | (memory_resource)->num_realloc, \ |
677 | | (memory_resource)->num_realloc_moves, \ |
678 | | (memory_resource)->realloc_octets_moved); |
679 | | #else |
680 | 1.96G | #define TraceMagickAccessMemoryResource_T(module,function,line,operation,memory_resource) ; |
681 | | #endif |
682 | | |
683 | | /* |
684 | | Clean up a MagickMemoryResource_T, releasing referenced memory and |
685 | | resource allocation. Not safe if embedded in the memory buffer |
686 | | being released! |
687 | | */ |
688 | | static void _MagickFreeResourceLimitedMemory_T(const char *module,const char *function,const unsigned int line, |
689 | | MagickMemoryResource_T *memory_resource) |
690 | 404M | { |
691 | 404M | TraceMagickAccessMemoryResource_T(module,function,line,"FREE",memory_resource); |
692 | 404M | #if !(defined(MAGICK_DEBUG_RL_MEMORY) && MAGICK_DEBUG_RL_MEMORY) |
693 | 404M | (void) module; |
694 | 404M | (void) function; |
695 | 404M | (void) line; |
696 | 404M | #endif |
697 | | #if defined(MAGICK_MEMORY_LOG_REALLOC_STATS) && MAGICK_MEMORY_LOG_REALLOC_STATS |
698 | | if (memory_resource->num_realloc > 0) |
699 | | { |
700 | | const char |
701 | | *alloc_module, |
702 | | *modulebase; |
703 | | |
704 | | /* fixup module info to just include the filename - and not the |
705 | | whole path to the file. This makes the log huge for no good |
706 | | reason */ |
707 | | alloc_module=(memory_resource)->alloc_module; |
708 | | for (modulebase=alloc_module+strlen(alloc_module)-1; modulebase > alloc_module; modulebase--) |
709 | | if (IsBasenameSeparator(*modulebase)) |
710 | | { |
711 | | modulebase++; |
712 | | break; |
713 | | } |
714 | | |
715 | | fprintf(stderr, |
716 | | "%s/%s/%u FreeResourceLimitedMemory:" |
717 | | " alloc_initial=%zu," |
718 | | " alloc_size=%zu," |
719 | | " alloc_size_real=%zu," |
720 | | " num_realloc=%zu," |
721 | | " num_realloc_moves=%zu," |
722 | | " realloc_octets_moved=%zu\n", |
723 | | modulebase, |
724 | | (memory_resource)->alloc_function, |
725 | | (memory_resource)->alloc_line, |
726 | | (memory_resource)->alloc_size_initial, |
727 | | (memory_resource)->alloc_size, |
728 | | (memory_resource)->alloc_size_real+sizeof(MagickMemoryResource_T), |
729 | | (memory_resource)->num_realloc, |
730 | | (memory_resource)->num_realloc_moves, |
731 | | (memory_resource)->realloc_octets_moved); |
732 | | } |
733 | | #endif /* defined(MAGICK_MEMORY_LOG_REALLOC_STATS) && MAGICK_MEMORY_LOG_REALLOC_STATS */ |
734 | 404M | if (memory_resource->memory != 0) |
735 | 368M | { |
736 | 368M | MagickFree(memory_resource->memory); |
737 | 368M | memory_resource->memory=0; |
738 | 368M | } |
739 | 404M | if (memory_resource->alloc_size != 0) |
740 | 368M | LiberateMagickResource(MemoryResource, memory_resource->alloc_size); |
741 | 404M | memory_resource->alloc_size_real = 0; |
742 | 404M | memory_resource->alloc_size_limit = SIZE_MAX; |
743 | 404M | memory_resource->alloc_size_initial = 0; |
744 | 404M | memory_resource->alloc_size = 0; |
745 | 404M | memory_resource->num_realloc = 0; |
746 | 404M | memory_resource->num_realloc_limit = SIZE_MAX; |
747 | 404M | memory_resource->num_realloc_moves = 0; |
748 | 404M | memory_resource->num_realloc_moves_limit = SIZE_MAX; |
749 | 404M | memory_resource->realloc_octets_moved = 0; |
750 | 404M | } |
751 | | |
752 | | |
753 | | /* |
754 | | Reallocate resource-limited array memory based on pointer to |
755 | | existing allocation, object count, and object size. Freshly |
756 | | allocated memory is cleared to zero if the clear flag is set. |
757 | | |
758 | | This works like MagickRealloc() except for supporting count and size |
759 | | arguments similar to calloc(). GNU libc has a reallocarray() |
760 | | function using similar arguments. A pointer to the (possibly) new |
761 | | allocation is returned, so if NULL is returned, the previous pointer |
762 | | remains valid, similar to realloc(). |
763 | | |
764 | | Alignment concerns: 128-bit SSE registers have an alignment |
765 | | requirement of 16 bytes, the 256-bit Intel AVX registers have an |
766 | | alignment requirement of 32 bytes, and the 512-bit Intel AVX-512 |
767 | | registers have an alignment requirement of 64 bytes, that is. |
768 | | |
769 | | Linux malloc produces allocations aligned to 16-bytes. |
770 | | */ |
771 | | |
772 | | MagickExport void *_MagickReallocateResourceLimitedMemoryLoc(void *p, |
773 | | const size_t count, |
774 | | const size_t size, |
775 | | const MagickBool clear, |
776 | | const char *module, |
777 | | const char *function, |
778 | | const unsigned int line) |
779 | 781M | { |
780 | 781M | MagickMemoryResource_T memory_resource; |
781 | 781M | size_t size_diff; |
782 | 781M | const size_t new_size = MagickArraySize(count,size); |
783 | 781M | void *res; |
784 | 781M | MagickPassFail |
785 | 781M | status = MagickPass; |
786 | | |
787 | | #if defined(MAGICK_DEBUG_RL_MEMORY) && MAGICK_DEBUG_RL_MEMORY |
788 | | fprintf(stderr,"%s/%s/%u: p = %p, count = %zu, size = %zu\n", module, function, line, p, count, size); |
789 | | #endif |
790 | | |
791 | | /* Copy (or init) 'memory_resource' based on provided user-land pointer */ |
792 | 781M | MagickCopyMemoryResource_T_From_Pub(module,function,line,&memory_resource, p); |
793 | 781M | TraceMagickAccessMemoryResource_T(module,function,line,"BEFORE",&memory_resource); |
794 | | |
795 | 781M | do |
796 | 781M | { |
797 | 781M | if (((new_size == 0) && (count != 0) && (size != 0)) || |
798 | 781M | (new_size > SIZE_MAX/2) || |
799 | 781M | (SIZE_MAX-new_size <= sizeof(MagickMemoryResource_T)) || |
800 | 781M | (new_size > memory_resource.alloc_size_limit)) |
801 | 292 | { |
802 | | /* Memory allocation FAILED */ |
803 | 292 | #if defined(ENOMEM) |
804 | 292 | errno = ENOMEM; |
805 | 292 | #endif /* if defined(ENOMEM) */ |
806 | 292 | status = MagickFail; |
807 | 292 | break; |
808 | 292 | } |
809 | 781M | else if (new_size == 0) |
810 | 404M | { |
811 | | /* Deallocate all allocated memory (if any) */ |
812 | 404M | _MagickFreeResourceLimitedMemory_T(module,function,line,&memory_resource); |
813 | 404M | break; |
814 | 404M | } |
815 | 377M | else if (new_size > memory_resource.alloc_size) |
816 | 373M | { |
817 | | /* Allocate or enlarge memory */ |
818 | 373M | size_diff = new_size - memory_resource.alloc_size; |
819 | 373M | if (AcquireMagickResource(MemoryResource,size_diff) == MagickPass) |
820 | 373M | { |
821 | 373M | if (new_size > memory_resource.alloc_size_real) |
822 | 369M | { |
823 | 369M | void *realloc_memory; |
824 | 369M | size_t realloc_size = new_size+sizeof(MagickMemoryResource_T); |
825 | 369M | if (memory_resource.alloc_size_real != 0) |
826 | 1.35M | { |
827 | | /* This is a realloc */ |
828 | | |
829 | | /* If number of allocations will exceed reallocation limit */ |
830 | 1.35M | if (memory_resource.num_realloc+1U > memory_resource.num_realloc_limit) |
831 | 0 | { |
832 | | /* Force a de-alloc, resulting in "Memory re-allocation FAILED" */ |
833 | 0 | realloc_size = 0; |
834 | 0 | } |
835 | 1.35M | else |
836 | 1.35M | { |
837 | | /* Round up underlying allocation sizes in |
838 | | order to lessen realloc calls and lessen |
839 | | memory moves. |
840 | | */ |
841 | | /* realloc_size <<= 1; */ |
842 | 1.35M | MagickRoundUpStringLength(realloc_size); |
843 | 1.35M | } |
844 | 1.35M | } |
845 | 369M | realloc_memory = (ReallocFunc)(memory_resource.memory, |
846 | 369M | realloc_size); |
847 | | /* If number of realloc moves exceeds num_realloc_moves_limit */ |
848 | 369M | if ((realloc_memory != 0) && (memory_resource.alloc_size_real != 0) && |
849 | 1.35M | (realloc_memory != memory_resource.memory)) |
850 | 1.08M | { |
851 | 1.08M | if (memory_resource.num_realloc_moves+1U > memory_resource.num_realloc_moves_limit) |
852 | 0 | { |
853 | | /* Deallocate all allocated memory*/ |
854 | 0 | realloc_memory = (ReallocFunc)(memory_resource.memory,0); |
855 | 0 | } |
856 | 1.08M | } |
857 | 369M | if ((realloc_memory != 0) && (realloc_size != 0)) |
858 | 369M | { |
859 | 369M | if (clear) |
860 | 497k | (void) memset(UserLandPointerGivenBaseAlloc(realloc_memory)+ |
861 | 497k | memory_resource.alloc_size,0,size_diff); |
862 | | |
863 | | /* A realloc has pre-existing memory */ |
864 | 369M | if (memory_resource.alloc_size_real != 0) |
865 | 1.35M | { |
866 | | /* Tally actual reallocations */ |
867 | 1.35M | memory_resource.num_realloc++; |
868 | | /* Tally reallocations which resulted in a memory move */ |
869 | 1.35M | if (realloc_memory != memory_resource.memory) |
870 | 1.08M | { |
871 | 1.08M | memory_resource.num_realloc_moves++; |
872 | 1.08M | memory_resource.realloc_octets_moved += |
873 | 1.08M | memory_resource.alloc_size_real+sizeof(MagickMemoryResource_T); |
874 | 1.08M | } |
875 | 1.35M | } |
876 | 369M | memory_resource.memory = realloc_memory; |
877 | 369M | if (memory_resource.alloc_size == 0) |
878 | 368M | memory_resource.alloc_size_initial = new_size; |
879 | 369M | memory_resource.alloc_size = new_size; |
880 | 369M | memory_resource.alloc_size_real = realloc_size-sizeof(MagickMemoryResource_T); |
881 | 369M | } |
882 | 0 | else |
883 | 0 | { |
884 | | /* Memory re-allocation FAILED */ |
885 | 0 | #if defined(ENOMEM) |
886 | 0 | errno = ENOMEM; |
887 | 0 | #endif /* if defined(ENOMEM) */ |
888 | 0 | status = MagickFail; |
889 | 0 | } |
890 | 369M | } |
891 | 4.11M | else |
892 | 4.11M | { |
893 | 4.11M | if (clear) |
894 | 6.02k | (void) memset(UserLandPointerGivenBaseAlloc(memory_resource.memory)+ |
895 | 6.02k | memory_resource.alloc_size,0,size_diff); |
896 | | |
897 | | /* Re-allocation is not required */ |
898 | 4.11M | memory_resource.alloc_size = new_size; |
899 | 4.11M | } |
900 | 373M | } |
901 | 763 | else |
902 | 763 | { |
903 | | /* |
904 | | Acquire memory resource FAILED. If this was a |
905 | | realloc, it is expected that the original pointer is |
906 | | valid and retained by the user, who will responsibly |
907 | | free it so its resource allocation will be released |
908 | | later. |
909 | | */ |
910 | 763 | #if defined(ENOMEM) |
911 | 763 | errno = ENOMEM; |
912 | 763 | #endif /* if defined(ENOMEM) */ |
913 | 763 | status = MagickFail; |
914 | 763 | } |
915 | 373M | break; |
916 | 373M | } |
917 | 3.32M | else if (new_size < memory_resource.alloc_size) |
918 | 484k | { |
919 | | /* Reduce memory */ |
920 | 484k | size_diff = memory_resource.alloc_size - new_size; |
921 | 484k | LiberateMagickResource(MemoryResource,size_diff); |
922 | 484k | memory_resource.alloc_size = new_size; |
923 | | /* FIXME: Maybe actually realloc to smaller size here? */ |
924 | 484k | break; |
925 | 484k | } |
926 | 781M | } while (0); |
927 | | |
928 | 781M | if (memory_resource.memory != 0) |
929 | 377M | { |
930 | 377M | (void) memcpy((void *) memory_resource.memory,&memory_resource, |
931 | 377M | sizeof(MagickMemoryResource_T)); |
932 | 377M | } |
933 | 781M | TraceMagickAccessMemoryResource_T(module,function,line,"AFTER",&memory_resource); |
934 | | |
935 | 781M | res = ((status == MagickPass) && memory_resource.memory) ? |
936 | 404M | UserLandPointerGivenBaseAlloc(memory_resource.memory) : 0; |
937 | | |
938 | 781M | return res; |
939 | 781M | } |
940 | | |
941 | | MagickExport void *_MagickReallocateResourceLimitedMemory(void *p, |
942 | | const size_t count, |
943 | | const size_t size, |
944 | | const MagickBool clear) |
945 | 0 | { |
946 | 0 | return _MagickReallocateResourceLimitedMemoryLoc(p,count,size,clear,GetMagickModule()); |
947 | 0 | } |
948 | | |
949 | | /* |
950 | | Allocate resource-limited memory. Similar to MagickMalloc(). |
951 | | |
952 | | Memory must be released using MagickFreeMemoryResource(). |
953 | | */ |
954 | | MagickExport void *_MagickAllocateResourceLimitedMemoryLoc(const size_t size, |
955 | | const char *module, |
956 | | const char *function, |
957 | | const unsigned int line) |
958 | 333M | { |
959 | 333M | return _MagickReallocateResourceLimitedMemoryLoc(0,1,size,MagickFalse,module,function,line); |
960 | 333M | } |
961 | | |
962 | | MagickExport void *_MagickAllocateResourceLimitedMemory(const size_t size) |
963 | 0 | { |
964 | 0 | return _MagickAllocateResourceLimitedMemoryLoc(size,GetMagickModule()); |
965 | 0 | } |
966 | | |
967 | | /* |
968 | | Free resource-limited memory which was allocated by |
969 | | MagickReallocMemoryResource() or MagickMallocMemoryResource(). |
970 | | |
971 | | Similar to MagickFree(). |
972 | | */ |
973 | | MagickExport void _MagickFreeResourceLimitedMemoryLoc(void *p, |
974 | | const char *module,const char *function,const unsigned int line) |
975 | 275M | { |
976 | 275M | _MagickReallocateResourceLimitedMemoryLoc(p,0,0,MagickFalse,module,function,line); |
977 | 275M | } |
978 | | |
979 | | MagickExport void _MagickFreeResourceLimitedMemory(void *p) |
980 | 0 | { |
981 | 0 | _MagickFreeResourceLimitedMemoryLoc(p,GetMagickModule()); |
982 | 0 | } |
983 | | |
984 | | /* |
985 | | Get current resource-limited memory size attribute (or defaulted value if NULL) |
986 | | */ |
987 | | MagickExport size_t _MagickResourceLimitedMemoryGetSizeAttribute(const void *p, |
988 | | const MagickAllocateResourceLimitedMemoryAttribute attr) |
989 | 0 | { |
990 | 0 | MagickMemoryResource_T memory_resource; |
991 | 0 | size_t result = 0; |
992 | | |
993 | | /* Copy (or init) 'memory_resource' based on provided user-land pointer */ |
994 | 0 | MagickCopyMemoryResource_T_From_Pub(__FILE__,GetCurrentFunction(),__LINE__,&memory_resource, p); |
995 | |
|
996 | 0 | switch (attr) |
997 | 0 | { |
998 | 0 | case ResourceLimitedMemoryAttributeAllocSize: |
999 | | /* Currently requested allocation size */ |
1000 | 0 | result = memory_resource.alloc_size; |
1001 | 0 | break; |
1002 | 0 | case ResourceLimitedMemoryAttributeAllocSizeReal: |
1003 | | /* Actual underlying requested allocation size */ |
1004 | 0 | result = memory_resource.alloc_size_real; |
1005 | 0 | break; |
1006 | 0 | case ResourceLimitedMemoryAttributeAllocNumReallocs: |
1007 | | /* Number of reallocations performed */ |
1008 | 0 | result = memory_resource.num_realloc; |
1009 | 0 | break; |
1010 | 0 | case ResourceLimitedMemoryAttributeAllocNumReallocsMoved: |
1011 | | /* Number of reallocations which moved memory (pointer change) */ |
1012 | 0 | result = memory_resource.num_realloc_moves; |
1013 | 0 | break; |
1014 | 0 | case ResourceLimitedMemoryAttributeAllocReallocOctetsMoved: |
1015 | | /* Total number of octets moved due to reallocations (may overflow!) */ |
1016 | 0 | result = memory_resource.realloc_octets_moved; |
1017 | 0 | break; |
1018 | 0 | } |
1019 | | |
1020 | 0 | return result; |
1021 | 0 | } |
1022 | | |
1023 | | /* |
1024 | | Set a per-allocation resource limit given a pointer to an allocation |
1025 | | */ |
1026 | | MagickExport void _SetMagickResourceLimitedMemoryLimitP(void *p, |
1027 | | MagickResourceLimitedMemoryLimitType type, |
1028 | | const size_t limit) |
1029 | 0 | { |
1030 | 0 | MagickMemoryResource_T *memory_resource; |
1031 | |
|
1032 | 0 | memory_resource = MagickAccessMemoryResource_T_From_Pub(p); |
1033 | |
|
1034 | 0 | switch (type) |
1035 | 0 | { |
1036 | 0 | case MagickResourceLimitedMemoryAllocSizeLimit: |
1037 | 0 | memory_resource->alloc_size_limit=limit; |
1038 | 0 | break; |
1039 | 0 | case MagickResourceLimitedMemoryNumReallocLimit: |
1040 | 0 | memory_resource->num_realloc_limit=limit; |
1041 | 0 | break; |
1042 | 0 | case MagickResourceLimitedMemoryNumReallocMovesLimit: |
1043 | 0 | memory_resource->num_realloc_moves=limit; |
1044 | 0 | break; |
1045 | 0 | } |
1046 | 0 | } |