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.falkeb...@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)
> 

Reply via email to