(root)/
strace-6.5/
tests-m32/
xselect.c
       1  /*
       2   * Check decoding of select/_newselect syscalls.
       3   *
       4   * Copyright (c) 2015-2018 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2015-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  /*
      12   * Based on test by Dr. David Alan Gilbert <dave@treblig.org>
      13   */
      14  
      15  #include <errno.h>
      16  #include <limits.h>
      17  #include <stdint.h>
      18  #include <stdio.h>
      19  #include <string.h>
      20  #include <unistd.h>
      21  #include <sys/select.h>
      22  
      23  #include "kernel_timeval.h"
      24  
      25  static const char *errstr;
      26  
      27  static long
      28  xselect(const kernel_ulong_t nfds,
      29  	const kernel_ulong_t rs,
      30  	const kernel_ulong_t ws,
      31  	const kernel_ulong_t es,
      32  	const kernel_ulong_t tv)
      33  #ifndef xselect
      34  {
      35  	long rc = syscall(TEST_SYSCALL_NR,
      36  			  F8ILL_KULONG_MASK | nfds, rs, ws, es, tv);
      37  	errstr = sprintrc(rc);
      38  	return rc;
      39  }
      40  #else
      41  	;
      42  #endif
      43  
      44  #define XSELECT(expected_, ...)						\
      45  	do {								\
      46  		long rc = xselect(__VA_ARGS__);				\
      47  		if (rc != (expected_))					\
      48  			perror_msg_and_fail(TEST_SYSCALL_STR		\
      49  					    ": expected %d"		\
      50  					    ", returned %ld",		\
      51  					    (expected_), rc);		\
      52  	} while (0)							\
      53  /* End of XSELECT definition. */
      54  
      55  int
      56  main(void)
      57  {
      58  #ifdef PATH_TRACING_FD
      59  	skip_if_unavailable("/proc/self/fd/");
      60  #endif
      61  
      62  #if defined(PATH_TRACING_FD) || defined(TRACING_FD)
      63  	static const int add_fd =
      64  # ifdef PATH_TRACING_FD
      65  				PATH_TRACING_FD
      66  # else
      67  				TRACING_FD
      68  # endif
      69  				;
      70  #endif /* PATH_TRACING_FD || TRACING_FD */
      71  
      72  	for (int i = 3; i < FD_SETSIZE; ++i) {
      73  #ifdef TRACING_FD
      74  		if (i == TRACING_FD)
      75  			continue;
      76  #endif
      77  #ifdef PATH_TRACING_FD
      78  		if (i == PATH_TRACING_FD)
      79  			continue;
      80  #endif
      81  		(void) close(i);
      82  	}
      83  
      84  	int fds[2];
      85  	if (pipe(fds))
      86  		perror_msg_and_fail("pipe");
      87  
      88  	static const int smallset_size = sizeof(kernel_ulong_t) * 8;
      89  	const int nfds = fds[1] + 1;
      90  	if (nfds > smallset_size)
      91  		error_msg_and_fail("nfds[%d] > smallset_size[%d]\n",
      92  				   nfds, smallset_size);
      93  
      94  	kernel_old_timeval_t tv_in = { 0, 123 };
      95  	kernel_old_timeval_t *const tv = tail_memdup(&tv_in, sizeof(tv_in));
      96  	const uintptr_t a_tv = (uintptr_t) tv;
      97  
      98  	TAIL_ALLOC_OBJECT_VAR_PTR(kernel_ulong_t, l_rs);
      99  	fd_set *const rs = (void *) l_rs;
     100  	const uintptr_t a_rs = (uintptr_t) rs;
     101  
     102  	TAIL_ALLOC_OBJECT_VAR_PTR(kernel_ulong_t, l_ws);
     103  	fd_set *const ws = (void *) l_ws;
     104  	const uintptr_t a_ws = (uintptr_t) ws;
     105  
     106  	TAIL_ALLOC_OBJECT_VAR_PTR(kernel_ulong_t, l_es);
     107  	fd_set *const es = (void *) l_es;
     108  	const uintptr_t a_es = (uintptr_t) es;
     109  
     110  	long rc;
     111  
     112  	/*
     113  	 * An equivalent of nanosleep.
     114  	 */
     115  	if (xselect(0, 0, 0, 0, a_tv)) {
     116  		if (errno == ENOSYS)
     117  			perror_msg_and_skip(TEST_SYSCALL_STR);
     118  		else
     119  			perror_msg_and_fail(TEST_SYSCALL_STR);
     120  	}
     121  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     122  	printf("%s(0, NULL, NULL, NULL, {tv_sec=%lld, tv_usec=%llu})"
     123  	       " = 0 (Timeout)\n",
     124  	       TEST_SYSCALL_STR, (long long) tv_in.tv_sec,
     125  	       zero_extend_signed_to_ull(tv_in.tv_usec));
     126  #endif
     127  
     128  	/* EFAULT on tv argument */
     129  	XSELECT(-1, 0, 0, 0, 0, a_tv + 1);
     130  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     131  	printf("%s(0, NULL, NULL, NULL, %#lx) = %s\n",
     132  	       TEST_SYSCALL_STR, (unsigned long) a_tv + 1, errstr);
     133  #endif
     134  
     135  	/*
     136  	 * Start with a nice simple select with the same set.
     137  	 */
     138  	for (int i = nfds; i <= smallset_size; ++i) {
     139  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
     140  		XSELECT(1, i, a_rs, a_rs, a_rs, 0);
     141  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     142  		printf("%s(%d, [%d %d], [%d %d], [%d %d], NULL) = 1 ()\n",
     143  		       TEST_SYSCALL_STR, i, fds[0], fds[1],
     144  		       fds[0], fds[1], fds[0], fds[1]);
     145  #else /* PATH_TRACING_FD || TRACING_FD */
     146  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]) | (1UL << add_fd);
     147  		XSELECT(i > add_fd ? 3 : 1, i, a_rs, a_rs, a_rs, 0);
     148  		if (i > add_fd) {
     149  			printf("%s(%d, [%d %d %d], [%d %d %d], [%d %d %d]"
     150  			       ", NULL) = 3 ()\n",
     151  			       TEST_SYSCALL_STR, i,
     152  			       fds[0], fds[1], add_fd,
     153  			       fds[0], fds[1], add_fd,
     154  			       fds[0], fds[1], add_fd);
     155  		}
     156  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     157  #if defined(PATH_TRACING_FD) && defined(TRACING_FD)
     158  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]) |
     159  			(1UL << TRACING_FD) | (1UL << PATH_TRACING_FD);
     160  		XSELECT(1 + 2 * (!!(i > TRACING_FD) + !!(i > PATH_TRACING_FD)),
     161  			i, a_rs, a_rs, a_rs, 0);
     162  		if (i > PATH_TRACING_FD) {
     163  			printf("%s(%d, [%d %d %d %d], [%d %d %d %d]"
     164  			       ", [%d %d %d %d], NULL) = 5 ()\n",
     165  			       TEST_SYSCALL_STR, i,
     166  			       fds[0], fds[1], TRACING_FD, PATH_TRACING_FD,
     167  			       fds[0], fds[1], TRACING_FD, PATH_TRACING_FD,
     168  			       fds[0], fds[1], TRACING_FD, PATH_TRACING_FD);
     169  		} else if (i > TRACING_FD) {
     170  			printf("%s(%d, [%d %d %d], [%d %d %d], [%d %d %d]"
     171  			       ", NULL) = 3 ()\n",
     172  			       TEST_SYSCALL_STR, i,
     173  			       fds[0], fds[1], TRACING_FD,
     174  			       fds[0], fds[1], TRACING_FD,
     175  			       fds[0], fds[1], TRACING_FD);
     176  		}
     177  #endif /* PATH_TRACING_FD && TRACING_FD */
     178  	}
     179  
     180  	/*
     181  	 * Odd timeout.
     182  	 */
     183  	*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
     184  	tv_in.tv_sec = 0xdeadbeefU;
     185  	tv_in.tv_usec = 0xfacefeedU;
     186  	memcpy(tv, &tv_in, sizeof(tv_in));
     187  	rc = xselect(nfds, a_rs, a_rs, a_rs, a_tv);
     188  	if (rc < 0) {
     189  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     190  		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
     191  		       ", {tv_sec=%lld, tv_usec=%llu}) = %s\n",
     192  		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
     193  		       fds[0], fds[1], fds[0], fds[1],
     194  		       (long long) tv_in.tv_sec,
     195  		       zero_extend_signed_to_ull(tv_in.tv_usec),
     196  		       errstr);
     197  #endif /* PATH_TRACING_FD && TRACING_FD */
     198  	} else {
     199  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     200  		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
     201  		       ", {tv_sec=%lld, tv_usec=%llu}) = %ld"
     202  		       " (left {tv_sec=%lld, tv_usec=%llu})\n",
     203  		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
     204  		       fds[0], fds[1], fds[0], fds[1],
     205  		       (long long) tv_in.tv_sec,
     206  		       zero_extend_signed_to_ull(tv_in.tv_usec),
     207  		       rc, (long long) tv->tv_sec,
     208  		       zero_extend_signed_to_ull(tv->tv_usec));
     209  #endif /* PATH_TRACING_FD && TRACING_FD */
     210  	}
     211  
     212  	/*
     213  	 * Very odd timeout.
     214  	 */
     215  	*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
     216  	tv_in.tv_sec = (time_t) 0xcafef00ddeadbeefLL;
     217  	tv_in.tv_usec = (suseconds_t) 0xbadc0dedfacefeedLL;
     218  	memcpy(tv, &tv_in, sizeof(tv_in));
     219  	rc = xselect(nfds, a_rs, a_rs, a_rs, a_tv);
     220  	if (rc < 0) {
     221  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     222  		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
     223  		       ", {tv_sec=%lld, tv_usec=%llu}) = %s\n",
     224  		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
     225  		       fds[0], fds[1], fds[0], fds[1],
     226  		       (long long) tv_in.tv_sec,
     227  		       zero_extend_signed_to_ull(tv_in.tv_usec),
     228  		       errstr);
     229  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     230  	} else {
     231  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     232  		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
     233  		       ", {tv_sec=%lld, tv_usec=%llu}) = %ld"
     234  		       " (left {tv_sec=%lld, tv_usec=%llu})\n",
     235  		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
     236  		       fds[0], fds[1], fds[0], fds[1],
     237  		       (long long) tv_in.tv_sec,
     238  		       zero_extend_signed_to_ull(tv_in.tv_usec),
     239  		       rc, (long long) tv->tv_sec,
     240  		       zero_extend_signed_to_ull(tv->tv_usec));
     241  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     242  	}
     243  
     244  	/*
     245  	 * Another simple one, with a timeout.
     246  	 */
     247  	for (int i = nfds; i <= smallset_size; ++i) {
     248  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
     249  		*l_ws = (1UL << 1) | (1UL << 2) |
     250  			(1UL << fds[0]) | (1UL << fds[1]);
     251  		*l_es = 0;
     252  		tv_in.tv_sec = 0xc0de1;
     253  		tv_in.tv_usec = 0xc0de2;
     254  		memcpy(tv, &tv_in, sizeof(tv_in));
     255  		XSELECT(3, i, a_rs, a_ws, a_es, a_tv);
     256  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     257  		printf("%s(%d, [%d %d], [%d %d %d %d], []"
     258  		       ", {tv_sec=%lld, tv_usec=%llu}) = 3 (out [1 2 %d]"
     259  		       ", left {tv_sec=%lld, tv_usec=%llu})\n",
     260  		       TEST_SYSCALL_STR, i, fds[0], fds[1],
     261  		       1, 2, fds[0], fds[1],
     262  		       (long long) tv_in.tv_sec,
     263  		       zero_extend_signed_to_ull(tv_in.tv_usec),
     264  		       fds[1],
     265  		       (long long) tv->tv_sec,
     266  		       zero_extend_signed_to_ull(tv->tv_usec));
     267  #else /* PATH_TRACING_FD || TRACING_FD */
     268  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]) | (1UL << add_fd);
     269  		*l_ws = (1UL << 1) | (1UL << 2) |
     270  			(1UL << fds[0]) | (1UL << fds[1]);
     271  		tv_in.tv_sec = 0xc0de1;
     272  		tv_in.tv_usec = 0xc0de2;
     273  		memcpy(tv, &tv_in, sizeof(tv_in));
     274  		XSELECT(3 + (i > add_fd), i, a_rs, a_ws, a_es, a_tv);
     275  		if (i > add_fd) {
     276  			printf("%s(%d, [%d %d %d], [%d %d %d %d], []"
     277  			       ", {tv_sec=%lld, tv_usec=%llu})"
     278  			       " = 4 (in [%d], out [1 2 %d]"
     279  			       ", left {tv_sec=%lld, tv_usec=%llu})\n",
     280  			       TEST_SYSCALL_STR, i,
     281  			       fds[0], fds[1], add_fd,
     282  			       1, 2, fds[0], fds[1],
     283  			       (long long) tv_in.tv_sec,
     284  			       zero_extend_signed_to_ull(tv_in.tv_usec),
     285  			       add_fd, fds[1],
     286  			       (long long) tv->tv_sec,
     287  			       zero_extend_signed_to_ull(tv->tv_usec));
     288  		}
     289  
     290  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
     291  		*l_ws = (1UL << 1) | (1UL << 2) |
     292  			(1UL << fds[0]) | (1UL << fds[1]) | (1UL << add_fd);
     293  		tv_in.tv_sec = 0xc0de1;
     294  		tv_in.tv_usec = 0xc0de2;
     295  		memcpy(tv, &tv_in, sizeof(tv_in));
     296  		XSELECT(3 + (i > add_fd), i, a_rs, a_ws, a_es, a_tv);
     297  		if (i > add_fd) {
     298  			printf("%s(%d, [%d %d], [%d %d %d %d %d], []"
     299  			       ", {tv_sec=%lld, tv_usec=%llu})"
     300  			       " = 4 (out [1 2 %d %d]"
     301  			       ", left {tv_sec=%lld, tv_usec=%llu})\n",
     302  			       TEST_SYSCALL_STR, i,
     303  			       fds[0], fds[1],
     304  			       1, 2, fds[0], fds[1], add_fd,
     305  			       (long long) tv_in.tv_sec,
     306  			       zero_extend_signed_to_ull(tv_in.tv_usec),
     307  			       fds[1], add_fd,
     308  			       (long long) tv->tv_sec,
     309  			       zero_extend_signed_to_ull(tv->tv_usec));
     310  		}
     311  
     312  		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
     313  		*l_ws = (1UL << 1) | (1UL << 2) |
     314  			(1UL << fds[0]) | (1UL << fds[1]);
     315  		*l_es = (1UL << add_fd);
     316  		tv_in.tv_sec = 0xc0de1;
     317  		tv_in.tv_usec = 0xc0de2;
     318  		memcpy(tv, &tv_in, sizeof(tv_in));
     319  		XSELECT(3, i, a_rs, a_ws, a_es, a_tv);
     320  		if (i > add_fd) {
     321  		printf("%s(%d, [%d %d], [%d %d %d %d], [%d]"
     322  		       ", {tv_sec=%lld, tv_usec=%llu}) = 3 (out [1 2 %d]"
     323  		       ", left {tv_sec=%lld, tv_usec=%llu})\n",
     324  		       TEST_SYSCALL_STR, i,
     325  		       fds[0], fds[1],
     326  		       1, 2, fds[0], fds[1], add_fd,
     327  		       (long long) tv_in.tv_sec,
     328  		       zero_extend_signed_to_ull(tv_in.tv_usec),
     329  		       fds[1],
     330  		       (long long) tv->tv_sec,
     331  		       zero_extend_signed_to_ull(tv->tv_usec));
     332  		}
     333  
     334  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     335  	}
     336  
     337  	/*
     338  	 * Now the crash case that trinity found, negative nfds
     339  	 * but with a pointer to a large chunk of valid memory.
     340  	 */
     341  	static fd_set set[0x1000000 / sizeof(fd_set)];
     342  	FD_SET(fds[1], set);
     343  	XSELECT(-1, -1U, 0, (uintptr_t) set, 0, 0);
     344  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     345  	printf("%s(-1, NULL, %p, NULL, NULL) = %s\n",
     346  	       TEST_SYSCALL_STR, set, errstr);
     347  #endif
     348  
     349  	/*
     350  	 * Big sets, nfds exceeds FD_SETSIZE limit.
     351  	 */
     352  	const size_t big_size = sizeof(fd_set) + sizeof(long);
     353  	fd_set *const big_rs = tail_alloc(big_size);
     354  	const uintptr_t a_big_rs = (uintptr_t) big_rs;
     355  
     356  	fd_set *const big_ws = tail_alloc(big_size);
     357  	const uintptr_t a_big_ws = (uintptr_t) big_ws;
     358  
     359  	for (unsigned int i = FD_SETSIZE; i <= big_size * 8; ++i) {
     360  		memset(big_rs, 0, big_size);
     361  		memset(big_ws, 0, big_size);
     362  		FD_SET(fds[0], big_rs);
     363  		tv->tv_sec = 0;
     364  		tv->tv_usec = 10 + (i - FD_SETSIZE);
     365  		XSELECT(0, i, a_big_rs, a_big_ws, 0, a_tv);
     366  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     367  		printf("%s(%d, [%d], [], NULL, {tv_sec=0, tv_usec=%d})"
     368  		       " = 0 (Timeout)\n",
     369  		       TEST_SYSCALL_STR, i, fds[0], 10 + (i - FD_SETSIZE));
     370  #else
     371  		FD_SET(fds[0], big_rs);
     372  		FD_SET(add_fd, big_rs);
     373  		tv->tv_sec = 0;
     374  		tv->tv_usec = 10 + (i - FD_SETSIZE);
     375  		XSELECT(1, i, a_big_rs, a_big_ws, 0, a_tv);
     376  		printf("%s(%d, [%d %d], [], NULL, {tv_sec=0, tv_usec=%d})"
     377  		       " = 1 (in [%d], left {tv_sec=0, tv_usec=%llu})\n",
     378  		       TEST_SYSCALL_STR, i, fds[0], add_fd,
     379  		       10 + (i - FD_SETSIZE), add_fd,
     380  		       zero_extend_signed_to_ull(tv->tv_usec));
     381  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     382  	}
     383  
     384  	/*
     385  	 * Huge sets, nfds equals to INT_MAX.
     386  	 */
     387  	FD_SET(fds[0], set);
     388  	FD_SET(fds[1], set);
     389  	tv->tv_sec = 0;
     390  	tv->tv_usec = 123;
     391  	XSELECT(0, INT_MAX, (uintptr_t) set, (uintptr_t) &set[1],
     392  		(uintptr_t) &set[2], a_tv);
     393  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     394  	printf("%s(%d, [%d %d], [], [], {tv_sec=0, tv_usec=123})"
     395  	       " = 0 (Timeout)\n",
     396  	       TEST_SYSCALL_STR, INT_MAX, fds[0], fds[1]);
     397  #else
     398  	FD_SET(fds[0], set);
     399  	FD_SET(fds[1], set);
     400  	FD_SET(add_fd, set);
     401  	tv->tv_sec = 0;
     402  	tv->tv_usec = 123;
     403  	XSELECT(1, INT_MAX, (uintptr_t) set, (uintptr_t) &set[1],
     404  		(uintptr_t) &set[2], a_tv);
     405  	printf("%s(%d, [%d %d %d], [], [], {tv_sec=0, tv_usec=123})"
     406  	       " = 1 (in [%d], left {tv_sec=0, tv_usec=%llu})\n",
     407  	       TEST_SYSCALL_STR, INT_MAX, fds[0], fds[1], add_fd,
     408  	       add_fd, zero_extend_signed_to_ull(tv->tv_usec));
     409  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     410  
     411  	/*
     412  	 * Small sets, nfds exceeds FD_SETSIZE limit.
     413  	 * The kernel seems to be fine with it but strace cannot follow.
     414  	 */
     415  	*l_rs = (1UL << fds[0]) | (1UL << fds[1])
     416  #ifdef TRACING_FD
     417  		| (1UL << TRACING_FD)
     418  #endif
     419  #ifdef PATH_TRACING_FD
     420  		| (1UL << PATH_TRACING_FD)
     421  #endif
     422  		;
     423  	*l_ws = (1UL << fds[0]);
     424  	*l_es = (1UL << fds[0]) | (1UL << fds[1])
     425  #ifdef TRACING_FD
     426  		| (1UL << TRACING_FD)
     427  #endif
     428  #ifdef PATH_TRACING_FD
     429  		| (1UL << PATH_TRACING_FD)
     430  #endif
     431  		;
     432  	tv->tv_sec = 0;
     433  	tv->tv_usec = 123;
     434  	rc = xselect(FD_SETSIZE + 1, a_rs, a_ws, a_es, a_tv);
     435  	if (rc < 0) {
     436  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     437  		printf("%s(%d, %p, %p, %p, {tv_sec=0, tv_usec=123}) = %s\n",
     438  		       TEST_SYSCALL_STR, FD_SETSIZE + 1, rs, ws, es, errstr);
     439  #endif
     440  	} else {
     441  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     442  		printf("%s(%d, %p, %p, %p, {tv_sec=0, tv_usec=123})"
     443  		       " = 0 (Timeout)\n",
     444  		       TEST_SYSCALL_STR, FD_SETSIZE + 1, rs, ws, es);
     445  #endif
     446  	}
     447  
     448  	/*
     449  	 * Small sets, one of allocated descriptors exceeds smallset_size.
     450  	 */
     451  	if (dup2(fds[1], smallset_size) != smallset_size)
     452  		perror_msg_and_fail("dup2");
     453  #ifdef TRACING_FD
     454  	FD_SET(TRACING_FD, rs);
     455  	FD_SET(TRACING_FD, ws);
     456  	FD_SET(TRACING_FD, es);
     457  #endif
     458  #ifdef PATH_TRACING_FD
     459  	FD_SET(PATH_TRACING_FD, rs);
     460  	FD_SET(PATH_TRACING_FD, ws);
     461  	FD_SET(PATH_TRACING_FD, es);
     462  #endif
     463  	XSELECT(-1, smallset_size + 1, a_rs, a_ws, a_es, 0);
     464  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     465  	printf("%s(%d, %p, %p, %p, NULL) = %s\n",
     466  	       TEST_SYSCALL_STR, smallset_size + 1, rs, ws, es, errstr);
     467  #endif
     468  
     469  	/*
     470  	 * Small and big sets,
     471  	 * one of allocated descriptors exceeds smallset_size.
     472  	 */
     473  	memset(big_rs, 0, big_size);
     474  	FD_SET(fds[0], big_rs);
     475  	FD_SET(smallset_size, big_rs);
     476  	memset(big_ws, 0, big_size);
     477  	FD_SET(fds[1], big_ws);
     478  	FD_SET(smallset_size, big_ws);
     479  	XSELECT(-1, smallset_size + 1, a_big_rs, a_big_ws, a_es, 0);
     480  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     481  	printf("%s(%d, [%d %d], [%d %d], %p, NULL) = %s\n",
     482  	       TEST_SYSCALL_STR, smallset_size + 1,
     483  	       fds[0], smallset_size,
     484  	       fds[1], smallset_size,
     485  	       es, errstr);
     486  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     487  	XSELECT(-1, smallset_size + 1, a_es, a_big_ws, a_big_rs, 0);
     488  #if !defined(PATH_TRACING_FD) && !defined(TRACING_FD)
     489  	printf("%s(%d, %p, [%d %d], [%d %d], NULL) = %s\n",
     490  	       TEST_SYSCALL_STR, smallset_size + 1,
     491  	       es,
     492  	       fds[1], smallset_size,
     493  	       fds[0], smallset_size,
     494  	       errstr);
     495  #endif /* !PATH_TRACING_FD && !TRACING_FD */
     496  
     497  	puts("+++ exited with 0 +++");
     498  	return 0;
     499  }