X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Faltstack%2Ftest%2Frun.c;fp=ccan%2Faltstack%2Ftest%2Frun.c;h=adc1020eb0a12cf4019c9593cb7aa9ff0a9392c7;hp=0000000000000000000000000000000000000000;hb=e65a92188aa1ac4c27a86d427acdf09417595ade;hpb=9840dbd3e19eaee1ed82a445cd5e9f041a434f70 diff --git a/ccan/altstack/test/run.c b/ccan/altstack/test/run.c new file mode 100644 index 00000000..adc1020e --- /dev/null +++ b/ccan/altstack/test/run.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define _XOPEN_SOURCE 700 +#include + +enum { + getrlimit_ = 1<<0, + setrlimit_ = 1<<1, + mmap_ = 1<<2, + sigaltstack_ = 1<<3, + sigaction_ = 1<<4, + munmap_ = 1<<5, +}; +int fail, call1, call2; +char *m_; +rlim_t max_; +#define e(x) (900+(x)) +#define seterr(x) (errno = e(x)) +#define setcall(x) ((call1 |= !errno ? (x) : 0), (call2 |= errno || out_ ? (x) : 0)) +#define getrlimit(...) (fail&getrlimit_ ? (seterr(getrlimit_), -1) : (setcall(getrlimit_), getrlimit(__VA_ARGS__))) +#define mmap(...) (fail&mmap_ ? (seterr(mmap_), (void *)-1) : (setcall(mmap_), mmap(__VA_ARGS__))) +#define munmap(a, b) (fail&munmap_ ? (seterr(munmap_), -1) : (setcall(munmap_), munmap(m_=(a), max_=(b)))) +#define setrlimit(...) (fail&setrlimit_ ? (seterr(setrlimit_), -1) : (setcall(setrlimit_), setrlimit(__VA_ARGS__))) +#define sigaltstack(...) (fail&sigaltstack_ ? (seterr(sigaltstack_), -1) : (setcall(sigaltstack_), sigaltstack(__VA_ARGS__))) +#define sigaction(...) (fail&sigaction_ ? (seterr(sigaction_), -1) : (setcall(sigaction_), sigaction(__VA_ARGS__))) + +#define KiB (1024UL) +#define MiB (KiB*KiB) +#define GiB (MiB*KiB) +#define TiB (GiB*KiB) + +FILE *mystderr; +#undef stderr +#define stderr mystderr +#undef ok +#include +#undef ok + +long used; + +static void __attribute__((optimize("O0"))) dn(unsigned long i) +{ + if (used) used = altstack_used(); + if (i) dn(--i); +} +static void *wrap(void *i) +{ + dn((unsigned long) i); + return wrap; +} + +int main(void) +{ + plan_tests(16); + +#define chkfail(x, y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, ok1((fail = x) && (y) && errno == (z) && call1 == (c1) && call2 == (c2))); +#define chkok( y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, fail = 0, ok1((y) && errno == (z) && call1 == (c1) && call2 == (c2))); + + chkfail(getrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(getrlimit_), + 0, + 0); + + chkfail(setrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(setrlimit_), + getrlimit_, + 0); + + chkfail(mmap_, altstack(8*MiB, wrap, 0, 0) == -1, e(mmap_), + getrlimit_|setrlimit_, + setrlimit_); + + chkfail(sigaltstack_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaltstack_), + getrlimit_|setrlimit_|mmap_, + setrlimit_|munmap_); + + chkfail(sigaction_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaction_), + getrlimit_|setrlimit_|mmap_|sigaltstack_, + setrlimit_|munmap_|sigaltstack_); + + chkfail(munmap_, altstack(8*MiB, wrap, 0, 0) == 1, e(munmap_), + getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, + setrlimit_|sigaltstack_|sigaction_); + if (fail = 0, munmap(m_, max_) == -1) + err(1, "munmap"); + + chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, + getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, + setrlimit_|munmap_|sigaltstack_|sigaction_); + + // be sure segv catch is repeatable (SA_NODEFER) + chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, + getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, + setrlimit_|munmap_|sigaltstack_|sigaction_); + + used = 1; + chkfail(munmap_, altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, + getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, + setrlimit_|sigaltstack_|sigaction_); + if (fail = 0, munmap(m_, max_) == -1) + err(1, "munmap"); + + ok1(used > 1*MiB-1*KiB && used < 1*MiB); + + char *p; + for(p = altstack_geterr(); *p; p++) + if (*p >= '0' && *p <= '9') + *p = '~'; + + #define estr "(altstack@~~~) SIGSEGV caught; (altstack@~~~) munmap(m, max): Unknown error ~~~" + ok1(strcmp(altstack_geterr(), estr) == 0); + + char buf[ALTSTACK_ERR_MAXLEN*2] = {0}; + if ((mystderr = fmemopen(buf, sizeof(buf), "w")) == NULL) + err(1, "fmemopen"); + + altstack_perror(); + fflush(mystderr); + ok1(strcmp(buf, estr "\n") == 0); + + used = 1; + chkok( altstack(8*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, + getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, + setrlimit_|munmap_|sigaltstack_|sigaction_); + + ok1(used > 8*MiB-8*KiB && used < 8*MiB); + + used = 0; + chkok( altstack(8*MiB, wrap, (void *) 100000, 0) == 0, 0, + getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_|munmap_, + setrlimit_|munmap_|sigaltstack_|sigaction_); + + used = 1; + altstack_rsp_save(); + dn(0); + ok1(used == 32); + + return exit_status(); +}