comp.lang.ada
 help / color / mirror / Atom feed
From: Florian Weimer <fw@deneb.enyo.de>
Subject: A hole in Ada type safety
Date: Sat, 30 Apr 2011 10:41:17 +0200
Date: 2011-04-30T10:41:17+02:00	[thread overview]
Message-ID: <87oc3odtci.fsf@mid.deneb.enyo.de> (raw)

I don't know if this is a new observation---I couldn't find
documentation for it.  I plan to incorporate feedback into
<http://www.enyo.de/fw/notes/ada-type-safety.html>.

The standard way to show that type safety has been broken in a
language is to implement a cast function Conversion from any type
Source to any type Target:

    generic
       type Source is private;
       type Target is private;
    function Conversion (S : Source) return Target;

This generic function can be used like Ada.Unchecked_Conversion:

    with Ada.Text_IO;
    with Ada.Unchecked_Conversion;

    with Conversion;

    procedure Convert_Test is
       type Integer_Access is access all Integer;
       
       J : aliased Integer;
       J_Access : Integer_Access := J'Access;
       
       function Convert is new Conversion (Integer_Access, Integer);
       function Unchecked_Convert is new Ada.Unchecked_Conversion
         (Integer_Access, Integer);
       
    begin
       Ada.Text_IO.Put_Line (Integer'Image (Convert (J_Access)));
       Ada.Text_IO.Put_Line (Integer'Image (Unchecked_Convert (J_Access)));
    end Convert_Test;

How can we implement Conversion? It turns out that discriminant
records with defaults combined with aliasing do the trick:

    function Conversion (S : Source) return Target is
       type Source_Wrapper is tagged record
          S : Source;
       end record;
       type Target_Wrapper is tagged record
          T : Target;
       end record;
       
       type Selector is (Source_Field, Target_Field);
       type Magic (Sel : Selector := Target_Field) is record
          case Sel is
    	 when Source_Field =>
    	    S : Source_Wrapper;
    	 when Target_Field =>
    	    T : Target_Wrapper;
          end case;
       end record;
       
       M : Magic;
       
       function Convert (T : Target_Wrapper) return Target is
       begin
          M := (Sel => Source_Field, S => (S => S));
          return T.T;
       end Convert;
       
    begin
       return Convert (M.T);
    end Conversion;

When the inner function Convert is called, the discriminant Sel of M
has the value Target_Field, thus the component M.T can be
dereferenced. The assignment statement in Convert changes the
discriminant and the value. But the source value S is still reachable
as an object of type Target because the parameter T aliases the
component M.T, so the return statement executes without raising an
exception.

The two tagged records are used to force that the inner Convert
function receives its parameter by reference. Without them, an
implementation would be free to pass the discriminant record Magic by
copy, and aliasing would not occur.

Our implementation lacks the full power of Ada.Unchecked_Conversion
because it does not supported limited or unconstrained types. However,
it is sufficient to break type safety.



             reply	other threads:[~2011-04-30  8:41 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-30  8:41 Florian Weimer [this message]
2011-04-30 11:56 ` A hole in Ada type safety Robert A Duff
2011-04-30 15:27   ` Gavino
2011-04-30 16:16   ` Florian Weimer
2011-04-30 23:39     ` Randy Brukardt
2011-05-01 10:26       ` Florian Weimer
2011-05-03  1:40         ` Randy Brukardt
2011-05-03 16:57           ` Robert A Duff
2011-05-07  9:09           ` Florian Weimer
2011-05-07  9:28             ` Dmitry A. Kazakov
2011-05-07  9:57               ` Florian Weimer
2011-05-08  8:08                 ` Dmitry A. Kazakov
2011-05-08  8:46                   ` Florian Weimer
2011-05-08  9:32                     ` Dmitry A. Kazakov
2011-05-08 10:30                       ` Florian Weimer
2011-05-08 20:24                         ` anon
2011-05-08 21:11                           ` Simon Wright
2011-05-10  6:27                             ` anon
2011-05-10 14:39                               ` Adam Beneschan
2011-05-11 20:39                                 ` anon
2011-05-12  0:51                                   ` Randy Brukardt
2011-05-13  0:47                                     ` anon
2011-05-13  0:58                                       ` Adam Beneschan
2011-05-13  5:31                                       ` AdaMagica
2011-05-12  5:51                                   ` AdaMagica
2011-05-12 12:09                                     ` Robert A Duff
2011-05-12 14:40                                     ` Adam Beneschan
2011-05-14  0:30                                       ` Randy Brukardt
2011-05-09  7:48                         ` Dmitry A. Kazakov
2011-05-09 20:41             ` Randy Brukardt
2011-05-14 23:47     ` anon
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox