diff --git a/contrib/netbsd-tests/lib/libc/setjmp/t_setjmp.c b/contrib/netbsd-tests/lib/libc/setjmp/t_setjmp.c --- a/contrib/netbsd-tests/lib/libc/setjmp/t_setjmp.c +++ b/contrib/netbsd-tests/lib/libc/setjmp/t_setjmp.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,8 @@ #define TEST_U_SETJMP 1 #define TEST_SIGSETJMP_SAVE 2 #define TEST_SIGSETJMP_NOSAVE 3 +#define TEST_LONGJMP_ZERO 4 +#define TEST_U_LONGJMP_ZERO 5 static int expectsignal; @@ -101,12 +104,16 @@ sigjmp_buf sjb; sigset_t ss; int i, x; + volatile bool did_longjmp; i = getpid(); + did_longjmp = false; - if (test == TEST_SETJMP || test == TEST_SIGSETJMP_SAVE) + if (test == TEST_SETJMP || test == TEST_SIGSETJMP_SAVE || + test == TEST_LONGJMP_ZERO) expectsignal = 0; - else if (test == TEST_U_SETJMP || test == TEST_SIGSETJMP_NOSAVE) + else if (test == TEST_U_SETJMP || test == TEST_SIGSETJMP_NOSAVE || + test == TEST_U_LONGJMP_ZERO) expectsignal = 1; else atf_tc_fail("unknown test"); @@ -119,26 +126,37 @@ REQUIRE_ERRNO(sigaddset(&ss, SIGABRT) != -1); REQUIRE_ERRNO(sigprocmask(SIG_BLOCK, &ss, NULL) != -1); - if (test == TEST_SETJMP) + if (test == TEST_SETJMP || test == TEST_LONGJMP_ZERO) x = setjmp(jb); - else if (test == TEST_U_SETJMP) + else if (test == TEST_U_SETJMP || test == TEST_U_LONGJMP_ZERO) x = _setjmp(jb); else x = sigsetjmp(sjb, !expectsignal); if (x != 0) { - ATF_REQUIRE_MSG(x == i, "setjmp returned wrong value"); + if (test == TEST_LONGJMP_ZERO || test == TEST_U_LONGJMP_ZERO) + ATF_REQUIRE_MSG(x == 1, "setjmp returned wrong value"); + else + ATF_REQUIRE_MSG(x == i, "setjmp returned wrong value"); + kill(i, SIGABRT); ATF_REQUIRE_MSG(!expectsignal, "kill(SIGABRT) failed"); atf_tc_pass(); + } else if (did_longjmp) { + atf_tc_fail("setjmp returned zero after longjmp"); } REQUIRE_ERRNO(sigprocmask(SIG_UNBLOCK, &ss, NULL) != -1); + did_longjmp = true; if (test == TEST_SETJMP) longjmp(jb, i); + else if (test == TEST_LONGJMP_ZERO) + longjmp(jb, 0); else if (test == TEST_U_SETJMP) _longjmp(jb, i); + else if (test == TEST_U_LONGJMP_ZERO) + _longjmp(jb, 0); else siglongjmp(sjb, i); @@ -185,12 +203,34 @@ h_check(TEST_SIGSETJMP_NOSAVE); } +ATF_TC(longjmp_zero); +ATF_TC_HEAD(longjmp_zero, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks longjmp(3) with a zero value"); +} +ATF_TC_BODY(longjmp_zero, tc) +{ + h_check(TEST_LONGJMP_ZERO); +} + +ATF_TC(_longjmp_zero); +ATF_TC_HEAD(_longjmp_zero, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks _longjmp(3) with a zero value"); +} +ATF_TC_BODY(_longjmp_zero, tc) +{ + h_check(TEST_U_LONGJMP_ZERO); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, setjmp); ATF_TP_ADD_TC(tp, _setjmp); ATF_TP_ADD_TC(tp, sigsetjmp_save); ATF_TP_ADD_TC(tp, sigsetjmp_nosave); + ATF_TP_ADD_TC(tp, longjmp_zero); + ATF_TP_ADD_TC(tp, _longjmp_zero); return atf_no_error(); } diff --git a/lib/libc/aarch64/gen/_setjmp.S b/lib/libc/aarch64/gen/_setjmp.S --- a/lib/libc/aarch64/gen/_setjmp.S +++ b/lib/libc/aarch64/gen/_setjmp.S @@ -91,7 +91,8 @@ #endif /* Load the return value */ - mov x0, x1 + cmp x1, #0 + csinc x0, x1, xzr, ne ret botch: diff --git a/lib/libc/aarch64/gen/setjmp.S b/lib/libc/aarch64/gen/setjmp.S --- a/lib/libc/aarch64/gen/setjmp.S +++ b/lib/libc/aarch64/gen/setjmp.S @@ -113,7 +113,8 @@ ldp d14, d15, [x0] /* Load the return value */ - mov x0, x1 + cmp x1, #0 + csinc x0, x1, xzr, ne ret botch: diff --git a/lib/libc/riscv/gen/_setjmp.S b/lib/libc/riscv/gen/_setjmp.S --- a/lib/libc/riscv/gen/_setjmp.S +++ b/lib/libc/riscv/gen/_setjmp.S @@ -131,6 +131,9 @@ /* Load the return value */ mv a0, a1 + bnez a1, 1f + li a0, 1 +1: ret botch: diff --git a/lib/libc/riscv/gen/setjmp.S b/lib/libc/riscv/gen/setjmp.S --- a/lib/libc/riscv/gen/setjmp.S +++ b/lib/libc/riscv/gen/setjmp.S @@ -161,6 +161,9 @@ /* Load the return value */ mv a0, a1 + bnez a1, 1f + li a0, 1 +1: ret botch: