Blame gnulib-tests/zerosize-ptr.h

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