strace seg with select and -ve nfds

Denys Vlasenko dvlasenk at redhat.com
Wed Nov 6 10:34:53 UTC 2013


On 11/06/2013 01:06 AM, Dmitry V. Levin wrote:
> On Tue, Nov 05, 2013 at 04:19:31PM +0100, Denys Vlasenko wrote:
>> On 11/05/2013 01:33 PM, Dr. David Alan Gilbert wrote:
>> There can be legitimate programs which use select() in excess of glibc-imposed
>> artificial limit on bit array sizes.
> 
> Yes, the syscall itself imposes no such limitations.
> Such programs are more expected to use poll() instead of select(), though.
> 
>>> (I guess you could argue that's a false positive from fortify, but there
>>> again I think it is an illegal use of FD_ISSET).
>>
>> Do you see a reasonably portable way to check FD_ISSET?
> 
> Looks like all FD_ISSET implementations just test the n-th bit in the
> array of long ints.  I've pushed a commit with yet another FD_ISSET
> implementation that hopefully does the same.

static int
fd_isset(int d, fd_set *fds)
{
        const int bpl = 8 * sizeof(long);
        long *s = (long *) fds;
        return !!(s[d / bpl] & (1L << (d % bpl)));
}

The function is executed *for each bit*.

With gcc -Os at least, this will execute a signed division
because gcc must ensure "d / bpl" has a correct value for
negative d too - it does not know that we never use negative d.

   0:   89 f9                   mov    %edi,%ecx
   2:   bf 40 00 00 00          mov    $0x40,%edi
   7:   89 c8                   mov    %ecx,%eax
   9:   99                      cltd
   a:   f7 ff                   idiv   %edi      <============
   c:   89 d1                   mov    %edx,%ecx
   e:   48 63 d0                movslq %eax,%rdx
  11:   48 8b 04 d6             mov    (%rsi,%rdx,8),%rax
  15:   48 d3 f8                sar    %cl,%rax
  18:   83 e0 01                and    $0x1,%eax
  1b:   c3                      retq

Making bpl "unsigned":

   0:   89 f8                   mov    %edi,%eax
   2:   89 f9                   mov    %edi,%ecx
   4:   c1 e8 06                shr    $0x6,%eax
   7:   83 e1 3f                and    $0x3f,%ecx
   a:   89 c0                   mov    %eax,%eax  <==== stupid gcc??
   c:   48 8b 04 c6             mov    (%rsi,%rax,8),%rax
  10:   48 d3 f8                sar    %cl,%rax
  13:   83 e0 01                and    $0x1,%eax
  16:   c3                      retq

Inlining fd_isset eliminates call overhead at the cost of only 2 bytes:

# size desc.o  desc.o.inlined
   text	   data	    bss	    dec	    hex	filename
   5101	      0	   1024	   6125	   17ed	desc.o
   5103	      0	   1024	   6127	   17ef	desc.o.inlined

I committed a change to implement these.





More information about the Strace-devel mailing list