[fpc-pascal] FPC 2.6.2 throws SEGV in fpc_AnsiStr_Decr_Ref(). How is this possible?

Ludo Brands ludo.brands at free.fr
Thu May 9 08:21:18 CEST 2013


On 05/09/2013 05:19 AM, Bruce Tulloch wrote:
> 
> This tells me that the test at the top of fpc_AnsiStr_Decr_Ref:
> 
>         cmpl $0,(%eax)
>         jne .Ldecr_ref_continue
>         ret
> .Ldecr_ref_continue:
> 
> passed (i.e. (%eax) was NOT nil) but sometime during the execution of
> the following code:
> 
> // Temps allocated between ebp-24 and ebp+0
>         subl    $4,%esp
> // Var S located in register
> // Var l located in register
>         movl    %eax,(%esp)
> // [101] l:=@PAnsiRec <mailto:=@PAnsiRec>(S-FirstOff)^.Ref;
>         movl    (%eax),%edx
>         subl    $8,%edx
> // [102] If l^<0 then exit;
>         cmpl    $0,(%edx)
> 
> the variable (%eax) MUST have been changed (to nil) BY ANOTHER THREAD.
>
> Is there any other plausible explanation I may have missed?
>

SIGSEGV is caused by an access to any memory outside the process address
space. Not only nil. So the first test only checks if the address is not
nil but will let other, even invalid, addresses pass on.


> If there is no other explanation, then it means I need to find out how
> the string variable referred to by (%eax) could have been been accessed
> (or even known to exist) by any other thread in the same address space.
> 
> If that variable is local to a function (i.e. foo's Result with SEGV
> upon its assignment immediately it first comes into scope, per my
> earlier email) then absent a bug in FPC's handling string references and
> allocation, it seems impossible that it could be known or referenced by
> any other other thread.
> 
> I'm reasonably confident there's no other way it could be overwritten by
> another thread (i.e. I don't think there are any range or buffer pointer
> errors anywhere else) so logic tells me I must have the wrong thesis or
> there's a string handling error in FPC.
> 
> Any clues or insight, gratefully received :-)
> 

Result in foo is initialized with the address of the left side variable
in the call to foo. If you have
  s:=foo;
result will point to s. If you just call
  foo;
and drop the result, the compiler will create and use a hidden temp
string variable. Strings are managed types and initialized to nil.

So you are looking at the wrong location for your bug. You should look
at what has corrupted the string variable that receives the result of foo.

Ludo



More information about the fpc-pascal mailing list