Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 6fd53da

Browse files
author
Jason Evans
committed
Fix prof_tdata_get()-related regressions.
Fix prof_tdata_get() to avoid dereferencing an invalid tdata pointer (when it's PROF_TDATA_STATE_{REINCARNATED,PURGATORY}). Fix prof_tdata_get() callers to check for invalid results besides NULL (PROF_TDATA_STATE_{REINCARNATED,PURGATORY}). These regressions were caused by 602c8e0 (Implement per thread heap profiling.), which did not make it into any releases prior to these fixes.
1 parent 7c17e16 commit 6fd53da

File tree

2 files changed

+26
-30
lines changed

2 files changed

+26
-30
lines changed

include/jemalloc/internal/prof.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,13 @@ prof_tdata_get(bool create)
308308

309309
tdata = *prof_tdata_tsd_get();
310310
if (create) {
311-
if (tdata == NULL)
312-
tdata = prof_tdata_init();
313-
else if (tdata->state == prof_tdata_state_expired)
311+
if ((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) {
312+
if (tdata == NULL)
313+
tdata = prof_tdata_init();
314+
} else if (tdata->state == prof_tdata_state_expired)
314315
tdata = prof_tdata_reinit(tdata);
315-
assert(tdata == NULL || tdata->state ==
316-
prof_tdata_state_attached);
316+
assert((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX ||
317+
tdata->state == prof_tdata_state_attached);
317318
}
318319

319320
return (tdata);

src/prof.c

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,8 @@ prof_gctx_create(prof_bt_t *bt)
487487
}
488488

489489
static void
490-
prof_gctx_maybe_destroy(prof_gctx_t *gctx)
490+
prof_gctx_maybe_destroy(prof_gctx_t *gctx, prof_tdata_t *tdata)
491491
{
492-
prof_tdata_t *tdata;
493492

494493
cassert(config_prof);
495494

@@ -500,8 +499,6 @@ prof_gctx_maybe_destroy(prof_gctx_t *gctx)
500499
* avoid a race between the main body of prof_tctx_destroy() and entry
501500
* into this function.
502501
*/
503-
tdata = prof_tdata_get(false);
504-
assert((uintptr_t)tdata > (uintptr_t)PROF_TDATA_STATE_MAX);
505502
prof_enter(tdata);
506503
malloc_mutex_lock(gctx->lock);
507504
if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) {
@@ -552,25 +549,19 @@ prof_gctx_should_destroy(prof_gctx_t *gctx)
552549
static void
553550
prof_tctx_destroy(prof_tctx_t *tctx)
554551
{
552+
prof_tdata_t *tdata = tctx->tdata;
555553
prof_gctx_t *gctx = tctx->gctx;
556-
bool destroy_gctx;
554+
bool destroy_tdata, destroy_gctx;
557555

558556
assert(tctx->cnts.curobjs == 0);
559557
assert(tctx->cnts.curbytes == 0);
560558
assert(opt_prof_accum == false);
561559
assert(tctx->cnts.accumobjs == 0);
562560
assert(tctx->cnts.accumbytes == 0);
563561

564-
{
565-
prof_tdata_t *tdata = tctx->tdata;
566-
bool tdata_destroy;
567-
568-
ckh_remove(&tdata->bt2tctx, &gctx->bt, NULL, NULL);
569-
tdata_destroy = prof_tdata_should_destroy(tdata);
570-
malloc_mutex_unlock(tdata->lock);
571-
if (tdata_destroy)
572-
prof_tdata_destroy(tdata);
573-
}
562+
ckh_remove(&tdata->bt2tctx, &gctx->bt, NULL, NULL);
563+
destroy_tdata = prof_tdata_should_destroy(tdata);
564+
malloc_mutex_unlock(tdata->lock);
574565

575566
malloc_mutex_lock(gctx->lock);
576567
tctx_tree_remove(&gctx->tctxs, tctx);
@@ -594,7 +585,10 @@ prof_tctx_destroy(prof_tctx_t *tctx)
594585
destroy_gctx = false;
595586
malloc_mutex_unlock(gctx->lock);
596587
if (destroy_gctx)
597-
prof_gctx_maybe_destroy(gctx);
588+
prof_gctx_maybe_destroy(gctx, tdata);
589+
590+
if (destroy_tdata)
591+
prof_tdata_destroy(tdata);
598592

599593
idalloc(tctx);
600594
}
@@ -683,7 +677,7 @@ prof_lookup(prof_bt_t *bt)
683677
ret.v = imalloc(sizeof(prof_tctx_t));
684678
if (ret.p == NULL) {
685679
if (new_gctx)
686-
prof_gctx_maybe_destroy(gctx);
680+
prof_gctx_maybe_destroy(gctx, tdata);
687681
return (NULL);
688682
}
689683
ret.p->tdata = tdata;
@@ -695,7 +689,7 @@ prof_lookup(prof_bt_t *bt)
695689
malloc_mutex_unlock(tdata->lock);
696690
if (error) {
697691
if (new_gctx)
698-
prof_gctx_maybe_destroy(gctx);
692+
prof_gctx_maybe_destroy(gctx, tdata);
699693
idalloc(ret.v);
700694
return (NULL);
701695
}
@@ -1019,6 +1013,7 @@ prof_gctx_merge_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *arg)
10191013
static prof_gctx_t *
10201014
prof_gctx_finish_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *arg)
10211015
{
1016+
prof_tdata_t *tdata = (prof_tdata_t *)arg;
10221017
prof_tctx_t *next;
10231018
bool destroy_gctx;
10241019

@@ -1032,7 +1027,7 @@ prof_gctx_finish_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *arg)
10321027
destroy_gctx = prof_gctx_should_destroy(gctx);
10331028
malloc_mutex_unlock(gctx->lock);
10341029
if (destroy_gctx)
1035-
prof_gctx_maybe_destroy(gctx);
1030+
prof_gctx_maybe_destroy(gctx, tdata);
10361031

10371032
return (NULL);
10381033
}
@@ -1310,7 +1305,7 @@ prof_dump(bool propagate_err, const char *filename, bool leakcheck)
13101305
if (prof_dump_close(propagate_err))
13111306
goto label_open_close_error;
13121307

1313-
gctx_tree_iter(&gctxs, NULL, prof_gctx_finish_iter, NULL);
1308+
gctx_tree_iter(&gctxs, NULL, prof_gctx_finish_iter, tdata);
13141309
malloc_mutex_unlock(&prof_dump_mtx);
13151310

13161311
if (leakcheck)
@@ -1320,7 +1315,7 @@ prof_dump(bool propagate_err, const char *filename, bool leakcheck)
13201315
label_write_error:
13211316
prof_dump_close(propagate_err);
13221317
label_open_close_error:
1323-
gctx_tree_iter(&gctxs, NULL, prof_gctx_finish_iter, NULL);
1318+
gctx_tree_iter(&gctxs, NULL, prof_gctx_finish_iter, tdata);
13241319
malloc_mutex_unlock(&prof_dump_mtx);
13251320
return (true);
13261321
}
@@ -1643,7 +1638,7 @@ const char *
16431638
prof_thread_name_get(void)
16441639
{
16451640
prof_tdata_t *tdata = prof_tdata_get(true);
1646-
if (tdata == NULL)
1641+
if ((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
16471642
return (NULL);
16481643
return (tdata->thread_name);
16491644
}
@@ -1656,7 +1651,7 @@ prof_thread_name_set(const char *thread_name)
16561651
char *s;
16571652

16581653
tdata = prof_tdata_get(true);
1659-
if (tdata == NULL)
1654+
if ((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
16601655
return (true);
16611656

16621657
size = strlen(thread_name) + 1;
@@ -1675,7 +1670,7 @@ bool
16751670
prof_thread_active_get(void)
16761671
{
16771672
prof_tdata_t *tdata = prof_tdata_get(true);
1678-
if (tdata == NULL)
1673+
if ((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
16791674
return (false);
16801675
return (tdata->active);
16811676
}
@@ -1686,7 +1681,7 @@ prof_thread_active_set(bool active)
16861681
prof_tdata_t *tdata;
16871682

16881683
tdata = prof_tdata_get(true);
1689-
if (tdata == NULL)
1684+
if ((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
16901685
return (true);
16911686
tdata->active = active;
16921687
return (false);

0 commit comments

Comments
 (0)