[pacman-dev] [PATCH] Add REALLOC macro to simplify realloc error handling
Allan McRae
allan at archlinux.org
Mon Apr 13 07:05:28 UTC 2020
On 13/4/20 3:28 pm, Rikard Falkeborn wrote:
> realloc can fail just like the other memory allocation functions. Add a
> macro to simplify handling of realloc failures, similar to the already
> existing MALLOC, CALLOC, etc.
>
> Replace the existing realloc uses with the new macro, allowing us to
> move tedious error handling to the macro. Also, in be_package and
> be_sync, this fixes hypothetical memory leaks (and thereafter null
> pointer dereferences) in case realloc fails to shrink the allocated
> memory.
>
Ack.
> Signed-off-by: Rikard Falkeborn <rikard.falkeborn at gmail.com>
> ---
> lib/libalpm/be_local.c | 7 +------
> lib/libalpm/be_package.c | 3 +--
> lib/libalpm/be_sync.c | 2 +-
> lib/libalpm/util.c | 13 +++----------
> lib/libalpm/util.h | 1 +
> 5 files changed, 7 insertions(+), 19 deletions(-)
>
> diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
> index 9ebdfa40..689f0102 100644
> --- a/lib/libalpm/be_local.c
> +++ b/lib/libalpm/be_local.c
> @@ -843,12 +843,7 @@ static int local_db_read(alpm_pkg_t *info, int inforeq)
> }
> /* attempt to hand back any memory we don't need */
> if(files_count > 0) {
> - alpm_file_t *newfiles;
> -
> - newfiles = realloc(files, sizeof(alpm_file_t) * files_count);
> - if(newfiles != NULL) {
> - files = newfiles;
> - }
> + REALLOC(files, sizeof(alpm_file_t) * files_count, (void)0);
> } else {
> FREE(files);
> }
> diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
> index 7a118d2a..4832966b 100644
> --- a/lib/libalpm/be_package.c
> +++ b/lib/libalpm/be_package.c
> @@ -669,8 +669,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
> if(full) {
> if(newpkg->files.files) {
> /* attempt to hand back any memory we don't need */
> - newpkg->files.files = realloc(newpkg->files.files,
> - sizeof(alpm_file_t) * newpkg->files.count);
> + REALLOC(newpkg->files.files, sizeof(alpm_file_t) * newpkg->files.count, (void)0);
> /* "checking for conflicts" requires a sorted list, ensure that here */
> _alpm_log(handle, ALPM_LOG_DEBUG,
> "sorting package filelist for %s\n", pkgfile);
> diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
> index aafed15d..5f457122 100644
> --- a/lib/libalpm/be_sync.c
> +++ b/lib/libalpm/be_sync.c
> @@ -689,7 +689,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
> }
> /* attempt to hand back any memory we don't need */
> if(files_count > 0) {
> - files = realloc(files, sizeof(alpm_file_t) * files_count);
> + REALLOC(files, sizeof(alpm_file_t) * files_count, (void)0);
> } else {
> FREE(files);
> }
> diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
> index c46b1397..cebc87ec 100644
> --- a/lib/libalpm/util.c
> +++ b/lib/libalpm/util.c
> @@ -1427,22 +1427,15 @@ int _alpm_fnmatch(const void *pattern, const void *string)
> */
> void *_alpm_realloc(void **data, size_t *current, const size_t required)
> {
> - char *newdata;
> -
> - newdata = realloc(*data, required);
> - if(!newdata) {
> - _alpm_alloc_fail(required);
> - return NULL;
> - }
> + REALLOC(*data, required, return NULL);
>
> if (*current < required) {
> /* ensure all new memory is zeroed out, in both the initial
> * allocation and later reallocs */
> - memset(newdata + *current, 0, required - *current);
> + memset((char*)*data + *current, 0, required - *current);
> }
> *current = required;
> - *data = newdata;
> - return newdata;
> + return *data;
> }
>
> /** This automatically grows data based on current/required.
> diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
> index 675eedec..3306a022 100644
> --- a/lib/libalpm/util.h
> +++ b/lib/libalpm/util.h
> @@ -53,6 +53,7 @@ void _alpm_alloc_fail(size_t size);
>
> #define MALLOC(p, s, action) do { p = malloc(s); if(p == NULL) { _alpm_alloc_fail(s); action; } } while(0)
> #define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { _alpm_alloc_fail(l * s); action; } } while(0)
> +#define REALLOC(p, s, action) do { void* np = realloc(p, s); if(np == NULL) { _alpm_alloc_fail(s); action; } else { p = np; } } while(0)
> /* This strdup macro is NULL safe- copying NULL will yield NULL */
> #define STRDUP(r, s, action) do { if(s != NULL) { r = strdup(s); if(r == NULL) { _alpm_alloc_fail(strlen(s)); action; } } else { r = NULL; } } while(0)
> #define STRNDUP(r, s, l, action) do { if(s != NULL) { r = strndup(s, l); if(r == NULL) { _alpm_alloc_fail(l); action; } } else { r = NULL; } } while(0)
>
More information about the pacman-dev
mailing list