Skip to content

Commit

Permalink
Bug fix - use-after-free when b6b_offload() is called after all threa…
Browse files Browse the repository at this point in the history
…ds are dead
  • Loading branch information
dimkr committed Jan 15, 2018
1 parent 4f77295 commit b9c14db
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 4 deletions.
5 changes: 3 additions & 2 deletions include/b6b/interp.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of b6b.
*
* Copyright 2017 Dima Krasner
* Copyright 2017, 2018 Dima Krasner
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,7 +57,8 @@ struct b6b_interp {

static inline int b6b_threaded(struct b6b_interp *interp)
{
return b6b_thread_next(b6b_thread_first(&interp->threads)) ? 1 : 0;
const struct b6b_thread *t = b6b_thread_first(&interp->threads);
return (t && b6b_thread_next(t)) ? 1 : 0;
}

#else
Expand Down
4 changes: 2 additions & 2 deletions src/b6b_interp.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of b6b.
*
* Copyright 2017 Dima Krasner
* Copyright 2017, 2018 Dima Krasner
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -244,7 +244,7 @@ static void b6b_join(struct b6b_interp *interp)
/* destroy the main thread */
t = b6b_thread_first(&interp->threads);
if (t)
b6b_thread_destroy(t);
b6b_thread_pop(&interp->threads, t);

# ifdef B6B_HAVE_OFFLOAD_THREAD
b6b_offload_thread_stop(&interp->offth);
Expand Down
9 changes: 9 additions & 0 deletions tests/b6b_test_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,5 +199,14 @@ int main()
assert(interp.fg->_->s[i] == 0);
b6b_interp_destroy(&interp);

/* regression test: use-after-free in b6b_threaded() during cleanup, when
* all threads have been freed while the global frame still holds a
* reference to a file and its fclose() is offloaded */
assert(b6b_interp_new_argv(&interp, 0, NULL, B6B_OPT_TRACE));
assert(b6b_call_copy(&interp,
"{$global a [$open /dev/null]} {$spawn {{$exit}}} {$loop {{$yield}}}",
67) == B6B_EXIT);
b6b_interp_destroy(&interp);

return EXIT_SUCCESS;
}

0 comments on commit b9c14db

Please sign in to comment.