2008-05-27 Roland McGrath <roland@redhat.com>
* syscall.c [LINUX] (is_negated_errno): New function.
(get_error) [LINUX]: Use it for all such cases.
Fixes RH#447587.
diff --git a/syscall.c b/syscall.c
index a2d26d3..428b868 100644
--- a/syscall.c
+++ b/syscall.c
@@ -1473,6 +1473,23 @@
return 1;
}
+#ifdef LINUX
+/*
+ * Check the syscall return value register value for whether it is
+ * a negated errno code indicating an error, or a success return value.
+ */
+static inline int
+is_negated_errno(unsigned long int val)
+{
+ unsigned long int max = -(long int) nerrnos;
+ if (personality_wordsize[current_personality] < sizeof(val)) {
+ val = (unsigned int) val;
+ max = (unsigned int) max;
+ }
+ return val > max;
+}
+#endif
+
static int
get_error(tcp)
struct tcb *tcp;
@@ -1480,57 +1497,57 @@
int u_error = 0;
#ifdef LINUX
#if defined(S390) || defined(S390X)
- if (gpr2 && (unsigned) -gpr2 < nerrnos) {
- tcp->u_rval = -1;
- u_error = -gpr2;
- }
- else {
- tcp->u_rval = gpr2;
- u_error = 0;
- }
+ if (is_negated_errno(gpr2)) {
+ tcp->u_rval = -1;
+ u_error = -gpr2;
+ }
+ else {
+ tcp->u_rval = gpr2;
+ u_error = 0;
+ }
#else /* !S390 && !S390X */
#ifdef I386
- if (eax < 0 && -eax < nerrnos) {
- tcp->u_rval = -1;
- u_error = -eax;
- }
- else {
- tcp->u_rval = eax;
- u_error = 0;
- }
+ if (is_negated_errno(eax)) {
+ tcp->u_rval = -1;
+ u_error = -eax;
+ }
+ else {
+ tcp->u_rval = eax;
+ u_error = 0;
+ }
#else /* !I386 */
#ifdef X86_64
- if (rax < 0 && -rax < nerrnos) {
- tcp->u_rval = -1;
- u_error = -rax;
- }
- else {
- tcp->u_rval = rax;
- u_error = 0;
- }
+ if (is_negated_errno(rax)) {
+ tcp->u_rval = -1;
+ u_error = -rax;
+ }
+ else {
+ tcp->u_rval = rax;
+ u_error = 0;
+ }
#else
#ifdef IA64
- if (ia32) {
- int err;
+ if (ia32) {
+ int err;
- err = (int)r8;
- if (err < 0 && -err < nerrnos) {
- tcp->u_rval = -1;
- u_error = -err;
- }
- else {
- tcp->u_rval = err;
- u_error = 0;
- }
- } else {
- if (r10) {
- tcp->u_rval = -1;
- u_error = r8;
- } else {
- tcp->u_rval = r8;
- u_error = 0;
- }
+ err = (int)r8;
+ if (is_negated_errno(err)) {
+ tcp->u_rval = -1;
+ u_error = -err;
}
+ else {
+ tcp->u_rval = err;
+ u_error = 0;
+ }
+ } else {
+ if (r10) {
+ tcp->u_rval = -1;
+ u_error = r8;
+ } else {
+ tcp->u_rval = r8;
+ u_error = 0;
+ }
+ }
#else /* !IA64 */
#ifdef MIPS
if (a3) {
@@ -1542,7 +1559,7 @@
}
#else
#ifdef POWERPC
- if (result && (unsigned long) -result < nerrnos) {
+ if (is_negated_errno(result)) {
tcp->u_rval = -1;
u_error = -result;
}
@@ -1552,7 +1569,7 @@
}
#else /* !POWERPC */
#ifdef M68K
- if (d0 && (unsigned) -d0 < nerrnos) {
+ if (is_negated_errno(d0)) {
tcp->u_rval = -1;
u_error = -d0;
}
@@ -1562,7 +1579,7 @@
}
#else /* !M68K */
#ifdef ARM
- if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
+ if (is_negated_errno(regs.ARM_r0)) {
tcp->u_rval = -1;
u_error = -regs.ARM_r0;
}
@@ -1602,7 +1619,7 @@
}
#else /* !SPARC64 */
#ifdef HPPA
- if (r28 && (unsigned) -r28 < nerrnos) {
+ if (is_negated_errno(r28)) {
tcp->u_rval = -1;
u_error = -r28;
}
@@ -1612,19 +1629,19 @@
}
#else
#ifdef SH
- /* interpret R0 as return value or error number */
- if (r0 && (unsigned) -r0 < nerrnos) {
- tcp->u_rval = -1;
- u_error = -r0;
- }
- else {
- tcp->u_rval = r0;
- u_error = 0;
- }
+ /* interpret R0 as return value or error number */
+ if (is_negated_errno(r0)) {
+ tcp->u_rval = -1;
+ u_error = -r0;
+ }
+ else {
+ tcp->u_rval = r0;
+ u_error = 0;
+ }
#else
#ifdef SH64
/* interpret result as return value or error number */
- if (r9 && (unsigned) -r9 < nerrnos) {
+ if (is_negated_errno(r9)) {
tcp->u_rval = -1;
u_error = -r9;
}
@@ -2007,7 +2024,7 @@
if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
- else
+ else
nargs = tcp->u_nargs = MAX_ARGS;
if (ptrace (PTRACE_GETREGS, pid, NULL, (long) ®s) < 0)