summaryrefslogtreecommitdiff
path: root/libphobos/testsuite/libphobos.thread/fiber_guard_page.d
blob: 49c22658542f48c4a7f0320913b7db4419f6dee2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// { dg-options "-O0" }
// { dg-shouldfail "segv or bus error" }
import core.thread;
import core.sys.posix.sys.mman;

// this should be true for most architectures
// (taken from core.thread)
version = StackGrowsDown;

enum stackSize = 4096;

// Simple method that causes a stack overflow
void stackMethod()
{
    // Over the stack size, so it overflows the stack
    int[stackSize/int.sizeof+100] x;
}

void main()
{
    auto test_fiber = new Fiber(&stackMethod, stackSize);

    // allocate a page below (above) the fiber's stack to make stack overflows possible (w/o segfaulting)
    version (StackGrowsDown)
    {
        static assert(__traits(identifier, test_fiber.tupleof[8]) == "m_pmem");
        auto stackBottom = test_fiber.tupleof[8];
        auto p = mmap(stackBottom - 8 * stackSize, 8 * stackSize,
                      PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
        assert(p !is null, "failed to allocate page");
    }
    else
    {
        auto m_sz = test_fiber.tupleof[7];
        auto m_pmem = test_fiber.tupleof[8];
        static assert(__traits(identifier, test_fiber.tupleof[7]) == "m_size");
        static assert(__traits(identifier, test_fiber.tupleof[8]) == "m_pmem");

        auto stackTop = m_pmem + m_sz;
        auto p = mmap(stackTop, 8 * stackSize,
                      PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
        assert(p !is null, "failed to allocate page");
    }

    // the guard page should prevent a mem corruption by stack
    // overflow and cause a segfault instead (or generate SIGBUS on *BSD flavors)
    test_fiber.call();
}