1 /* Return a pointer to a zero-size object in memory. 2 Copyright (C) 2009-2021 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 17 /* ISO C 99 does not allow memcmp(), memchr() etc. to be invoked with a NULL 18 argument. Therefore this file produces a non-NULL pointer which cannot 19 be dereferenced, if possible. */ 20 21 /* On Android, when targeting Android 4.4 or older with a GCC toolchain, 22 prevent a compilation error 23 "error: call to 'mmap' declared with attribute error: mmap is not 24 available with _FILE_OFFSET_BITS=64 when using GCC until android-21. 25 Either raise your minSdkVersion, disable _FILE_OFFSET_BITS=64, or 26 switch to Clang." 27 The files that we access in this compilation unit are less than 2 GB 28 large. */ 29 #if defined __ANDROID__ 30 # undef _FILE_OFFSET_BITS 31 # undef __USE_FILE_OFFSET64 32 #endif 33 34 #include <stdlib.h> 35 36 /* Test whether mmap() and mprotect() are available. 37 We don't use HAVE_MMAP, because AC_FUNC_MMAP would not define it on HP-UX. 38 HAVE_MPROTECT is not enough, because mingw does not have mmap() but has an 39 mprotect() function in libgcc.a. 40 And OS/2 kLIBC has <sys/mman.h> and mprotect(), but not mmap(). */ 41 #if HAVE_SYS_MMAN_H && HAVE_MPROTECT && !defined __KLIBC__ 42 # include <fcntl.h> 43 # include <unistd.h> 44 # include <sys/types.h> 45 # include <sys/mman.h> 46 /* Define MAP_FILE when it isn't otherwise. */ 47 # ifndef MAP_FILE 48 # define MAP_FILE 0 49 # endif 50 #endif 51 52 /* Return a pointer to a zero-size object in memory (that is, actually, a 53 pointer to a page boundary where the previous page is readable and writable 54 and the next page is neither readable not writable), if possible. 55 Return NULL otherwise. */ 56 57 static void * 58 zerosize_ptr (void) /* */ 59 { 60 /* Use mmap and mprotect when they exist. Don't test HAVE_MMAP, because it is 61 not defined on HP-UX 11 (since it does not support MAP_FIXED). */ 62 #if HAVE_SYS_MMAN_H && HAVE_MPROTECT && !defined __KLIBC__ 63 # if HAVE_MAP_ANONYMOUS 64 const int flags = MAP_ANONYMOUS | MAP_PRIVATE; 65 const int fd = -1; 66 # else /* !HAVE_MAP_ANONYMOUS */ 67 const int flags = MAP_FILE | MAP_PRIVATE; 68 int fd = open ("/dev/zero", O_RDONLY, 0666); 69 if (fd >= 0) 70 # endif 71 { 72 int pagesize = getpagesize (); 73 char *two_pages = 74 (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE, 75 flags, fd, 0); 76 if (two_pages != (char *)(-1) 77 && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0) 78 return two_pages + pagesize; 79 } 80 #endif 81 return NULL; 82 }