/* * Fork and then allocate in both the parent and the child, in case * fork messes up the heap. Note: this is not intended to test the * parent and child running concurrently -- that should probably be * its own test program. */ static void test12(void) { pid_t pid; void *p; tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ say("Child allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } say("Child done.\n"); exit(0); } /* parent */ say("Parent allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent"); } say("Parent done.\n"); dowait(pid); tprintf("Passed sbrk test 12.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate, then fork, then free the allocated page in the child. */ static void test14(void) { pid_t pid; void *p; tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt before forking"); } tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } tprintf("Child freeing a page...\n"); dosbrk(-PAGE_SIZE); exit(0); } dowait(pid); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent after child ran"); } tprintf("Passed sbrk test 14.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate one page, check that it holds data, and free it. */ static void test2(void) { void *op, *p, *q; op = dosbrk(0); tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); if (p != op) { errx(1, "FAILED: sbrk grow didn't return the old break " "(got %p, expected %p", p, op); } markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt"); } p = dosbrk(0); tprintf("Freeing the page...\n"); q = dosbrk(-PAGE_SIZE); if (q != p) { errx(1, "FAILED: sbrk shrink didn't return the old break " "(got %p, expected %p", q, p); } q = dosbrk(0); if (q != op) { errx(1, "FAILED: sbrk shrink didn't restore the heap " "(got %p, expected %p", q, op); } success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
static void test22(void) { int i; void *p, *q; int num = 10; int num_pages = 5 * 1024; // 20MB p = dosbrk(num_pages * PAGE_SIZE); q = dosbrk(0); if ((unsigned int)q - (unsigned int)p != (unsigned int)(num_pages*PAGE_SIZE)) { errx(1, "Heap size not equal to expected size: p=0x%x q=0x%x", (unsigned int)p, (unsigned int)q); } // Just touch the last 10 pages for (i = 0; i < num; i++) { markpage(p, num_pages-(i+1)); } // Check the last 10 pages for (i = 0; i < num; i++) { if (checkpage(p, num_pages-(i+1), false)) { errx(1, "FAILED: data corrupt"); } } success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate and then fork, in case fork doesn't preserve the heap. */ static void test13(void) { pid_t pid; void *p; printf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt before forking"); } printf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } exit(0); } if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent"); } dowait(pid); printf("Passed sbrk test 13.\n"); }
/* * Allocate six pages, check that they hold data and that the pages * don't get mixed up, and free them one at a time, repeating the * check after each free. */ static void test4(void) { const unsigned num = 6; void *op, *p, *q; unsigned i, j; bool bad; op = dosbrk(0); printf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); if (p != op) { errx(1, "FAILED: sbrk grow didn't return the old break " "(got %p, expected %p", p, op); } bad = false; for (i=0; i<num; i++) { markpage(p, i); if (checkpage(p, i, false)) { warnx("FAILED: data corrupt on page %u", i); bad = true; } } if (bad) { exit(1); } printf("Freeing the pages one at a time...\n"); for (i=num; i-- > 0; ) { (void)dosbrk(-PAGE_SIZE); for (j=0; j<i; j++) { if (checkpage(p, j, false)) { warnx("FAILED: data corrupt on page %u " "after freeing %u pages", j, i); bad = true; } } } if (bad) { exit(1); } q = dosbrk(0); if (q != op) { errx(1, "FAILED: sbrk shrink didn't restore the heap " "(got %p, expected %p", q, op); } printf("Passed sbrk test 4.\n"); }
/* * Allocate one page, check that it holds data, and leak it. */ static void test1(void) { void *p; tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt"); } success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate one page, check that it holds data, and leak it. */ static void test1(void) { void *p; printf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt"); } printf("Passed sbrk test 1.\n"); }
/* * Allocate all of memory one page at a time. The same restrictions * and considerations apply as above. */ static void test10(void) { void *p, *op; unsigned i, n; bool bad; tprintf("Allocating all of memory one page at a time:\n"); op = dosbrk(0); n = 0; while ((p = sbrk(PAGE_SIZE)) != (void *)-1) { markpagelight(op, n); n++; } tprintf("Got %u pages (%zu bytes).\n", n, (size_t)PAGE_SIZE * n); tprintf("Now freeing them.\n"); bad = false; for (i=0; i<n; i++) { if (checkpagelight(op, n - i - 1, false)) { warnx("FAILED: data corrupt on page %u", i); bad = true; } (void)dosbrk(-PAGE_SIZE); } if (bad) { exit(1); } tprintf("Freed %u pages.\n", n); p = dosbrk(0); if (p != op) { errx(1, "FAILURE: break did not return to original value"); } tprintf("Now let's see if I can allocate another page.\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt"); } (void)dosbrk(-PAGE_SIZE); tprintf("Passed sbrk test 10.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate six pages, check that they hold data and that the * pages don't get mixed up, and free them. */ static void test3(void) { const unsigned num = 6; void *op, *p, *q; unsigned i; bool bad; op = dosbrk(0); tprintf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); if (p != op) { errx(1, "FAILED: sbrk grow didn't return the old break " "(got %p, expected %p", p, op); } bad = false; for (i=0; i<num; i++) { markpage(p, i); if (checkpage(p, i, false)) { warnx("FAILED: data corrupt on page %u", i); bad = true; } } if (bad) { exit(1); } p = dosbrk(0); tprintf("Freeing the pages...\n"); q = dosbrk(-PAGE_SIZE * num); if (q != p) { errx(1, "FAILED: sbrk shrink didn't return the old break " "(got %p, expected %p", q, p); } q = dosbrk(0); if (q != op) { errx(1, "FAILED: sbrk shrink didn't restore the heap " "(got %p, expected %p", q, op); } success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate and free in both the parent and the child, and do more * than one page. */ static void test15(void) { unsigned num = 12; pid_t pid; unsigned i; void *p; tprintf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); for (i=0; i<num; i++) { markpage(p, i); } for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking"); } } tprintf("Freeing one page...\n"); (void)dosbrk(-PAGE_SIZE); num--; for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking (2)"); } } tprintf("Allocating two pages...\n"); (void)dosbrk(PAGE_SIZE * 2); markpage(p, num++); markpage(p, num++); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking (3)"); } } tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child"); } } say("Child: freeing three pages\n"); dosbrk(-PAGE_SIZE * 3); num -= 3; for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child (2)"); } } say("Child: allocating two pages\n"); dosbrk(PAGE_SIZE * 2); markpage(p, num++); markpage(p, num++); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child (3)"); } } say("Child: freeing all\n"); dosbrk(-PAGE_SIZE * num); exit(0); } say("Parent: allocating four pages\n"); dosbrk(PAGE_SIZE * 4); for (i=0; i<4; i++) { markpage(p, num++); } for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in parent"); } } say("Parent: waiting\n"); dowait(pid); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt after waiting"); } } (void)dosbrk(-PAGE_SIZE * num); tprintf("Passed sbrk test 15.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }