"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/sljit/sljitProtExecAllocator.c" between
pcre2-10.35.tar.bz2 and pcre2-10.36.tar.bz2

About: The PCRE2 library implements Perl compatible regular expression pattern matching. New future PCRE version with revised API.

sljitProtExecAllocator.c  (pcre2-10.35.tar.bz2):sljitProtExecAllocator.c  (pcre2-10.36.tar.bz2)
skipping to change at line 79 skipping to change at line 79
#define CHUNK_SIZE 0x10000 #define CHUNK_SIZE 0x10000
struct chunk_header { struct chunk_header {
void *executable; void *executable;
}; };
/* /*
alloc_chunk / free_chunk : alloc_chunk / free_chunk :
* allocate executable system memory chunks * allocate executable system memory chunks
* the size is always divisible by CHUNK_SIZE * the size is always divisible by CHUNK_SIZE
allocator_grab_lock / allocator_release_lock : SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :
* make the allocator thread safe * provided as part of sljitUtils
* can be empty if the OS (or the application) does not support threading
* only the allocator requires this lock, sljit is fully thread safe * only the allocator requires this lock, sljit is fully thread safe
as it only uses local variables as it only uses local variables
*/ */
#ifndef __NetBSD__
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h>
#include <string.h>
#ifndef O_NOATIME #ifndef O_NOATIME
#define O_NOATIME 0 #define O_NOATIME 0
#endif #endif
#ifdef __O_TMPFILE /* this is a linux extension available since kernel 3.11 */
#ifndef O_TMPFILE #ifndef O_TMPFILE
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) #define O_TMPFILE 020200000
#endif #endif
#endif
#if !(defined(__NetBSD__) && defined(MAP_REMAPDUP))
int mkostemp(char *template, int flags);
#ifdef __NetBSD__ #ifndef _GNU_SOURCE
/*
* 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); char *secure_getenv(const char *name);
int mkostemp(char *template, int flags);
#endif #endif
static SLJIT_INLINE int create_tempfile(void) static SLJIT_INLINE int create_tempfile(void)
{ {
int fd; int fd;
char tmp_name[256]; char tmp_name[256];
size_t tmp_name_len; size_t tmp_name_len = 0;
char *dir; char *dir;
size_t len; struct stat st;
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
mode_t mode;
#endif
#ifdef HAVE_MEMFD_CREATE #ifdef HAVE_MEMFD_CREATE
/* this is a GNU extension, make sure to use -D_GNU_SOURCE */ /* this is a GNU extension, make sure to use -D_GNU_SOURCE */
fd = memfd_create("sljit", MFD_CLOEXEC); fd = memfd_create("sljit", MFD_CLOEXEC);
if (fd != -1) if (fd != -1) {
fchmod(fd, 0);
return fd; return fd;
#endif
#ifdef P_tmpdir
len = (P_tmpdir != NULL) ? strlen(P_tmpdir) : 0;
if (len > 0 && len < sizeof(tmp_name)) {
strcpy(tmp_name, P_tmpdir);
tmp_name_len = len;
} }
else {
strcpy(tmp_name, "/tmp");
tmp_name_len = 4;
}
#else
strcpy(tmp_name, "/tmp");
tmp_name_len = 4;
#endif #endif
dir = secure_getenv("TMPDIR"); dir = secure_getenv("TMPDIR");
if (dir) { if (dir) {
len = strlen(dir); tmp_name_len = strlen(dir);
if (len > 0 && len < sizeof(tmp_name)) { if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) {
strcpy(tmp_name, dir); if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode))
tmp_name_len = len; strcpy(tmp_name, dir);
} }
} }
#ifdef P_tmpdir
if (!tmp_name_len) {
tmp_name_len = strlen(P_tmpdir);
if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))
strcpy(tmp_name, P_tmpdir);
}
#endif
if (!tmp_name_len) {
strcpy(tmp_name, "/tmp");
tmp_name_len = 4;
}
SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)); SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));
while (tmp_name_len > 0 && tmp_name[tmp_name_len - 1] == '/') { if (tmp_name[tmp_name_len - 1] == '/')
tmp_name_len--; tmp_name[--tmp_name_len] = '\0';
tmp_name[tmp_name_len] = '\0';
}
#ifdef O_TMPFILE #ifdef __linux__
fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, /*
S_IRUSR | S_IWUSR); * the previous trimming might had left an empty string if TMPDIR="/"
* so work around the problem below
*/
fd = open(tmp_name_len ? tmp_name : "/",
O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);
if (fd != -1) if (fd != -1)
return fd; return fd;
#endif #endif
if (tmp_name_len + 7 >= sizeof(tmp_name)) if (tmp_name_len + 7 >= sizeof(tmp_name))
{
return -1; return -1;
}
strcpy(tmp_name + tmp_name_len, "/XXXXXX"); strcpy(tmp_name + tmp_name_len, "/XXXXXX");
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
mode = umask(0777);
#endif
fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME); fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
umask(mode);
#else
fchmod(fd, 0);
#endif
if (fd == -1) if (fd == -1)
return fd; return -1;
if (unlink(tmp_name)) { if (unlink(tmp_name)) {
close(fd); close(fd);
return -1; return -1;
} }
return fd; return fd;
} }
static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)
skipping to change at line 220 skipping to change at line 221
if (retval->executable == MAP_FAILED) { if (retval->executable == MAP_FAILED) {
munmap((void *)retval, size); munmap((void *)retval, size);
close(fd); close(fd);
return NULL; return NULL;
} }
close(fd); close(fd);
return retval; return retval;
} }
#else #else
/*
* MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to
* adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed
*/
static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)
{ {
struct chunk_header *retval; struct chunk_header *retval;
void *maprx;
retval = (struct chunk_header *)mmap(NULL, size, retval = (struct chunk_header *)mmap(NULL, size,
PROT_MPROTECT(PROT_EXEC|PROT_WRITE|PROT_READ), PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),
MAP_ANON, -1, 0); MAP_ANON | MAP_SHARED, -1, 0);
if (retval == MAP_FAILED) if (retval == MAP_FAILED)
return NULL; return NULL;
maprx = mremap(retval, size, NULL, size, MAP_REMAPDUP); retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);
if (maprx == MAP_FAILED) { if (retval->executable == MAP_FAILED) {
munmap((void *)retval, size); munmap((void *)retval, size);
return NULL; return NULL;
} }
if (mprotect(retval, size, PROT_READ | PROT_WRITE) == -1 || if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {
mprotect(maprx, size, PROT_READ | PROT_EXEC) == -1) { munmap(retval->executable, size);
munmap(maprx, size);
munmap((void *)retval, size); munmap((void *)retval, size);
return NULL; return NULL;
} }
retval->executable = maprx;
return retval; return retval;
} }
#endif /* NetBSD >= 8 */ #endif /* NetBSD */
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{ {
struct chunk_header *header = ((struct chunk_header *)chunk) - 1; struct chunk_header *header = ((struct chunk_header *)chunk) - 1;
munmap(header->executable, size); munmap(header->executable, size);
munmap((void *)header, size); munmap((void *)header, size);
} }
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
skipping to change at line 321 skipping to change at line 324
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
{ {
struct chunk_header *chunk_header; struct chunk_header *chunk_header;
struct block_header *header; struct block_header *header;
struct block_header *next_header; struct block_header *next_header;
struct free_block *free_block; struct free_block *free_block;
sljit_uw chunk_size; sljit_uw chunk_size;
sljit_sw executable_offset; sljit_sw executable_offset;
allocator_grab_lock(); SLJIT_ALLOCATOR_LOCK();
if (size < (64 - sizeof(struct block_header))) if (size < (64 - sizeof(struct block_header)))
size = (64 - sizeof(struct block_header)); size = (64 - sizeof(struct block_header));
size = ALIGN_SIZE(size); size = ALIGN_SIZE(size);
free_block = free_blocks; free_block = free_blocks;
while (free_block) { while (free_block) {
if (free_block->size >= size) { if (free_block->size >= size) {
chunk_size = free_block->size; chunk_size = free_block->size;
if (chunk_size > size + 64) { if (chunk_size > size + 64) {
/* We just cut a block from the end of the free b lock. */ /* We just cut a block from the end of the free b lock. */
skipping to change at line 346 skipping to change at line 349
header->executable_offset = free_block->header.ex ecutable_offset; header->executable_offset = free_block->header.ex ecutable_offset;
AS_BLOCK_HEADER(header, size)->prev_size = size; AS_BLOCK_HEADER(header, size)->prev_size = size;
} }
else { else {
sljit_remove_free_block(free_block); sljit_remove_free_block(free_block);
header = (struct block_header*)free_block; header = (struct block_header*)free_block;
size = chunk_size; size = chunk_size;
} }
allocated_size += size; allocated_size += size;
header->size = size; header->size = size;
allocator_release_lock(); SLJIT_ALLOCATOR_UNLOCK();
return MEM_START(header); return MEM_START(header);
} }
free_block = free_block->next; free_block = free_block->next;
} }
chunk_size = sizeof(struct chunk_header) + sizeof(struct block_header); chunk_size = sizeof(struct chunk_header) + sizeof(struct block_header);
chunk_size = (chunk_size + size + CHUNK_SIZE - 1) & CHUNK_MASK; chunk_size = (chunk_size + size + CHUNK_SIZE - 1) & CHUNK_MASK;
chunk_header = alloc_chunk(chunk_size); chunk_header = alloc_chunk(chunk_size);
if (!chunk_header) { if (!chunk_header) {
allocator_release_lock(); SLJIT_ALLOCATOR_UNLOCK();
return NULL; return NULL;
} }
executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (slj it_u8*)chunk_header); executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (slj it_u8*)chunk_header);
chunk_size -= sizeof(struct chunk_header) + sizeof(struct block_header); chunk_size -= sizeof(struct chunk_header) + sizeof(struct block_header);
total_size += chunk_size; total_size += chunk_size;
header = (struct block_header *)(chunk_header + 1); header = (struct block_header *)(chunk_header + 1);
skipping to change at line 391 skipping to change at line 394
} }
else { else {
/* All space belongs to this allocation. */ /* All space belongs to this allocation. */
allocated_size += chunk_size; allocated_size += chunk_size;
header->size = chunk_size; header->size = chunk_size;
next_header = AS_BLOCK_HEADER(header, chunk_size); next_header = AS_BLOCK_HEADER(header, chunk_size);
} }
next_header->size = 1; next_header->size = 1;
next_header->prev_size = chunk_size; next_header->prev_size = chunk_size;
next_header->executable_offset = executable_offset; next_header->executable_offset = executable_offset;
allocator_release_lock(); SLJIT_ALLOCATOR_UNLOCK();
return MEM_START(header); return MEM_START(header);
} }
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{ {
struct block_header *header; struct block_header *header;
struct free_block* free_block; struct free_block* free_block;
allocator_grab_lock(); SLJIT_ALLOCATOR_LOCK();
header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
header = AS_BLOCK_HEADER(header, -header->executable_offset); header = AS_BLOCK_HEADER(header, -header->executable_offset);
allocated_size -= header->size; allocated_size -= header->size;
/* Connecting free blocks together if possible. */ /* Connecting free blocks together if possible. */
/* If header->prev_size == 0, free_block will equal to header. /* If header->prev_size == 0, free_block will equal to header.
In this case, free_block->header.size will be > 0. */ In this case, free_block->header.size will be > 0. */
free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size); free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
if (SLJIT_UNLIKELY(!free_block->header.size)) { if (SLJIT_UNLIKELY(!free_block->header.size)) {
skipping to change at line 440 skipping to change at line 443
/* If this block is freed, we still have (allocated_size / 2) fre e space. */ /* If this block is freed, we still have (allocated_size / 2) fre e space. */
if (total_size - free_block->size > (allocated_size * 3 / 2)) { if (total_size - free_block->size > (allocated_size * 3 / 2)) {
total_size -= free_block->size; total_size -= free_block->size;
sljit_remove_free_block(free_block); sljit_remove_free_block(free_block);
free_chunk(free_block, free_block->size + free_chunk(free_block, free_block->size +
sizeof(struct chunk_header) + sizeof(struct chunk_header) +
sizeof(struct block_header)); sizeof(struct block_header));
} }
} }
allocator_release_lock(); SLJIT_ALLOCATOR_UNLOCK();
} }
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{ {
struct free_block* free_block; struct free_block* free_block;
struct free_block* next_free_block; struct free_block* next_free_block;
allocator_grab_lock(); SLJIT_ALLOCATOR_LOCK();
free_block = free_blocks; free_block = free_blocks;
while (free_block) { while (free_block) {
next_free_block = free_block->next; next_free_block = free_block->next;
if (!free_block->header.prev_size && if (!free_block->header.prev_size &&
AS_BLOCK_HEADER(free_block, free_block->size)->si ze == 1) { AS_BLOCK_HEADER(free_block, free_block->size)->si ze == 1) {
total_size -= free_block->size; total_size -= free_block->size;
sljit_remove_free_block(free_block); sljit_remove_free_block(free_block);
free_chunk(free_block, free_block->size + free_chunk(free_block, free_block->size +
sizeof(struct chunk_header) + sizeof(struct chunk_header) +
sizeof(struct block_header)); sizeof(struct block_header));
} }
free_block = next_free_block; free_block = next_free_block;
} }
SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks) ); SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks) );
allocator_release_lock(); SLJIT_ALLOCATOR_UNLOCK();
} }
SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr) SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr)
{ {
return ((struct block_header *)(ptr))[-1].executable_offset; return ((struct block_header *)(ptr))[-1].executable_offset;
} }
 End of changes. 38 change blocks. 
69 lines changed or deleted 71 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)