diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2020-06-30 16:08:27 +0200 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2020-06-30 16:19:02 +0200 |
commit | b419f96c626d1f9cbbba42698e947e32a0af9c4f (patch) | |
tree | 23457bd7b1c10d0bac6b4649e543a91b18619e0e /ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c | |
parent | b3698ed9eb434ad119bd130fdc3ce4e6be4c0f84 (diff) | |
download | php-git-b419f96c626d1f9cbbba42698e947e32a0af9c4f.tar.gz |
Update to PCRE2 10.35
Diffstat (limited to 'ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c')
-rw-r--r-- | ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c b/ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c index 8a5b2b3cfe..3f412fe68f 100644 --- a/ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c +++ b/ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c @@ -70,7 +70,6 @@ struct chunk_header { void *executable; - int fd; }; /* @@ -96,8 +95,20 @@ struct chunk_header { #endif #endif +#if !(defined(__NetBSD__) && defined(MAP_REMAPDUP)) int mkostemp(char *template, int flags); + +#ifdef __NetBSD__ +/* + * this is a workaround for NetBSD < 8 that lacks a system provided + * secure_getenv function. + * ideally this should never be used, as the standard allocator is + * a preferred option for those systems and should be used instead. + */ +#define secure_getenv(name) issetugid() ? NULL : getenv(name) +#else char *secure_getenv(const char *name); +#endif static SLJIT_INLINE int create_tempfile(void) { @@ -108,6 +119,13 @@ static SLJIT_INLINE int create_tempfile(void) char *dir; size_t len; +#ifdef HAVE_MEMFD_CREATE + /* this is a GNU extension, make sure to use -D_GNU_SOURCE */ + fd = memfd_create("sljit", MFD_CLOEXEC); + if (fd != -1) + return fd; +#endif + #ifdef P_tmpdir len = (P_tmpdir != NULL) ? strlen(P_tmpdir) : 0; @@ -125,6 +143,7 @@ static SLJIT_INLINE int create_tempfile(void) #endif dir = secure_getenv("TMPDIR"); + if (dir) { len = strlen(dir); if (len > 0 && len < sizeof(tmp_name)) { @@ -189,23 +208,50 @@ static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); if (retval->executable == MAP_FAILED) { - munmap(retval, size); + munmap((void *)retval, size); close(fd); return NULL; } - retval->fd = fd; + close(fd); + return retval; +} +#else +static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) +{ + struct chunk_header *retval; + void *maprx; + + retval = (struct chunk_header *)mmap(NULL, size, + PROT_MPROTECT(PROT_EXEC|PROT_WRITE|PROT_READ), + MAP_ANON, -1, 0); + + if (retval == MAP_FAILED) + return NULL; + + maprx = mremap(retval, size, NULL, size, MAP_REMAPDUP); + if (maprx == MAP_FAILED) { + munmap((void *)retval, size); + return NULL; + } + + if (mprotect(retval, size, PROT_READ | PROT_WRITE) == -1 || + mprotect(maprx, size, PROT_READ | PROT_EXEC) == -1) { + munmap(maprx, size); + munmap((void *)retval, size); + return NULL; + } + retval->executable = maprx; return retval; } +#endif /* NetBSD >= 8 */ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) { struct chunk_header *header = ((struct chunk_header *)chunk) - 1; - int fd = header->fd; munmap(header->executable, size); - munmap(header, size); - close(fd); + munmap((void *)header, size); } /* --------------------------------------------------------------------- */ @@ -385,7 +431,9 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) if (total_size - free_block->size > (allocated_size * 3 / 2)) { total_size -= free_block->size; sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + sizeof(struct block_header)); + free_chunk(free_block, free_block->size + + sizeof(struct chunk_header) + + sizeof(struct block_header)); } } @@ -406,7 +454,9 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { total_size -= free_block->size; sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + sizeof(struct block_header)); + free_chunk(free_block, free_block->size + + sizeof(struct chunk_header) + + sizeof(struct block_header)); } free_block = next_free_block; } |