aboutsummaryrefslogtreecommitdiffstats
path: root/erts/lib_src
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2017-04-05 14:32:16 +0200
committerRickard Green <[email protected]>2017-04-07 15:02:10 +0200
commit8f452530e61b299d4d48f82f41ab5364723607ae (patch)
tree29bc2e4cfac2bcd5fdc4cdee4996a39350a1a32a /erts/lib_src
parent671d690debf653a6b1e86c3e7880b9c5640b1324 (diff)
downloadotp-8f452530e61b299d4d48f82f41ab5364723607ae.tar.gz
otp-8f452530e61b299d4d48f82f41ab5364723607ae.tar.bz2
otp-8f452530e61b299d4d48f82f41ab5364723607ae.zip
Stack guard for PCRE
Diffstat (limited to 'erts/lib_src')
-rw-r--r--erts/lib_src/common/ethr_aux.c64
-rw-r--r--erts/lib_src/pthread/ethread.c25
-rw-r--r--erts/lib_src/win/ethread.c21
3 files changed, 93 insertions, 17 deletions
diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c
index 3501fe335a..bbffca4d6d 100644
--- a/erts/lib_src/common/ethr_aux.c
+++ b/erts/lib_src/common/ethr_aux.c
@@ -68,6 +68,8 @@ size_t ethr_max_stack_size__; /* kilo words */
ethr_rwmutex xhndl_rwmtx;
ethr_xhndl_list *xhndl_list;
+static ethr_tsd_key ethr_stacklimit_key__;
+
static int main_threads;
static int init_ts_event_alloc(void);
@@ -237,13 +239,11 @@ ethr_init_common__(ethr_init_data *id)
#endif
ethr_min_stack_size__ = ETHR_PAGE_ALIGN(ethr_min_stack_size__);
- ethr_min_stack_size__ = ETHR_B2KW(ethr_min_stack_size__);
-
ethr_max_stack_size__ = 32*1024*1024;
#if SIZEOF_VOID_P == 8
ethr_max_stack_size__ *= 2;
#endif
- ethr_max_stack_size__ = ETHR_B2KW(ethr_max_stack_size__);
+ ethr_max_stack_size__ = ETHR_PAGE_ALIGN(ethr_max_stack_size__);
res = ethr_init_atomics();
if (res != 0)
@@ -253,6 +253,10 @@ ethr_init_common__(ethr_init_data *id)
if (res != 0)
return res;
+ res = ethr_tsd_key_create(&ethr_stacklimit_key__, "stacklimit");
+ if (res != 0)
+ return res;
+
xhndl_list = NULL;
return 0;
@@ -313,6 +317,60 @@ ethr_late_init_common__(ethr_late_init_data *lid)
return 0;
}
+/*
+ * Stack limit
+ */
+
+void *ethr_get_stacklimit(void)
+{
+ return ethr_tsd_get(ethr_stacklimit_key__);
+}
+
+int ethr_set_stacklimit(void *limit)
+{
+ void *prev = ethr_tsd_get(ethr_stacklimit_key__);
+ if (prev)
+ return EACCES;
+ if (!limit)
+ return EINVAL;
+ return ethr_tsd_set(ethr_stacklimit_key__, limit);
+}
+
+/* internal stacklimit (thread creation) */
+
+void
+ethr_set_stacklimit__(char *prev_c, size_t stacksize)
+{
+ /*
+ * We *don't* want this function inlined, i.e., it is
+ * risky to call this function from another function
+ * in ethr_aux.c
+ */
+ void *limit = NULL;
+ char c;
+ int res;
+
+ if (stacksize) {
+ char *start;
+ if (&c > prev_c) {
+ start = (char *) ((((ethr_uint_t) prev_c)
+ / ethr_pagesize__)
+ * ethr_pagesize__);
+ limit = start + stacksize;
+ }
+ else {
+ start = (char *) (((((ethr_uint_t) prev_c) - 1)
+ / ethr_pagesize__ + 1)
+ * ethr_pagesize__);
+ limit = start - stacksize;
+ }
+ }
+
+ res = ethr_tsd_set(ethr_stacklimit_key__, limit);
+ if (res != 0)
+ ethr_abort__();
+}
+
int
ethr_install_exit_handler(void (*funcp)(void))
{
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index 29bffa7e12..f0d4296445 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -81,6 +81,7 @@ typedef struct {
void *(*thr_func)(void *);
void *arg;
void *prep_func_res;
+ size_t stacksize;
char *name;
char name_buff[16];
} ethr_thr_wrap_data__;
@@ -88,12 +89,15 @@ typedef struct {
static void *thr_wrapper(void *vtwd)
{
ethr_sint32_t result;
+ char c;
void *res;
ethr_thr_wrap_data__ *twd = (ethr_thr_wrap_data__ *) vtwd;
void *(*thr_func)(void *) = twd->thr_func;
void *arg = twd->arg;
ethr_ts_event *tsep = NULL;
+ ethr_set_stacklimit__(&c, twd->stacksize);
+
result = (ethr_sint32_t) ethr_make_ts_event__(&tsep);
if (result == 0) {
@@ -330,6 +334,7 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg,
twd.tse = ethr_get_ts_event();
twd.thr_func = func;
twd.arg = arg;
+ twd.stacksize = 0;
if (opts && opts->name) {
snprintf(twd.name_buff, 16, "%s", opts->name);
@@ -354,18 +359,24 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg,
#ifdef ETHR_DEBUG
suggested_stack_size /= 2; /* Make sure we got margin */
#endif
+ stack_size = ETHR_KW2B(suggested_stack_size);
+ stack_size = ETHR_PAGE_ALIGN(stack_size);
+ stack_size += ethr_pagesize__; /* For possible system usage */
#ifdef ETHR_STACK_GUARD_SIZE
/* The guard is at least on some platforms included in the stack size
passed when creating threads */
- suggested_stack_size += ETHR_B2KW(ETHR_STACK_GUARD_SIZE);
+ stack_size += ETHR_STACK_GUARD_SIZE;
#endif
- if (suggested_stack_size < ethr_min_stack_size__)
- stack_size = ETHR_KW2B(ethr_min_stack_size__);
- else if (suggested_stack_size > ethr_max_stack_size__)
- stack_size = ETHR_KW2B(ethr_max_stack_size__);
- else
- stack_size = ETHR_PAGE_ALIGN(ETHR_KW2B(suggested_stack_size));
+ if (stack_size < ethr_min_stack_size__)
+ stack_size = ethr_min_stack_size__;
+ else if (stack_size > ethr_max_stack_size__)
+ stack_size = ethr_max_stack_size__;
(void) pthread_attr_setstacksize(&attr, stack_size);
+ twd.stacksize = stack_size;
+ twd.stacksize -= ethr_pagesize__; /* For possible system usage */
+#ifdef ETHR_STACK_GUARD_SIZE
+ twd.stacksize -= ETHR_STACK_GUARD_SIZE;
+#endif
}
#ifdef ETHR_STACK_GUARD_SIZE
diff --git a/erts/lib_src/win/ethread.c b/erts/lib_src/win/ethread.c
index e0f19f7ba1..ba77b3dc88 100644
--- a/erts/lib_src/win/ethread.c
+++ b/erts/lib_src/win/ethread.c
@@ -56,6 +56,7 @@ typedef struct {
void *(*thr_func)(void *);
void *arg;
void *prep_func_res;
+ size_t stacksize;
} ethr_thr_wrap_data__;
#define ETHR_INVALID_TID_ID -1
@@ -94,6 +95,7 @@ static void thr_exit_cleanup(ethr_tid *tid, void *res)
static unsigned __stdcall thr_wrapper(LPVOID vtwd)
{
+ char c;
ethr_tid my_tid;
ethr_sint32_t result;
void *res;
@@ -102,6 +104,8 @@ static unsigned __stdcall thr_wrapper(LPVOID vtwd)
void *arg = twd->arg;
ethr_ts_event *tsep = NULL;
+ ethr_set_stacklimit__(&c, twd->stacksize);
+
result = (ethr_sint32_t) ethr_make_ts_event__(&tsep);
if (result == 0) {
@@ -305,18 +309,21 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg,
tid->jdata->res = NULL;
}
+ twd.stacksize = 0;
+
if (use_stack_size >= 0) {
size_t suggested_stack_size = (size_t) use_stack_size;
#ifdef ETHR_DEBUG
suggested_stack_size /= 2; /* Make sure we got margin */
#endif
- if (suggested_stack_size < ethr_min_stack_size__)
- stack_size = (unsigned) ETHR_KW2B(ethr_min_stack_size__);
- else if (suggested_stack_size > ethr_max_stack_size__)
- stack_size = (unsigned) ETHR_KW2B(ethr_max_stack_size__);
- else
- stack_size = (unsigned)
- ETHR_PAGE_ALIGN(ETHR_KW2B(suggested_stack_size));
+ stack_size = (unsigned) ETHR_PAGE_ALIGN(ETHR_KW2B(suggested_stack_size));
+
+ if (stack_size < (unsigned) ethr_min_stack_size__)
+ stack_size = (unsigned) ethr_min_stack_size__;
+ else if (stack_size > (unsigned) ethr_max_stack_size__)
+ stack_size = (unsigned) ethr_max_stack_size__;
+
+ twd.stacksize = stack_size;
}
ethr_atomic32_init(&twd.result, -1);