diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2019-11-25 22:48:50 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2019-11-28 10:48:09 +0100 |
commit | ba95c303e379b9f23289aaaffe18fb5d49ddf4a3 (patch) | |
tree | 88004462cb796a8660b85383b6389d3f4eea745c | |
parent | 584ffa02f1bef6931b3feb78559841ffe9c8600f (diff) | |
download | mariadb-git-ba95c303e379b9f23289aaaffe18fb5d49ddf4a3.tar.gz |
MDEV-21167 LF_PINS::stack_ends_here inaccurate, leading to alloca() larger than stack
Use my_thread_var::stack_ends_here inside lf_pinbox_real_free() for address
where thread stack ends.
Remove LF_PINS::stack_ends_here.
It is not safe to assume that mysys_var that was used during pin allocation,
remains correct during free. E.g with binlog group commit in Innodb,
that frees pins for multiple Innodb transactions, it does not work
correctly.
-rw-r--r-- | include/lf.h | 1 | ||||
-rw-r--r-- | mysys/lf_alloc-pin.c | 14 |
2 files changed, 5 insertions, 10 deletions
diff --git a/include/lf.h b/include/lf.h index e4cad7eabb3..10a60c5c949 100644 --- a/include/lf.h +++ b/include/lf.h @@ -65,7 +65,6 @@ typedef struct { typedef struct { void * volatile pin[LF_PINBOX_PINS]; LF_PINBOX *pinbox; - void **stack_ends_here; void *purgatory; uint32 purgatory_count; uint32 volatile link; diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 2a0ee7fddf9..b98684556c3 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -151,7 +151,6 @@ void lf_pinbox_destroy(LF_PINBOX *pinbox) */ LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox) { - struct st_my_thread_var *var; uint32 pins, next, top_ver; LF_PINS *el; /* @@ -194,12 +193,7 @@ LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox) el->link= pins; el->purgatory_count= 0; el->pinbox= pinbox; - var= my_thread_var; - /* - Threads that do not call my_thread_init() should still be - able to use the LF_HASH. - */ - el->stack_ends_here= (var ? & var->stack_ends_here : NULL); + return el; } @@ -335,16 +329,18 @@ static void lf_pinbox_real_free(LF_PINS *pins) void *list; void **addr= NULL; void *first= NULL, *last= NULL; + struct st_my_thread_var *var= my_thread_var; + void *stack_ends_here= var ? var->stack_ends_here : NULL; LF_PINBOX *pinbox= pins->pinbox; npins= pinbox->pins_in_array+1; #ifdef HAVE_ALLOCA - if (pins->stack_ends_here != NULL) + if (stack_ends_here != NULL) { int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; /* create a sorted list of pinned addresses, to speed up searches */ - if (available_stack_size(&pinbox, *pins->stack_ends_here) > + if (available_stack_size(&pinbox, stack_ends_here) > alloca_size + ALLOCA_SAFETY_MARGIN) { struct st_harvester hv; |