summaryrefslogtreecommitdiff
path: root/ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-06-30 16:08:27 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2020-06-30 16:19:02 +0200
commitb419f96c626d1f9cbbba42698e947e32a0af9c4f (patch)
tree23457bd7b1c10d0bac6b4649e543a91b18619e0e /ext/pcre/pcre2lib/sljit/sljitProtExecAllocator.c
parentb3698ed9eb434ad119bd130fdc3ce4e6be4c0f84 (diff)
downloadphp-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.c66
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;
}