Blame gnulib-tests/zerosize-ptr.h

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