-
Notifications
You must be signed in to change notification settings - Fork 2
libap: expand xmalloc family to full gnulib-compatible set #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <stdio.h> | ||
| #include <stddef.h> | ||
| #include <xalloc.h> | ||
|
|
||
| /* Called on allocation failure. Programs may override this. */ | ||
|
|
@@ -38,6 +39,31 @@ xrealloc(void *p, size_t n) | |
| return p; | ||
| } | ||
|
|
||
| /* Reallocate P as an array of N objects of S bytes each, with error checking. */ | ||
| void * | ||
| xreallocarray(void *p, size_t n, size_t s) | ||
| { | ||
| void *r = reallocarray(p, n, s); | ||
| if(!r && n != 0 && s != 0) | ||
| xalloc_die(); | ||
| return r; | ||
| } | ||
|
|
||
| /* Allocate an array of N objects of S bytes each, with error checking. */ | ||
| void * | ||
| xnmalloc(size_t n, size_t s) | ||
| { | ||
| return xreallocarray(NULL, n, s); | ||
| } | ||
|
|
||
| /* Resize P to an array of N objects of S bytes each, with error checking. | ||
| Unlike x2nrealloc, this resizes to exactly N — it does not grow. */ | ||
| void * | ||
| xnrealloc(void *p, size_t n, size_t s) | ||
| { | ||
| return xreallocarray(p, n, s); | ||
| } | ||
|
|
||
| void * | ||
| xmemdup(const void *src, size_t n) | ||
| { | ||
|
|
@@ -46,6 +72,18 @@ xmemdup(const void *src, size_t n) | |
| return p; | ||
| } | ||
|
|
||
| char * | ||
| xcharalloc(size_t n) | ||
| { | ||
| return xmalloc(n); | ||
| } | ||
|
|
||
| void * | ||
| xzalloc(size_t s) | ||
| { | ||
| return xcalloc(s, 1); | ||
| } | ||
|
|
||
| char * | ||
| xstrdup(const char *s) | ||
| { | ||
|
|
@@ -64,20 +102,70 @@ xstrndup(const char *s, size_t n) | |
| return p; | ||
| } | ||
|
|
||
| /* | ||
| * xnrealloc - realloc *pp to hold at least *pn elements of size s, | ||
| * doubling *pn each time. Useful for growing arrays. | ||
| */ | ||
| /* Grow P (array of *PN objects of S bytes) by ~1.5x, with error checking. | ||
| If P is null, allocate an initial block sized for the default fast path. */ | ||
| void * | ||
| xnrealloc(void *p, size_t *pn, size_t s) | ||
| x2nrealloc(void *p, size_t *pn, size_t s) | ||
| { | ||
| size_t n = *pn; | ||
| if(n == 0) | ||
| n = 1; | ||
| else if(n > (size_t)-1 / 2 / s) | ||
| xalloc_die(); | ||
| else | ||
| n *= 2; | ||
|
|
||
| if(!p) { | ||
| enum { DEFAULT_MXFAST = 64 * sizeof(size_t) / 4 }; | ||
| if(!n) { | ||
| n = DEFAULT_MXFAST / s; | ||
| n += !n; | ||
| } | ||
|
Comment on lines
+114
to
+117
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } else { | ||
| /* n = floor(1.5 * n) + 1, checking for overflow */ | ||
| size_t incr = (n >> 1) + 1; | ||
| if(n > (size_t)-1 - incr) | ||
| xalloc_die(); | ||
| n += incr; | ||
| } | ||
| p = xreallocarray(p, n, s); | ||
| *pn = n; | ||
| return p; | ||
| } | ||
|
|
||
| void * | ||
| x2realloc(void *p, size_t *ps) | ||
| { | ||
| return x2nrealloc(p, ps, 1); | ||
| } | ||
|
|
||
| /* Grow array PA of *PN items (each S bytes) by at least N_INCR_MIN items, | ||
| not exceeding N_MAX total (-1 = unlimited). */ | ||
| void * | ||
| xpalloc(void *pa, ptrdiff_t *pn, ptrdiff_t n_incr_min, ptrdiff_t n_max, ptrdiff_t s) | ||
| { | ||
| enum { DEFAULT_MXFAST = 64 * sizeof(size_t) / 4 }; | ||
| ptrdiff_t n0 = *pn; | ||
| ptrdiff_t n; | ||
| size_t nbytes; | ||
|
|
||
| /* Grow by ~50%; cap at n_max if set. */ | ||
| n = n0 + (n0 >> 1) + 1; | ||
| if(n0 > (ptrdiff_t)((size_t)-1 / 2)) | ||
| n = (ptrdiff_t)((size_t)-1 / 2); /* overflow guard */ | ||
| if(0 <= n_max && n_max < n) | ||
| n = n_max; | ||
|
|
||
| nbytes = (size_t)n * (size_t)s; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The multiplication if(s > 0 && (size_t)n > (size_t)-1 / (size_t)s)
xalloc_die();
nbytes = (size_t)n * (size_t)s; |
||
| /* If tiny, round up to DEFAULT_MXFAST */ | ||
| if(nbytes < DEFAULT_MXFAST && s > 0) { | ||
| n = DEFAULT_MXFAST / s; | ||
| nbytes = (size_t)n * (size_t)s; | ||
| } | ||
|
|
||
| if(!pa) | ||
| *pn = 0; | ||
| if(n - n0 < n_incr_min) { | ||
| n = n0 + n_incr_min; | ||
| if(n < 0 || (0 <= n_max && n_max < n)) | ||
| xalloc_die(); | ||
| nbytes = (size_t)n * (size_t)s; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
| pa = xrealloc(pa, nbytes); | ||
| *pn = n; | ||
| return xrealloc(p, n * s); | ||
| return pa; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function
reallocarrayis an OpenBSD extension and is not part of the standard Plan 9 APE library. Using it here will result in a link error. Since this islibap, you should provide a manual implementation that checks for overflow before callingrealloc.