libc: Fix longjmp/_longjmp(buf, 0) for AArch64 and RISC-V
These architectures fail to handle this special case, and will cause the corresponding setjmp/_setjmp to return 0 rather than 1. Fix this and add regression tests (also committed upstream). PR: 268684 Reviewed by: arichardson, jhb MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D29363
This commit is contained in:
parent
23ed2a38c2
commit
9fb118bebc
@ -70,6 +70,7 @@ __RCSID("$NetBSD: t_setjmp.c,v 1.2 2017/01/14 21:08:17 christos Exp $");
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -83,6 +84,8 @@ __RCSID("$NetBSD: t_setjmp.c,v 1.2 2017/01/14 21:08:17 christos Exp $");
|
|||||||
#define TEST_U_SETJMP 1
|
#define TEST_U_SETJMP 1
|
||||||
#define TEST_SIGSETJMP_SAVE 2
|
#define TEST_SIGSETJMP_SAVE 2
|
||||||
#define TEST_SIGSETJMP_NOSAVE 3
|
#define TEST_SIGSETJMP_NOSAVE 3
|
||||||
|
#define TEST_LONGJMP_ZERO 4
|
||||||
|
#define TEST_U_LONGJMP_ZERO 5
|
||||||
|
|
||||||
static int expectsignal;
|
static int expectsignal;
|
||||||
|
|
||||||
@ -101,12 +104,16 @@ h_check(int test)
|
|||||||
sigjmp_buf sjb;
|
sigjmp_buf sjb;
|
||||||
sigset_t ss;
|
sigset_t ss;
|
||||||
int i, x;
|
int i, x;
|
||||||
|
volatile bool did_longjmp;
|
||||||
|
|
||||||
i = getpid();
|
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;
|
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;
|
expectsignal = 1;
|
||||||
else
|
else
|
||||||
atf_tc_fail("unknown test");
|
atf_tc_fail("unknown test");
|
||||||
@ -119,26 +126,37 @@ h_check(int test)
|
|||||||
REQUIRE_ERRNO(sigaddset(&ss, SIGABRT) != -1);
|
REQUIRE_ERRNO(sigaddset(&ss, SIGABRT) != -1);
|
||||||
REQUIRE_ERRNO(sigprocmask(SIG_BLOCK, &ss, NULL) != -1);
|
REQUIRE_ERRNO(sigprocmask(SIG_BLOCK, &ss, NULL) != -1);
|
||||||
|
|
||||||
if (test == TEST_SETJMP)
|
if (test == TEST_SETJMP || test == TEST_LONGJMP_ZERO)
|
||||||
x = setjmp(jb);
|
x = setjmp(jb);
|
||||||
else if (test == TEST_U_SETJMP)
|
else if (test == TEST_U_SETJMP || test == TEST_U_LONGJMP_ZERO)
|
||||||
x = _setjmp(jb);
|
x = _setjmp(jb);
|
||||||
else
|
else
|
||||||
x = sigsetjmp(sjb, !expectsignal);
|
x = sigsetjmp(sjb, !expectsignal);
|
||||||
|
|
||||||
if (x != 0) {
|
if (x != 0) {
|
||||||
|
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");
|
ATF_REQUIRE_MSG(x == i, "setjmp returned wrong value");
|
||||||
|
|
||||||
kill(i, SIGABRT);
|
kill(i, SIGABRT);
|
||||||
ATF_REQUIRE_MSG(!expectsignal, "kill(SIGABRT) failed");
|
ATF_REQUIRE_MSG(!expectsignal, "kill(SIGABRT) failed");
|
||||||
atf_tc_pass();
|
atf_tc_pass();
|
||||||
|
} else if (did_longjmp) {
|
||||||
|
atf_tc_fail("setjmp returned zero after longjmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE_ERRNO(sigprocmask(SIG_UNBLOCK, &ss, NULL) != -1);
|
REQUIRE_ERRNO(sigprocmask(SIG_UNBLOCK, &ss, NULL) != -1);
|
||||||
|
|
||||||
|
did_longjmp = true;
|
||||||
if (test == TEST_SETJMP)
|
if (test == TEST_SETJMP)
|
||||||
longjmp(jb, i);
|
longjmp(jb, i);
|
||||||
|
else if (test == TEST_LONGJMP_ZERO)
|
||||||
|
longjmp(jb, 0);
|
||||||
else if (test == TEST_U_SETJMP)
|
else if (test == TEST_U_SETJMP)
|
||||||
_longjmp(jb, i);
|
_longjmp(jb, i);
|
||||||
|
else if (test == TEST_U_LONGJMP_ZERO)
|
||||||
|
_longjmp(jb, 0);
|
||||||
else
|
else
|
||||||
siglongjmp(sjb, i);
|
siglongjmp(sjb, i);
|
||||||
|
|
||||||
@ -185,12 +203,34 @@ ATF_TC_BODY(sigsetjmp_nosave, tc)
|
|||||||
h_check(TEST_SIGSETJMP_NOSAVE);
|
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_TCS(tp)
|
||||||
{
|
{
|
||||||
ATF_TP_ADD_TC(tp, setjmp);
|
ATF_TP_ADD_TC(tp, setjmp);
|
||||||
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_save);
|
||||||
ATF_TP_ADD_TC(tp, sigsetjmp_nosave);
|
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();
|
return atf_no_error();
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,8 @@ ENTRY(_longjmp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Load the return value */
|
/* Load the return value */
|
||||||
mov x0, x1
|
cmp x1, #0
|
||||||
|
csinc x0, x1, xzr, ne
|
||||||
ret
|
ret
|
||||||
|
|
||||||
botch:
|
botch:
|
||||||
|
@ -113,7 +113,8 @@ ENTRY(longjmp)
|
|||||||
ldp d14, d15, [x0]
|
ldp d14, d15, [x0]
|
||||||
|
|
||||||
/* Load the return value */
|
/* Load the return value */
|
||||||
mov x0, x1
|
cmp x1, #0
|
||||||
|
csinc x0, x1, xzr, ne
|
||||||
ret
|
ret
|
||||||
|
|
||||||
botch:
|
botch:
|
||||||
|
@ -131,6 +131,9 @@ ENTRY(_longjmp)
|
|||||||
|
|
||||||
/* Load the return value */
|
/* Load the return value */
|
||||||
mv a0, a1
|
mv a0, a1
|
||||||
|
bnez a1, 1f
|
||||||
|
li a0, 1
|
||||||
|
1:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
botch:
|
botch:
|
||||||
|
@ -161,6 +161,9 @@ ENTRY(longjmp)
|
|||||||
|
|
||||||
/* Load the return value */
|
/* Load the return value */
|
||||||
mv a0, a1
|
mv a0, a1
|
||||||
|
bnez a1, 1f
|
||||||
|
li a0, 1
|
||||||
|
1:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
botch:
|
botch:
|
||||||
|
Loading…
Reference in New Issue
Block a user