[fpc-devel] overflow error in Fpopendir
Seth Grover
sethdgrover at gmail.com
Thu Jun 30 20:00:38 CEST 2016
I am debugging an issue with FPC 3.0 on Linux x86_64 which I believe I have
tracked down to Fpopendir rtl/linux/ossysc.inc:
-----------------------------------------------------------
function Fpopendir(dirname : pchar): pdir; [public, alias :
'FPC_SYSC_OPENDIR'];
var
fd:integer;
st:stat;
ptr:pdir;
begin
Fpopendir:=nil;
if Fpstat(dirname,st)<0 then
exit;
{ Is it a dir ? }
if not((st.st_mode and $f000)=$4000)then
begin
errno:=ESysENOTDIR;
exit
end;
{ Open it}
fd:=Fpopen(dirname,O_RDONLY,438);
if fd<0 then
exit;
new(ptr);
if ptr=nil then
exit;
new(ptr^.dd_buf);
if ptr^.dd_buf=nil then
exit;
ptr^.dd_fd:=fd;
ptr^.dd_loc:=0;
ptr^.dd_size:=0;
ptr^.dd_nextoff:=0;
ptr^.dd_max:=sizeof(ptr^.dd_buf^);
Fpopendir:=ptr;
end;
-----------------------------------------------------------
In this process I have a LOT of open file handles. The system on which it
runs uses "ulimit -n 64000" to set the maximum number of open descriptors
to 64,000. However, once I get above 32768 file handles Fpopendir starts
failing, and causing me to leak directory descriptors. I didn't have debug
compiled down into the RTL, but looking at the machine code I can see
what's happening:
Fpopen is returning a good directory descriptor, for example, 51345.
However, the comparison "fd<0" is evaluating to true, which causes the
routine to error out.
Looking at the machine code:
0x00007ffff7038106 <+118>: callq 0x7ffff7037ee0
<SYSTEM_$$_FPOPEN$PCHAR$LONGINT$LONGINT$$LONGINT>
0x00007ffff703810b <+123>: mov %eax,%ebx
0x00007ffff703810d <+125>: cmp $0x0,%bx
0x00007ffff7038112 <+130>: jl 0x7ffff703816b
<SYSTEM_$$_FPOPENDIR$PCHAR$$PDIR+219>
At +123 I can see that $eax/$ebx contains the correct descriptor, 51345.
However, when I print $bx in the debugger, it looks like a negative number,
as if it had overflowed a signed 2-byte integer, so the function errors
out. This causes the file descriptor to be leaked as well, since no
reference to is is retained in the pdir record.
I'm a little bit confused at this, as fd is defined as an "integer," which
I thought was going to always be a 32-bit signed value on this system.
However, the FPC documentation tells me that this can be changed based on
compiler switches, so maybe somewhere up in one of the other .inc files
there is some flag making "integer" behave as a signed 16-byte number?
I am inclined just to patch my copy of the FPC rtl and change the
definition of fd from "integer" to "longint," but I wanted to get your take
on it first.
Thanks,
SG
--
Seth Grover
Be kind to all of your neighbors
Because they're just like you.
And you're nothing special
Unless they are too.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20160630/a58c8c13/attachment.html>
More information about the fpc-devel
mailing list