Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2013-03

Improper OUT usage.

11 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marco van de Voort

I was debugging a problem in the generation of FCL documentation (CHM format) with fpdoc (trunk), and found an interesting behaviour worth of sharing;

The location of the exception didn't seem to give much info, so I hoped to force problems to lead to early fails by recompiling with -CRriot and -gttt, but this (I assume the -gttt) lead to the following:

the first problem is that fcl-passrc likes to use OUT for all kinds of parameters, probably to silence some warnings.

BUT at the same time doesn't assign a value to it in all codepaths (in this case the visibility checking methods). At the same time, it passes global or fields with state variables(enums, curvisibility in this case) to the OUT parameters.

The result is that -gttt randomizes the OUT parameters on entry, the parameters are never changed in some codepaths, and in those cases the global state variable becomes corrupt, leading to all kinds of interesting behaviour. (like undocumented InOutError 107, which I assume is a relatively new RTE for printing out of range enums)

I changed the out parameters to VAR and the problem disappeared.

So be careful if you use OUT with types that have range limitations. Not setting the out parameter can make debug tools like gttt difficult.

Reply by email

Vincent Snijders
to Marco van de Voort

2013/3/9 Marco van de Voort :

Show quoted text 20 lines
the first problem is that fcl-passrc likes to use OUT for all kinds of parameters, probably to silence some warnings. BUT at the same time doesn't assign a value to it in all codepaths (in this case the visibility checking methods). At the same time, it passes global or fields with state variables(enums, curvisibility in this case) to the OUT parameters. The result is that -gttt randomizes the OUT parameters on entry, the parameters are never changed in some codepaths, and in those cases the global state variable becomes corrupt, leading to all kinds of interesting behaviour. (like undocumented InOutError 107, which I assume is a relatively new RTE for printing out of range enums) I changed the out parameters to VAR and the problem disappeared. So be careful if you use OUT with types that have range limitations. Not setting the out parameter can make debug tools like gttt difficult.

You found a big in fcp-passrc, because if you have an out parameter, then the callee has to output a valid variable. If it asumes that is initialized when called, then it must use var instead.

Vincent

Reply by email

Marco van de Voort
to Vincent Snijders

In our previous episode, Vincent Snijders said:

Show quoted text 7 lines
> So be careful if you use OUT with types that have range limitations. Not > setting the out parameter can make debug tools like gttt difficult. > You found a big in fcp-passrc, because if you have an out parameter, then the callee has to output a valid variable. If it asumes that is initialized when called, then it must use var instead.

I already had changed it to var in r23760. I did want to warn for the bug's pattern, so I wrote this to the ml.

Reply by email

Flávio Etrusco
to Marco van de Voort
Marco van de Voort wrote 12 lines
In our previous episode, Vincent Snijders said: > > So be careful if you use OUT with types that have range limitations. Not > > setting the out parameter can make debug tools like gttt difficult. > > > > You found a big in fcp-passrc, because if you have an out parameter, > then the callee has to output a valid variable. If it asumes that is > initialized when called, then it must use var instead. I already had changed it to var in r23760. I did want to warn for the bug's pattern, so I wrote this to the ml.

I'd really like the compiler would stop with an error if it can't prove a variable/out/result is initialized.
Did anybody try implementing this in FPC?

-Flávio

Reply by email

Sven Barth
to Flávio Etrusco
Flávio Etrusco wrote 17 lines
On Sun, Mar 10, 2013 at 11:56 AM, Marco van de Voort wrote: > In our previous episode, Vincent Snijders said: >>> So be careful if you use OUT with types that have range limitations. Not >>> setting the out parameter can make debug tools like gttt difficult. >>> >> >> You found a big in fcp-passrc, because if you have an out parameter, >> then the callee has to output a valid variable. If it asumes that is >> initialized when called, then it must use var instead. > > I already had changed it to var in r23760. I did want to warn for the > bug's pattern, so I wrote this to the ml. > I'd really like the compiler would stop with an error if it can't prove a variable/out/result is initialized. Did anybody try implementing this in FPC?

Have fun fixing the errors then:

=== example begin ===

type
   TTest = record
     t: LongInt;
   end;
var
   t: TTest;
begin
   FillChar(t, SizeOf(t), 0);
end;

=== example end ===

The above code will have the hint that "t" is not initalized.

Regards,
Sven

Reply by email

Flávio Etrusco
to Sven Barth
Sven Barth wrote 27 lines
On 10.03.2013 20:39, Flávio Etrusco wrote: > > I'd really like the compiler would stop with an error if it can't > prove a variable/out/result is initialized. > Did anybody try implementing this in FPC? Have fun fixing the errors then: === example begin === type TTest = record t: LongInt; end; var t: TTest; begin FillChar(t, SizeOf(t), 0); end; === example end === The above code will have the hint that "t" is not initalized. Regards, Sven

t.t := 0; // ;-)
This reminds me that a magic compiler procedure to zero-fill records without the sizeof parameter (and without the hint) has always been on my wishlist :-) (now I'll have to dig the message where sb explained why FillChar couldn't be declared with 'out' - IIRC something regarding interfaces)

Best regards,
Flávio

Reply by email

Sven Barth
to Flávio Etrusco
"Flávio Etrusco" wrote
On Sun, Mar 10, 2013 at 6:08 PM, Sven Barth
Show quoted text 29 lines
> On 10.03.2013 20:39, Flávio Etrusco wrote: >> >> I'd really like the compiler would stop with an error if it can't >> prove a variable/out/result is initialized. >> Did anybody try implementing this in FPC? > > > Have fun fixing the errors then: > > === example begin === > > type > TTest = record > t: LongInt; > end; > var > t: TTest; > begin > FillChar(t, SizeOf(t), 0); > end; > > === example end === > > The above code will have the hint that "t" is not initalized. > > Regards, > Sven t.t := 0; // ;-)

I don't consider this a nice solution...

Show quoted text 5 lines
This reminds me that a magic compiler procedure to zero-fill records without the sizeof parameter (and without the hint) has always been on my wishlist :-) (now I'll have to dig the message where sb explained why FillChar couldn't be declared with 'out' - IIRC something regarding interfaces)

In 2.7.1 (implemented for around three quarter of a year):

=== example begin ===

t := Default(TTest);

=== example end ===

Regards,
Sven

Reply by email

Jonas Maebe
to Sven Barth: Have fun fixing the errors then: === example begin === type TTest = record t: LongInt;…
Sven Barth wrote 6 lines
On 10.03.2013 20:39, Flávio Etrusco wrote: > I'd really like the compiler would stop with an error if it can't > prove a variable/out/result is initialized. > Did anybody try implementing this in FPC? Have fun fixing the errors then:

I thought he meant inside the routine with the out-parameter, i.e. add a similar check for out-parameters as for function results. On the caller side it doesn't matter whether or not the out-parameter is already initialized.

Jonas

Reply by email

Hans-Peter Diettrich
to Jonas Maebe
Show quoted text 9 lines
On 10 Mar 2013, at 22:08, Sven Barth wrote: > On 10.03.2013 20:39, Flávio Etrusco wrote: >> I'd really like the compiler would stop with an error if it can't >> prove a variable/out/result is initialized. >> Did anybody try implementing this in FPC? > Have fun fixing the errors then: I thought he meant inside the routine with the out-parameter, i.e. add a similar check for out-parameters as for function results. On the caller side it doesn't matter whether or not the out-parameter is already initialized.

IMO Out and Var parameters differ only in the handling of the "possibly missing initialization" warning. For Var parameters the check is made in caller code, for Out parameters in the called subroutine.

DoDi

Reply by email

Flávio Etrusco
to Sven Barth: I don't consider this a nice solution... In 2.7.1 (implemented for around three quarter…
Sven Barth wrote 23 lines
Am 11.03.2013 02:31 schrieb "Flávio Etrusco" : > On Sun, Mar 10, 2013 at 6:08 PM, Sven Barth > wrote: > > (...) > > TTest = record > > t: LongInt; > > end; > > var > > t: TTest; > > begin > > FillChar(t, SizeOf(t), 0); > > end; > > (...) > > > > The above code will have the hint that "t" is not initalized. > > > > Regards, > > Sven > > t.t := 0; // ;-) I don't consider this a nice solution...

I don't either ;-)
Of course the check would need a switch, I don't intend to change the whole Pascal code base...
My post was indeed about getting some more persperctive about the roadblockers - WRT both application and implementation - but I decide it was too big and "cleaned" a bit too much :-$

Show quoted text 16 lines
> This reminds me that a magic compiler procedure to zero-fill records > without the sizeof parameter (and without the hint) has always been on > my wishlist :-) (now I'll have to dig the message where sb explained > why FillChar couldn't be declared with 'out' - IIRC something > regarding interfaces) In 2.7.1 (implemented for around three quarter of a year): === example begin === t := Default(TTest); === example end === Regards, Sven

Great! Almost fantastic :-)
Looking forward for the 2.8 release.

Best regards,
Flávio

Reply by email

Flávio Etrusco
to Jonas Maebe: I thought he meant inside the routine with the out-parameter, i.e. add a similar check…
Jonas Maebe wrote 13 lines
On 10 Mar 2013, at 22:08, Sven Barth wrote: > On 10.03.2013 20:39, Flávio Etrusco wrote: >> I'd really like the compiler would stop with an error if it can't >> prove a variable/out/result is initialized. >> Did anybody try implementing this in FPC? > > Have fun fixing the errors then: I thought he meant inside the routine with the out-parameter, i.e. add a similar check for out-parameters as for function results. On the caller side it doesn't matter whether or not the out-parameter is already initialized. Jonas

Yes, I meant this. And for a second I too thought "where is the out param here?", but he's talking about the (local) variable case, which I also mentioned. Because 'FillChar' (and quite some other frequently used functions I AFAIR) receives a 'var' instead of 'out' I can't use it.

I will only dare asking one more thing for now: FPC's employment of SSA means having a similar level of checking as in Java (check branches, for scalar values) is "doable", right?

Best regards,
Flávio

Reply by email