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.
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to