bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Use malloca instead alloca


From: Ondřej Bílka
Subject: Re: [PATCH] Use malloca instead alloca
Date: Sat, 29 Dec 2012 11:33:15 +0100
User-agent: Mutt/1.5.20 (2009-06-14)

On Fri, Dec 28, 2012 at 03:17:30PM -0500, Rich Felker wrote:
> On Fri, Dec 28, 2012 at 06:38:23PM +0100, Ondřej Bílka wrote:
> >   /* malloca(N) is a safe variant of alloca(N).  It allocates N bytes of
> >      memory allocated on the stack or heap for large requests.
> >      It must be freed using freea() before
> >      the function returns.  Upon failure, it returns NULL.  */
> > 
> > #if 1
> > #define malloca(n) ({\
> >   void *__r__ = NULL;\
> >   if (n < 4096 - 8)\
> 
> This comparison is performed without promoting n to size_t. Although
> in most correct usages it should not matter, I think this should be
> fixed; things like malloca(-1) should fail (or allocate 4gb-1
> successfully) rather than succeeding and then causing memory
> corruption. Note that n is also being evaluated more than once, so
> just storing it in a variable of type size_t first would avoid this
> issue too.
> 
> Rich

Fixed, here is updated version.


/* Safe automatic memory allocation.
   Copyright (C) 2012 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */

#ifndef _MALLOCA_H
#define _MALLOCA_H

/* AIX requires this to be the first thing in the file.  */
#ifndef __GNUC__
# if HAVE_ALLOCA_H || defined _LIBC
#  include <alloca.h>
# else
#  ifdef _AIX
#pragma alloca
#  else
#   ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
#   endif
#  endif
# endif
#endif

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define _ALLOCA_MC 0x2439a2431bca4812L
#define _MALLOC_MC 0x1bca48122439a243L


  /* malloca(N) is a safe variant of alloca(N).  It allocates N bytes of
     memory allocated on the stack or heap for large requests.
     It must be freed using freea() before
     the function returns.  Upon failure, it returns NULL.  */

#if 1
#define malloca(n) ({\
  size_t  __n__ = n;\
  void  * __r__ = NULL;\
  if (__n__ <= 4096)\
    {\
      __r__ = alloca (__n__ + sizeof (uint64_t));\
      if (__r__)\
        {\
          *((uint64_t *)__r__) = _ALLOCA_MC;\
          __r__ += sizeof (uint64_t);\
        }\
    }\
  if (!__r__)\
    {\
      __r__ = malloc (__n__ + sizeof (uint64_t));\
      if (__r__)\
        {\
          *((uint64_t *)__r__) = _MALLOC_MC;\
          __r__ += sizeof (uint64_t);\
        }\
    }\
  __r__;\
})

/* If desired we could detect more corruption by 
   adding constant to end of alloca'd array. */

#define freea(r) {\
void *__r__ = r;\
if (__r__)\
  {\
    __r__ -= sizeof (uint64_t);\
    if  (    *((uint64_t *)__r__) == _MALLOC_MC)\
      free (__r__);\
    else if (*((uint64_t *)__r__) != _ALLOCA_MC)\
      __abort_freea();\
  }\
}

static void __abort_freea()
{
  fprintf(stderr, "double freea or corruption\n");
  abort();
}
#else
#define malloca malloc
#define freea   free
#endif
#ifdef __cplusplus
}
#endif

#endif /* _MALLOCA_H */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]