[fpc-devel] Dangerous optimization in CASE..OF
Michael Van Canneyt
michael at freepascal.org
Sun Jul 2 10:40:44 CEST 2017
On Sun, 2 Jul 2017, Martok wrote:
> Hi all,
>
>> The only way to get data with an invalid value in an enum in Pascal is by
>> using an unchecked (aka explicit) typecast, by executing code without range
>> checking (assigning an enum from a larger parent enum type into a smaller
>> sub-enum type), or by having an uninitialised variable.
>
> Turns out this is really not true. There are also as "esoteric" things as using
> Read(File). Or TStream.Read. Or the socket implementation of your choice. Or by
> calling a library function. There are many ways to have an invalid value in an
> enum in any meaningful code. Pretty much everything that is not a direct
> assignment from a constant is a potential candidate.
These cases are without exception covered by the " unchecked (aka explicit) typecast,"
part of Jonas's statement. Including Read(File).
If you use Read(File) you are implicitly telling the compiler that the file
only contains valid values for the enum. If you yourself are not sure of this,
you must use file of integer instead.
If you check their definitions, you will see that they all use untyped
buffers to do their work. So all 'type safety' bets are off as soon as
you use one of these mechanisms. This is not only true of enums, but for
every data type.
The correct pascal way is to do
var
I : integer;
M : MyEnum;
begin
MyStream.ReadBuffer(I,SizeOf(I));
if (I>=Ord(Low(TMyEnum))) and (I<=Ord(High(TMyEnum))) then
M:=TMyEnum(I)
else
// error
end
Instead of
MyStream.ReadBuffer(M,SizeOf(M));
Which is inherently not safe, as it uses an untyped buffer.
In essence:
you are on your own as soon as you use external sources of values for enums.
Michael.
More information about the fpc-devel
mailing list