Blame gnulib-tests/zerosize-ptr.h

Packit 33f14e
/* Return a pointer to a zero-size object in memory.
Packit 33f14e
   Copyright (C) 2009-2017 Free Software Foundation, Inc.
Packit 33f14e
Packit 33f14e
   This program is free software: you can redistribute it and/or modify
Packit 33f14e
   it under the terms of the GNU General Public License as published by
Packit 33f14e
   the Free Software Foundation; either version 3 of the License, or
Packit 33f14e
   (at your option) any later version.
Packit 33f14e
Packit 33f14e
   This program is distributed in the hope that it will be useful,
Packit 33f14e
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 33f14e
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 33f14e
   GNU General Public License for more details.
Packit 33f14e
Packit 33f14e
   You should have received a copy of the GNU General Public License
Packit 33f14e
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 33f14e
Packit 33f14e
/* ISO C 99 does not allow memcmp(), memchr() etc. to be invoked with a NULL
Packit 33f14e
   argument.  Therefore this file produces a non-NULL pointer which cannot
Packit 33f14e
   be dereferenced, if possible.  */
Packit 33f14e
Packit 33f14e
#include <stdlib.h>
Packit 33f14e
Packit 33f14e
/* Test whether mmap() and mprotect() are available.
Packit 33f14e
   We don't use HAVE_MMAP, because AC_FUNC_MMAP would not define it on HP-UX.
Packit 33f14e
   HAVE_MPROTECT is not enough, because mingw does not have mmap() but has an
Packit 33f14e
   mprotect() function in libgcc.a.  */
Packit 33f14e
#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
Packit 33f14e
# include <fcntl.h>
Packit 33f14e
# include <unistd.h>
Packit 33f14e
# include <sys/types.h>
Packit 33f14e
# include <sys/mman.h>
Packit 33f14e
/* Define MAP_FILE when it isn't otherwise.  */
Packit 33f14e
# ifndef MAP_FILE
Packit 33f14e
#  define MAP_FILE 0
Packit 33f14e
# endif
Packit 33f14e
#endif
Packit 33f14e
Packit 33f14e
/* Return a pointer to a zero-size object in memory (that is, actually, a
Packit 33f14e
   pointer to a page boundary where the previous page is readable and writable
Packit 33f14e
   and the next page is neither readable not writable), if possible.
Packit 33f14e
   Return NULL otherwise.  */
Packit 33f14e
Packit 33f14e
static void *
Packit 33f14e
zerosize_ptr (void)
Packit 33f14e
{
Packit 33f14e
/* Use mmap and mprotect when they exist.  Don't test HAVE_MMAP, because it is
Packit 33f14e
   not defined on HP-UX 11 (since it does not support MAP_FIXED).  */
Packit 33f14e
#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
Packit 33f14e
# if HAVE_MAP_ANONYMOUS
Packit 33f14e
  const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
Packit 33f14e
  const int fd = -1;
Packit 33f14e
# else /* !HAVE_MAP_ANONYMOUS */
Packit 33f14e
  const int flags = MAP_FILE | MAP_PRIVATE;
Packit 33f14e
  int fd = open ("/dev/zero", O_RDONLY, 0666);
Packit 33f14e
  if (fd >= 0)
Packit 33f14e
# endif
Packit 33f14e
    {
Packit 33f14e
      int pagesize = getpagesize ();
Packit 33f14e
      char *two_pages =
Packit 33f14e
        (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
Packit 33f14e
                       flags, fd, 0);
Packit 33f14e
      if (two_pages != (char *)(-1)
Packit 33f14e
          && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
Packit 33f14e
        return two_pages + pagesize;
Packit 33f14e
    }
Packit 33f14e
#endif
Packit 33f14e
  return NULL;
Packit 33f14e
}