comp.lang.ada
 help / color / mirror / Atom feed
* A hole in Ada type safety
@ 2011-04-30  8:41 Florian Weimer
  2011-04-30 11:56 ` Robert A Duff
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2011-04-30  8:41 UTC (permalink / 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.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-04-30  8:41 A hole in Ada type safety Florian Weimer
@ 2011-04-30 11:56 ` Robert A Duff
  2011-04-30 15:27   ` Gavino
  2011-04-30 16:16   ` Florian Weimer
  0 siblings, 2 replies; 31+ messages in thread
From: Robert A Duff @ 2011-04-30 11:56 UTC (permalink / raw)


Florian Weimer <fw@deneb.enyo.de> writes:

> I don't know if this is a new observation---I couldn't find
> documentation for it.

It's not new.  It is documented in AARM-3.7.2(4,4.a),
which dates back to Ada 83 days.

> 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.

Well, the program exhibits erroneous (i.e. unpredictable) behavior,
so anything could happen.  The above description is likely to happen.

> 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.

Yes.  Anything that is erroneous necessarily breaks type safety.
If you look up "erroneous execution" in the index, you'll find
them all.

Your comment, "This note shows that a combination of safe-looking
language features can be used to undermine type safety, too."
is the key point.  It is indeed unfortunate when "safe-looking"
features can be erroneous.

- Bob



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-04-30 11:56 ` Robert A Duff
@ 2011-04-30 15:27   ` Gavino
  2011-04-30 16:16   ` Florian Weimer
  1 sibling, 0 replies; 31+ messages in thread
From: Gavino @ 2011-04-30 15:27 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccoc3oq7ev.fsf@shell01.TheWorld.com...
> It is indeed unfortunate when "safe-looking"
> features can be erroneous.

Hence the need for something like SPARK.





^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-04-30 11:56 ` 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-14 23:47     ` anon
  1 sibling, 2 replies; 31+ messages in thread
From: Florian Weimer @ 2011-04-30 16:16 UTC (permalink / raw)


* Robert A. Duff:

> Florian Weimer <fw@deneb.enyo.de> writes:
>
>> I don't know if this is a new observation---I couldn't find
>> documentation for it.
>
> It's not new.  It is documented in AARM-3.7.2(4,4.a),
> which dates back to Ada 83 days.

Ah.  I didn't realize that call to Convert was already erroneous.

It does not seem possible to extend the restrictions on 'Access
prefixes to to subprogram parameters (due to the way controlled types
are implemented, for example).

>> 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.
>
> Yes.  Anything that is erroneous necessarily breaks type safety.
> If you look up "erroneous execution" in the index, you'll find
> them all.

My concern was that this was not explicitly labeled as erroneous. 8-)

> Your comment, "This note shows that a combination of safe-looking
> language features can be used to undermine type safety, too."
> is the key point.  It is indeed unfortunate when "safe-looking"
> features can be erroneous.

And once there is something like this in the language, it is difficult
to decide if a new addition (such as aliased parameters) make things
worse or not.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-04-30 16:16   ` Florian Weimer
@ 2011-04-30 23:39     ` Randy Brukardt
  2011-05-01 10:26       ` Florian Weimer
  2011-05-14 23:47     ` anon
  1 sibling, 1 reply; 31+ messages in thread
From: Randy Brukardt @ 2011-04-30 23:39 UTC (permalink / raw)


"Florian Weimer" <fw@deneb.enyo.de> wrote in message 
news:87tydfbtp3.fsf@mid.deneb.enyo.de...
...
> And once there is something like this in the language, it is difficult
> to decide if a new addition (such as aliased parameters) make things
> worse or not.

Not sure how something that adds new capabilities only for elementary types 
could make anything worse.

We also ran across this particular erroneousness in another case; we decided 
that we had to let subprograms trust their constraints (which introduces 
some additional erroneousness) as the alternative requires a lot of 
additional code for discriminanted parameters. (I forget where the wording 
change for that ended up.)

Cases like this is why I like to say that all real Ada programs are 
erroneous, so any result is allowed. :-) If you could write an entire 
program in SPARK, that could make that statement a falsehood, but the Ada 
runtime is most likely erroneous for some reason (interfacing to C tends to 
end up erroneous in some cases, for instance). You'd probably need a SPARK 
runtime on top of a SPARK OS in order to make a non-erroneous program a 
reality.

                              Randy.





^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-04-30 23:39     ` Randy Brukardt
@ 2011-05-01 10:26       ` Florian Weimer
  2011-05-03  1:40         ` Randy Brukardt
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2011-05-01 10:26 UTC (permalink / raw)


* Randy Brukardt:

> "Florian Weimer" <fw@deneb.enyo.de> wrote in message 
> news:87tydfbtp3.fsf@mid.deneb.enyo.de...
> ...
>> And once there is something like this in the language, it is difficult
>> to decide if a new addition (such as aliased parameters) make things
>> worse or not.
>
> Not sure how something that adds new capabilities only for
> elementary types could make anything worse.

It introduces a new form of aliasing.  This will be problematic, I
fear.  In particular, extreme care is necessary so that the cop-out in
3.7.2(4) is still the only one which is needed.  With this rule (I
don't know if this is the current text):

| If the formal parameter is an explicitly aliased parameter, the type
| of the actual parameter shall be tagged or the actual parameter
| shall be an aliased view of an object.

it is possible to obtain an aliased view of a discriminant-dependent
record component of tagged type which is not delimited by a subprogram
call.

This would allow to write the Conversion function like this:

   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 : aliased Target_Wrapper) 
        return access constant Target
      is
      begin
         return T.T'Access;
      end Convert;
      
      T : Target renames Convert (M.T).all;
      
   begin
      M := (Sel => Source_Field, S => (S => S));
      return T;
   end Conversion;

(I haven't checked with an Ada 2012 compiler, so this is somewhat
speculative.)

It seems to me that you need a C++-like rule that accessing an object
through a view which is not compatible with its dynamic type is
erroneous.  And this would be quite a defeat.

The difficulty I alluded lies in the answer to this question: Are
aliased parameters at fault, or are discriminants with defaults to
blame?

> Cases like this is why I like to say that all real Ada programs are 
> erroneous, so any result is allowed. :-)

It's a bit disappointing because all those nitty-gritty rules intended
to ensure type safety which make the language quite complicated, and
there's still such a hole.  It's certainly at odds with the marketing
materials.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  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
  0 siblings, 2 replies; 31+ messages in thread
From: Randy Brukardt @ 2011-05-03  1:40 UTC (permalink / raw)


"Florian Weimer" <fw@deneb.enyo.de> wrote in message 
news:87d3k2u36e.fsf@mid.deneb.enyo.de...
>* Randy Brukardt:
>> "Florian Weimer" <fw@deneb.enyo.de> wrote in message
>> news:87tydfbtp3.fsf@mid.deneb.enyo.de...
>> ...
>>> And once there is something like this in the language, it is difficult
>>> to decide if a new addition (such as aliased parameters) make things
>>> worse or not.
>>
>> Not sure how something that adds new capabilities only for
>> elementary types could make anything worse.
>
> It introduces a new form of aliasing.  This will be problematic, I
> fear.  In particular, extreme care is necessary so that the cop-out in
> 3.7.2(4) is still the only one which is needed.  With this rule (I
> don't know if this is the current text):
>
> | If the formal parameter is an explicitly aliased parameter, the type
> | of the actual parameter shall be tagged or the actual parameter
> | shall be an aliased view of an object.
>
> it is possible to obtain an aliased view of a discriminant-dependent
> record component of tagged type which is not delimited by a subprogram
> call.

But this is not a new capability. All tagged type parameters are implicitly 
aliased already in Ada (Ada 95 specifically), so there is nothing new being 
added here. (And in all honesty, all tagged objects should be implicitly 
aliased; it is a mistake to require that declaration on tagged types.)

> This would allow to write the Conversion function like this:
>
>   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 : aliased Target_Wrapper)
>        return access constant Target
>      is
>      begin
>         return T.T'Access;
>      end Convert;
>
>      T : Target renames Convert (M.T).all;
>
>   begin
>      M := (Sel => Source_Field, S => (S => S));
>      return T;
>   end Conversion;
>
> (I haven't checked with an Ada 2012 compiler, so this is somewhat
> speculative.)

Actually, I think T.T'Access is illegal, because the component T is not 
declared as aliased. You can take 'Access of the parameter T, but not of 
some random component (as is currently the case in Ada).

You could probably do it by adding an additional level of subprogram calls 
(that is, by passing T.T to another function that returns the access value). 
But I think you can already do that in Ada 95 (perhaps you would have to use 
'Unchecked_Access there).

But this looks like an attempt to shot yourself in the foot; it's hardly 
likely to happen by accident. Remember that no programming language can 
really defend against malicious programmers; the point is to defend against 
sloppy or careless programmers [which is all of us, sooner or later].

For instance, the tampering checks of the Ada containers implicit in the new 
Reference routines can be defeated by the use of Unchecked_Deallocation on 
the return object. But this is not something that is reasonably going to 
happen by accident, and it is out in the open for program reviewers (both 
tools and humans) to find. It's not worth worrying about.

> It seems to me that you need a C++-like rule that accessing an object
> through a view which is not compatible with its dynamic type is
> erroneous.  And this would be quite a defeat.

But that's exactly what 3.7.2(4) is. And it has been in Ada since the 
beginning.

It's not a real problem in practice because the use of constrained 
discriminated types is pretty rare.

Also note that a lot of renaming and 'Access of discriminant-dependent 
components is not allowed; we've tighened those rules with each version of 
Ada.

> The difficulty I alluded lies in the answer to this question: Are
> aliased parameters at fault, or are discriminants with defaults to
> blame?

Almost certainly discriminants with defaults, since the problem has existed 
in Ada since Ada 83, and we are not making it any worse (that would be 
impossible, IMHO).

>> Cases like this is why I like to say that all real Ada programs are
>> erroneous, so any result is allowed. :-)
>
> It's a bit disappointing because all those nitty-gritty rules intended
> to ensure type safety which make the language quite complicated, and
> there's still such a hole.  It's certainly at odds with the marketing
> materials.

Type safety is not about detering malicious programmers, merely careless 
ones. And what you are doing is clearly malicious, since its intent is to 
hide an Unchecked_Conversion operation in some other, far more complex form. 
Unless this is likely to happen by accident (and it is not), there isn't 
really a problem.

We actually considered repealing that 3.7.2(4) for Ada 2012, but decided not 
to simply because it would be very hard on programmers (you could never 
trust a composite constraint). Programmers *want* to trust constraints, even 
though they aren't anywhere near as meaningful as most think. (We had a 
replay of this with the predicate feature; there we decided to separate the 
"meaningful" ones from the other kind.)

                                  Randy.







^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-03  1:40         ` Randy Brukardt
@ 2011-05-03 16:57           ` Robert A Duff
  2011-05-07  9:09           ` Florian Weimer
  1 sibling, 0 replies; 31+ messages in thread
From: Robert A Duff @ 2011-05-03 16:57 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> It's not a real problem in practice because the use of constrained 
> discriminated types is pretty rare.

And passing an actual parameter to a procedure that can see that actual
as a global is also pretty rare.

- Bob



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  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-09 20:41             ` Randy Brukardt
  1 sibling, 2 replies; 31+ messages in thread
From: Florian Weimer @ 2011-05-07  9:09 UTC (permalink / raw)


* Randy Brukardt:

> Actually, I think T.T'Access is illegal, because the component T is not 
> declared as aliased. You can take 'Access of the parameter T, but not of 
> some random component (as is currently the case in Ada).

Wouldn't it work if the component T was aliased?

> But this looks like an attempt to shot yourself in the foot; it's hardly 
> likely to happen by accident. Remember that no programming language can 
> really defend against malicious programmers; the point is to defend against 
> sloppy or careless programmers [which is all of us, sooner or later].

My first answer that was rather confrontational.  Let me just say that
this is the line of argument used by C advocates.

> For instance, the tampering checks of the Ada containers implicit in
> the new Reference routines can be defeated by the use of
> Unchecked_Deallocation on the return object. But this is not
> something that is reasonably going to happen by accident, and it is
> out in the open for program reviewers (both tools and humans) to
> find. It's not worth worrying about.

It's true that use-after-free errors typically result in exactly the
same type safety violation.  But they seem to be rather hard to spot
in COTS software, and I'm not sure that the programming languages are
to blame.  Manual memory management is just hard.

>> It seems to me that you need a C++-like rule that accessing an object
>> through a view which is not compatible with its dynamic type is
>> erroneous.  And this would be quite a defeat.
>
> But that's exactly what 3.7.2(4) is. And it has been in Ada since the 
> beginning.

3.7.2(4) has very precise syntact requirements ("a name denoting a
subcomponent that depends on discriminants" etc.).  I don't think it
covers the new possibilities introduced by aliased parameters.

> Also note that a lot of renaming and 'Access of discriminant-dependent 
> components is not allowed; we've tighened those rules with each version of 
> Ada.

It's not clear to me if these rules are valuable when its easy to
circumvent them.  They mostly seem to increase the complexity of the
language.

>> The difficulty I alluded lies in the answer to this question: Are
>> aliased parameters at fault, or are discriminants with defaults to
>> blame?
>
> Almost certainly discriminants with defaults, since the problem has
> existed in Ada since Ada 83, and we are not making it any worse
> (that would be impossible, IMHO).

I tend to agree.  Would it make sense to deprecate discriminants with
defaults?  As a replacement, smart pointers could be added to the
language, with syntactical overhead compared to access types, which
would allow programmers to replace discriminants with default with a
smart pointer to an unconstrained type.  Implementations would be
allowed to use reference counting, or full garbage collection.
However, they would have to ensure that references to the object held
by the smart pointer would remain live for the time any reference to
it or its components exists (an actual subprogram parameter, for
instance).  There would be no promise that cycles do not result in
memory leaks.

Run-time complexity for reference counting is less than for full
garbage collection.  Making it a language feature, rather than a
library-provided functionality, makes it easier for implementations to
optimize updating the counts.  As usual, there is a trade-off between
flexibility and overhead: if the reference counters are kept separate,
it is possible to implement weak pointers and safe references to
sub-components.  Intrusive counts provide better cache locality and
the smart pointers themselves can be a single machine word.

> Type safety is not about detering malicious programmers, merely careless 
> ones.

I think type safety is important for ending up with language semantics
that can be explained.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-07  9:09           ` Florian Weimer
@ 2011-05-07  9:28             ` Dmitry A. Kazakov
  2011-05-07  9:57               ` Florian Weimer
  2011-05-09 20:41             ` Randy Brukardt
  1 sibling, 1 reply; 31+ messages in thread
From: Dmitry A. Kazakov @ 2011-05-07  9:28 UTC (permalink / raw)


On Sat, 07 May 2011 11:09:44 +0200, Florian Weimer wrote:

> Run-time complexity for reference counting is less than for full
> garbage collection.  Making it a language feature, rather than a
> library-provided functionality, makes it easier for implementations to
> optimize updating the counts.

Hmm, what about tasking? I gather that a built-in counter must be atomic.
Whether implemented lock-free or using a spin lock, that would be a
considerable overhead.

> As usual, there is a trade-off between
> flexibility and overhead: if the reference counters are kept separate,
> it is possible to implement weak pointers and safe references to
> sub-components.

Interesting. Do you have a certain schema in mind, how to this?

>> Type safety is not about detering malicious programmers, merely careless 
>> ones.
> 
> I think type safety is important for ending up with language semantics
> that can be explained.

I agree. It is the semantics which yields to safety, not the reverse.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-07  9:28             ` Dmitry A. Kazakov
@ 2011-05-07  9:57               ` Florian Weimer
  2011-05-08  8:08                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2011-05-07  9:57 UTC (permalink / raw)


* Dmitry A. Kazakov:

> On Sat, 07 May 2011 11:09:44 +0200, Florian Weimer wrote:
>
>> Run-time complexity for reference counting is less than for full
>> garbage collection.  Making it a language feature, rather than a
>> library-provided functionality, makes it easier for implementations to
>> optimize updating the counts.
>
> Hmm, what about tasking? I gather that a built-in counter must be atomic.
> Whether implemented lock-free or using a spin lock, that would be a
> considerable overhead.

Modern architectures eliminate most of the overhead in the non-shared
case.  In the M and E states of the MESI protocol, the operation can
be performed locally.

There are techniques to emulate this in software, but they require
safepointing support, which in turn needs extensive run-time
facilities.  (A safepoint allows you to carry out in a safe way an
operation which is clearly unsafe in the presence of multiple tasks.)
Hotspot performs a similar optimization, called biased locking.

>> As usual, there is a trade-off between flexibility and overhead: if
>> the reference counters are kept separate, it is possible to
>> implement weak pointers and safe references to sub-components.
>
> Interesting. Do you have a certain schema in mind, how to this?

The shared pointers in C++ and Boost implement this.  Andrei
Alexandrescu's Modern C++ Design contains a short overview of
implementation choices (but does not cover weak pointers).

GCC's implementation of std::share_ptr uses separate pointers to
objects and their reference counts.  The reference counts contain two
counters, for strong and weak references.  The actual object is
dealloated when the strong count reaches zero.  The reference counts
are deallocated when the strong and weak counts reach zero.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-07  9:57               ` Florian Weimer
@ 2011-05-08  8:08                 ` Dmitry A. Kazakov
  2011-05-08  8:46                   ` Florian Weimer
  0 siblings, 1 reply; 31+ messages in thread
From: Dmitry A. Kazakov @ 2011-05-08  8:08 UTC (permalink / raw)


On Sat, 07 May 2011 11:57:07 +0200, Florian Weimer wrote:

> * Dmitry A. Kazakov:
> 
>> On Sat, 07 May 2011 11:09:44 +0200, Florian Weimer wrote:
>>
>>> As usual, there is a trade-off between flexibility and overhead: if
>>> the reference counters are kept separate, it is possible to
>>> implement weak pointers and safe references to sub-components.
>>
>> Interesting. Do you have a certain schema in mind, how to this?
> 
> The shared pointers in C++ and Boost implement this.  Andrei
> Alexandrescu's Modern C++ Design contains a short overview of
> implementation choices (but does not cover weak pointers).
> 
> GCC's implementation of std::share_ptr uses separate pointers to
> objects and their reference counts.  The reference counts contain two
> counters, for strong and weak references.  The actual object is
> dealloated when the strong count reaches zero.  The reference counts
> are deallocated when the strong and weak counts reach zero.

I mean a schema which could be usable for Ada. I see many problems, apart
from tasking. If you want to refer components, you need to add the parent's
count to the component's count in order to prevent its zeroing. When you
create a reference you have to check if the counts already exist somewhere.
Since nothing is allocated in the object, where get that information from?
IMO weak references are quite useless if do not support notifications (when
the last strong reference is removed). I.e. you need a list of weak
reference holders. Maintaining such lists is a problem. It is more than
count, it can be changed during notifications etc.

One possible approach could be a storage pool maintaining allocating and
maintaining counts for all object allocated there. It won't work for
components, though. 

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08  8:08                 ` Dmitry A. Kazakov
@ 2011-05-08  8:46                   ` Florian Weimer
  2011-05-08  9:32                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2011-05-08  8:46 UTC (permalink / raw)


* Dmitry A. Kazakov:

> I mean a schema which could be usable for Ada. I see many problems, apart
> from tasking. If you want to refer components, you need to add the parent's
> count to the component's count in order to prevent its zeroing.

The component wouldn't have its own count.  A reference to a component
would consist of a pointer to the component, combined with a pointer
to the reference counters for the outmost object.

> When you create a reference you have to check if the counts already
> exist somewhere.  Since nothing is allocated in the object, where
> get that information from?

You would only be able to create a reference from prefixes which
contain references at certain points.  For everything else, you'd have
to use access values, as before.

> IMO weak references are quite useless if do not support notifications (when
> the last strong reference is removed). I.e. you need a list of weak
> reference holders.

I think they are supposed to be used for parent pointers in trees, for
instance, to avoid the cycle issue.  Not so much for finalization.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08  8:46                   ` Florian Weimer
@ 2011-05-08  9:32                     ` Dmitry A. Kazakov
  2011-05-08 10:30                       ` Florian Weimer
  0 siblings, 1 reply; 31+ messages in thread
From: Dmitry A. Kazakov @ 2011-05-08  9:32 UTC (permalink / raw)


On Sun, 08 May 2011 10:46:05 +0200, Florian Weimer wrote:

> * Dmitry A. Kazakov:
> 
>> I mean a schema which could be usable for Ada. I see many problems, apart
>> from tasking. If you want to refer components, you need to add the parent's
>> count to the component's count in order to prevent its zeroing.
> 
> The component wouldn't have its own count.  A reference to a component
> would consist of a pointer to the component, combined with a pointer
> to the reference counters for the outmost object.

Then a built-in access-to-component type might be a better solution. It
would eliminate a need for components to be aliased. Since the offset is
statically known (or a function that calculates it is), it need not to be
kept anywhere.

But the actual problem is that references to components look useless if
cannot be mixed with plain access to the component types. Ada does not
have means for that. E.g. classes of access types.

>> When you create a reference you have to check if the counts already
>> exist somewhere.  Since nothing is allocated in the object, where
>> get that information from?
> 
> You would only be able to create a reference from prefixes which
> contain references at certain points.

OK, but you need to create the first reference somehow. That is what an
embedded count does, the object is kind of a reference to itself. If that
is dropped, one have to find another mechanism for that.

>> IMO weak references are quite useless if do not support notifications (when
>> the last strong reference is removed). I.e. you need a list of weak
>> reference holders.
> 
> I think they are supposed to be used for parent pointers in trees, for
> instance, to avoid the cycle issue.  Not so much for finalization.

I rather use: parent-->child is a plain pointer, child-->parent is a strong
reference. The most interesting cases for weak references are in the first
line finalization notification. E.g. cached objects. They are referenced by
weak reference by the cache monitor. When the object is finalized, the
monitor synchronizes the object's actual state with the non-volatile memory
etc.

I think that the issue is too varying and complex to have it built-in. I
would prefer if Ada provided mechanisms for implementation of such stuff at
the library level. E.g. user-defined access types with primitive
referencing, dereferencing, finalization operations. Classes of access
types etc.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08  9:32                     ` Dmitry A. Kazakov
@ 2011-05-08 10:30                       ` Florian Weimer
  2011-05-08 20:24                         ` anon
  2011-05-09  7:48                         ` Dmitry A. Kazakov
  0 siblings, 2 replies; 31+ messages in thread
From: Florian Weimer @ 2011-05-08 10:30 UTC (permalink / raw)


* Dmitry A. Kazakov:

> Then a built-in access-to-component type might be a better solution. It
> would eliminate a need for components to be aliased. Since the offset is
> statically known (or a function that calculates it is), it need not to be
> kept anywhere.

You'd still have the safety hazard with the reference to the outer
record.  There are is some impact on encapsulation which has to be
considered.  And it's not going to help with the original problem (a
safer replacement for discriminants with defaults).

> OK, but you need to create the first reference somehow.

Uhm, I had imagined you'd use an allocator for that.  The whole thing
is meant to be a bit similar to access values.

>>> IMO weak references are quite useless if do not support notifications (when
>>> the last strong reference is removed). I.e. you need a list of weak
>>> reference holders.
>> 
>> I think they are supposed to be used for parent pointers in trees, for
>> instance, to avoid the cycle issue.  Not so much for finalization.
>
> I rather use: parent-->child is a plain pointer, child-->parent is a
> strong reference.

Dereferencing a weak pointer incurs a run-time check and operations on
the counters (if reference counting is used), and the parent pointer
is only needed for some traversal operations, so weak pointers upwards
seem the way to go.

> The most interesting cases for weak references are in the first line
> finalization notification. E.g. cached objects.

You would get that with controlled types.

I don't think weak references work for caches if you have reference
counts and precise finalization because the last reference to the
cached object goes away too soon.  There are different types of
references (sometimes called "weak", too) which are cleared by the
memory manager if it cannot satisfy an allocation request, but this
raises awkward concurrency issues, and this wouldn't actually need
references, you'd just have to register those special references with
the memory manager.

> I think that the issue is too varying and complex to have it
> built-in. I would prefer if Ada provided mechanisms for
> implementation of such stuff at the library level. E.g. user-defined
> access types with primitive referencing, dereferencing, finalization
> operations. Classes of access types etc.

A pure library implementation would make certain optimizations
difficult or impossible: for example, link-time replacement of
tasking-safe counter implementations when there is no tasking, or
avoidance of repeated counter operations on the same object.  It also
requires a lot of mechanics, adding more complexity to the language
than a built-in facility.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08 10:30                       ` Florian Weimer
@ 2011-05-08 20:24                         ` anon
  2011-05-08 21:11                           ` Simon Wright
  2011-05-09  7:48                         ` Dmitry A. Kazakov
  1 sibling, 1 reply; 31+ messages in thread
From: anon @ 2011-05-08 20:24 UTC (permalink / raw)


Your two programs has pointed out a puzzle in the RM-2005.  And that is 
does the definition of the standard Generic package Unchecked_Conversion 
violate the RM (6.5/(5.5/2). 

      generic
         type Source(<>) is limited private;
         type Target(<>) is limited private;
      function Ada.Unchecked_Conversion(S : Source) return Target;
      pragma Convention(Intrinsic, Ada.Unchecked_Conversion);
      pragma Pure(Ada.Unchecked_Conversion);


And when you compile the RM Ada 95 specification and body version of 
the Unchecked_Conversion using Ada 2005 compiler you get the following 
errors:

   (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2))
   return by reference not permitted in Ada 2005
   consider switching to return of access type

But that suggest the RM standard generic Unchecked_Conversion is obsolete 
in its current version or is in error. And yes, I know that mostly the 
compiler emulates the Unchecked_Conversion body, but that not always an 
option.

Now, since one reason the extended return statement was created was to 
handle "Limited Private" type the simple and return aggregate statements 
are out.

And, using a simple design of the extended return statement causes semantic 
error in Ada 95/2005 because any reference to an unconstrained Target is 
not valid. Such as:

      return Result : Target do    -- not valid, must be initialized
                                   -- in this form (Discriminant)
          Result := Target ( Object_Access.all ) ;
        end return ;


So, how does one use this extended return statement to return a 
"Unconstrained Discriminated Limited Private" object for this type of 
generic function?  Or is the Unchecked_Conversion generic function a 
violation of the RM 2005 rules?




In <87pqntscwj.fsf@mid.deneb.enyo.de>, Florian Weimer <fw@deneb.enyo.de> writes:
>* Dmitry A. Kazakov:
>
>> Then a built-in access-to-component type might be a better solution. It
>> would eliminate a need for components to be aliased. Since the offset is
>> statically known (or a function that calculates it is), it need not to be
>> kept anywhere.
>
>You'd still have the safety hazard with the reference to the outer
>record.  There are is some impact on encapsulation which has to be
>considered.  And it's not going to help with the original problem (a
>safer replacement for discriminants with defaults).
>
>> OK, but you need to create the first reference somehow.
>
>Uhm, I had imagined you'd use an allocator for that.  The whole thing
>is meant to be a bit similar to access values.
>
>>>> IMO weak references are quite useless if do not support notifications (when
>>>> the last strong reference is removed). I.e. you need a list of weak
>>>> reference holders.
>>> 
>>> I think they are supposed to be used for parent pointers in trees, for
>>> instance, to avoid the cycle issue.  Not so much for finalization.
>>
>> I rather use: parent-->child is a plain pointer, child-->parent is a
>> strong reference.
>
>Dereferencing a weak pointer incurs a run-time check and operations on
>the counters (if reference counting is used), and the parent pointer
>is only needed for some traversal operations, so weak pointers upwards
>seem the way to go.
>
>> The most interesting cases for weak references are in the first line
>> finalization notification. E.g. cached objects.
>
>You would get that with controlled types.
>
>I don't think weak references work for caches if you have reference
>counts and precise finalization because the last reference to the
>cached object goes away too soon.  There are different types of
>references (sometimes called "weak", too) which are cleared by the
>memory manager if it cannot satisfy an allocation request, but this
>raises awkward concurrency issues, and this wouldn't actually need
>references, you'd just have to register those special references with
>the memory manager.
>
>> I think that the issue is too varying and complex to have it
>> built-in. I would prefer if Ada provided mechanisms for
>> implementation of such stuff at the library level. E.g. user-defined
>> access types with primitive referencing, dereferencing, finalization
>> operations. Classes of access types etc.
>
>A pure library implementation would make certain optimizations
>difficult or impossible: for example, link-time replacement of
>tasking-safe counter implementations when there is no tasking, or
>avoidance of repeated counter operations on the same object.  It also
>requires a lot of mechanics, adding more complexity to the language
>than a built-in facility.




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08 20:24                         ` anon
@ 2011-05-08 21:11                           ` Simon Wright
  2011-05-10  6:27                             ` anon
  0 siblings, 1 reply; 31+ messages in thread
From: Simon Wright @ 2011-05-08 21:11 UTC (permalink / raw)


anon@att.net writes:

> Your two programs has pointed out a puzzle in the RM-2005.  And that is 
> does the definition of the standard Generic package Unchecked_Conversion 
> violate the RM (6.5/(5.5/2). 

"I beseech you, in the bowels of Christ, think it possible that you may
 be mistaken."
 O. Cromwell, 1650.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08 10:30                       ` Florian Weimer
  2011-05-08 20:24                         ` anon
@ 2011-05-09  7:48                         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 31+ messages in thread
From: Dmitry A. Kazakov @ 2011-05-09  7:48 UTC (permalink / raw)


On Sun, 08 May 2011 12:30:04 +0200, Florian Weimer wrote:

> * Dmitry A. Kazakov:
> 
>> Then a built-in access-to-component type might be a better solution. It
>> would eliminate a need for components to be aliased. Since the offset is
>> statically known (or a function that calculates it is), it need not to be
>> kept anywhere.
> 
> You'd still have the safety hazard with the reference to the outer
> record.  There are is some impact on encapsulation which has to be
> considered.  And it's not going to help with the original problem (a
> safer replacement for discriminants with defaults).

I don't think there is a solution for that. Variant components have no
static scope, so any reference can only be a weak one with dynamic checks.
I don't think that dynamic checks is a good idea. On the contrary, dynamic
accessibility checks is the most damaging feature Ada ever had.

>> OK, but you need to create the first reference somehow.
> 
> Uhm, I had imagined you'd use an allocator for that.  The whole thing
> is meant to be a bit similar to access values.

It would not work with stack-allocated objects.

Anyway, if you do it upon allocation, then in effect the reference count is
always there, "put" into the object either explicitly (via MI) or
implicitly (via the storage pool).

>>>> IMO weak references are quite useless if do not support notifications (when
>>>> the last strong reference is removed). I.e. you need a list of weak
>>>> reference holders.
>>> 
>>> I think they are supposed to be used for parent pointers in trees, for
>>> instance, to avoid the cycle issue.  Not so much for finalization.
>>
>> I rather use: parent-->child is a plain pointer, child-->parent is a
>> strong reference.
> 
> Dereferencing a weak pointer incurs a run-time check and operations on
> the counters (if reference counting is used), and the parent pointer
> is only needed for some traversal operations, so weak pointers upwards
> seem the way to go.

I considered that schema, but then dropped it. It was much simpler to have
children to hold their parents. Parent need not to have a reference to its
children because in the scenarios I considered, parent always controls its
children explicitly, e.g. when the tree is manipulated.

>> The most interesting cases for weak references are in the first line
>> finalization notification. E.g. cached objects.
> 
> You would get that with controlled types.

References must be "controlled" anyway, in the sense that reference
finalization is not null.

> I don't think weak references work for caches if you have reference
> counts and precise finalization because the last reference to the
> cached object goes away too soon.

Before the target object finalization occurs, all weak references get
notified and then invalidated when the strong count reaches zero. I don't
think that weak references asynchronously going invalid is a good idea.
Especially in tasking environment, where you cannot safely dereference weak
references, you have to temporarily promote them to strong references.

>> I think that the issue is too varying and complex to have it
>> built-in. I would prefer if Ada provided mechanisms for
>> implementation of such stuff at the library level. E.g. user-defined
>> access types with primitive referencing, dereferencing, finalization
>> operations. Classes of access types etc.
> 
> A pure library implementation would make certain optimizations
> difficult or impossible: for example, link-time replacement of
> tasking-safe counter implementations when there is no tasking, or
> avoidance of repeated counter operations on the same object.

Yes, but I would buy that. Hardware is cheaper than the software. When will
first implementations of such optimizations appear? How soon will they
become bug-free? How many generations of hardware will change in that
period of time?

> It also
> requires a lot of mechanics, adding more complexity to the language
> than a built-in facility.

No, it should simplify the language because this mechanics looks quite
universal to me. In particular it could make "access", "controlled" and
"tagged" types library level implementations.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-07  9:09           ` Florian Weimer
  2011-05-07  9:28             ` Dmitry A. Kazakov
@ 2011-05-09 20:41             ` Randy Brukardt
  1 sibling, 0 replies; 31+ messages in thread
From: Randy Brukardt @ 2011-05-09 20:41 UTC (permalink / raw)


"Florian Weimer" <fw@deneb.enyo.de> wrote in message 
news:877ha2op0n.fsf@mid.deneb.enyo.de...
>* Randy Brukardt:
>
>> Actually, I think T.T'Access is illegal, because the component T is not
>> declared as aliased. You can take 'Access of the parameter T, but not of
>> some random component (as is currently the case in Ada).
>
> Wouldn't it work if the component T was aliased?

Maybe, but there are fairly strong rules on which components can have 
'Access taken when they are discriminant dependent. (Note that these rules 
are not about aliasing, but rather to detect cases where components 
disappear because of direct modification. But of course they prevent a lot 
of aliasing problems as well.)

...
>> But this looks like an attempt to shot yourself in the foot; it's hardly
>> likely to happen by accident. Remember that no programming language can
>> really defend against malicious programmers; the point is to defend 
>> against
>> sloppy or careless programmers [which is all of us, sooner or later].
>
> My first answer that was rather confrontational.  Let me just say that
> this is the line of argument used by C advocates.

How so? C makes no attempt to detect problems caused by sloppy or careless 
programmers. It says that you shouldn't be sloppy or careless. Ada says that 
we'll detect errors caused by sloppiness or carelessness, but not by 
maliciousness (as that was thought to make the language unusable).

Just to give an example unrelated to the topic of discussion, you can use 
Unchecked_Conversion to break privacy - just dupication the full type 
declaration from the private part into your own code and Unchecked_Convert 
to/from the original private type to your full declaration. This clearly 
does all kinds of violence to the typing model, but it is not going to 
happen by accident. So Ada allows Unchecked_Conversion even though it can do 
untold damage if abused.

>> For instance, the tampering checks of the Ada containers implicit in
>> the new Reference routines can be defeated by the use of
>> Unchecked_Deallocation on the return object. But this is not
>> something that is reasonably going to happen by accident, and it is
>> out in the open for program reviewers (both tools and humans) to
>> find. It's not worth worrying about.
>
> It's true that use-after-free errors typically result in exactly the
> same type safety violation.  But they seem to be rather hard to spot
> in COTS software, and I'm not sure that the programming languages are
> to blame.  Manual memory management is just hard.

I think you are missing the point. If you do something abusive in the code, 
you can circumvent the checks. But that doesn't happen by accident.

Also note that the problem I was referring to has nothing to do with 
use-after-free; the problem is that the Unchecked_Deallocation triggers an 
early finalization while you still can be holding a valid copy of the 
wrapped access value.

>>> It seems to me that you need a C++-like rule that accessing an object
>>> through a view which is not compatible with its dynamic type is
>>> erroneous.  And this would be quite a defeat.
>>
>> But that's exactly what 3.7.2(4) is. And it has been in Ada since the
>> beginning.
>
> 3.7.2(4) has very precise syntact requirements ("a name denoting a
> subcomponent that depends on discriminants" etc.).  I don't think it
> covers the new possibilities introduced by aliased parameters.

Sorry, but there aren't any new possibilities, unless we all have missed 
something very fundemental. Ada has always allowed composite parameters to 
be passed by reference, and most compilers in fact do that. You can take 
'Unchecked_Access of components of any parameters that you want. You 
probably can't take 'Access of those components (the accessibility is 
local).

Aliased parameters have very little effect on this situation. The 
accessibility is changed very slightly so that it can be returned as part of 
a return object, but only in cases that already have very short lifetimes 
(mostly access discriminants and anonymous access returns). The parameter is 
guaranteed to have the same lifetime as the return object. So in virtually 
all cases, you'll still need to use 'Unchecked_Access to get access to 
components.

The problem here is parameter aliasing, and that was a problem with 
programming languages long before Ada was designed. Ada didn't try to solve 
it, and it's now 30 years too late to do so.


>> Also note that a lot of renaming and 'Access of discriminant-dependent
>> components is not allowed; we've tighened those rules with each version 
>> of
>> Ada.
>
> It's not clear to me if these rules are valuable when its easy to
> circumvent them.  They mostly seem to increase the complexity of the
> language.

Ada has never made any attempt to prevent malicious programmers; to do so 
would require having no low-level features in the language. The problem here 
(if there is a problem) is that this might happen by accident. But there is 
no more likelyhood of that now than in Ada 83 (and I'd argue it is a lot 
safer now, rather than using untyped 'Address to access components).

>>> The difficulty I alluded lies in the answer to this question: Are
>>> aliased parameters at fault, or are discriminants with defaults to
>>> blame?
>>
>> Almost certainly discriminants with defaults, since the problem has
>> existed in Ada since Ada 83, and we are not making it any worse
>> (that would be impossible, IMHO).
>
> I tend to agree.  Would it make sense to deprecate discriminants with
> defaults?

I don't think so, it is much too fundemental of a feature.

Note that the problem here is really parameter aliasing -- any time that a 
parameter can be accessed both by the parameter name and put some other name 
there is possibly trouble. (At least, you have a dependence on the parameter 
passing implementation, which Ada doesn't specify for many kinds of types.) 
Note that there are potentially problems for *any* kind of type -- this is 
precisely why Ada requires by-copy parameter passing for elementary types. 
It's not limited to discriminants with defaults.

Ada 2012 has added some attributes which can be used to test if this is 
happening (of course, that requires knowing that there is a potential 
problem). Beyond that, it is relatively easy for tools that have the entire 
source code available to check for such things -- but it isn't a problem 
that the language (which has to allow compilation of partial programs) can 
fix.

> ... As a replacement, smart pointers could be added to the
> language, with syntactical overhead compared to access types, which
> would allow programmers to replace discriminants with default with a
> smart pointer to an unconstrained type.  Implementations would be
> allowed to use reference counting, or full garbage collection.
> However, they would have to ensure that references to the object held
> by the smart pointer would remain live for the time any reference to
> it or its components exists (an actual subprogram parameter, for
> instance).  There would be no promise that cycles do not result in
> memory leaks.

Tucker tried to propose something like this (see AI05-0111-1). The feedback 
that we got (especially from the Ada conferences) was that it is just too 
complex to use. The complaint is that if you are going to work that hard, 
you probably would just as soon use real garbage collection.

Instead, we decided to address the two things that users can't write 
themselves -- control over finalization of allocated objects, and convinient 
syntax for user-defined pointers.

Thus Ada 2012 adds subpools and the Reference aspect, and nothing else. We 
hope that if smart pointers are really a good idea, that users and 
implementers will create implementations using these building blocks. And 
then we can consider standardizing something in Ada 2020 if they are being 
used a lot.

It doesn't make much sense to standardize something that few people appear 
to be interested in (even if it might be a good idea in a vacuum).

                                Randy. 





^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-08 21:11                           ` Simon Wright
@ 2011-05-10  6:27                             ` anon
  2011-05-10 14:39                               ` Adam Beneschan
  0 siblings, 1 reply; 31+ messages in thread
From: anon @ 2011-05-10  6:27 UTC (permalink / raw)


Better look again!

Even though a compiler emulates the "Unchecked_Conversion" with a built-in 
"pragma inline" being enforced.  The function still must be able to be 
written in Ada. That goes back to the origins of Ada and has not change. 
Plus, the function's source code can be inserted into a routine or 
re-named for use or testing of this routine. That is also apart of Ada.

Any programmer should be able to simulated the Unchecked_Conversion 
function in Ada (non GNAT), such as:

      pragma Suppress ( All_Checks ) ;    -- Ada 95/2005
      Target_Object := Target ( Source_Object ) ;
      pragma Unsuppress ( All_Checks ) ;  -- Ada 95/2005

Now, in Ada 83 there was no way to turn the checks back on after they
were suppressed. The exception was to use a function where the scope of 
the suppressed checks would be limited to that function only, thus a 
reason for the creation of the generic "Unchecked_Conversion" function.


The body of the "Unchecked_Conversion" function is:

---------------------------------------
  function Unchecked_Conversion ( S : Source ) 
           return Target is

      -- Ada 83 a Suppress statement per check must be given
      -- 
      pragma Suppress ( All_Checks ) ; 

    begin
      --  This statement should compile because all checks have been 
      --  turn off. Even without checks this routine must still comply 
      --  with type conversion rules set in RM 4.6, which can limited
      --  or restriction the conversion. 
      --
      --  Starting with Ada 95 the semantic and expansion analysis 
      --  must also, insure that the additional rules RM 13.9 
      --  ( 5 .. 10 ) are enforced. Since these rules can be derived
      --  from the legal rules for type conversion ( RM 4.6 ), these
      --  checks can be done in the while evaluating the type 
      --  conversion expression.
      --
      --  Ada 83, RM 13.10.2 ( 3 ) states the programmer is 
      --  "responsibility to ensure that these conversions maintain
      --  the properties that are guaranteed by the language for 
      --  objects of the target type." But the vendor can set
      --  restrictions.
      --
      return Target ( S ) ;
  end Unchecked_Conversion ;
---------------------------------------

Now in Ada 2005, RM 7.5 (1/2) states that a routine can not just copy
a "limited private" object. RM 6.5 (5.1/2, 5.c/2 ) states that if 
the target is limited the function "must produce a ""new"" object" 
instead of just copying the object.

Aka the "Unchecked_Conversion" which is a generic function is no 
longer just an inlined expression that is just a type conversions 
with all checks being disable. The function must now return a "new" 
object RM 6.5 (5.5/2, 5.c/2 ), by first requesting an new object 
from the Target's storage pool and then copying the Source data to 
that new object. So, in Ada 2005 the "Unchecked_Conversion" must be 
handled as a true generic function with a true return, instead of a 
built-in inline expression.

But GNAT still just performs a simple copy. So, is GNAT or the RM 
or is the generic "Unchecked_Conversion" function in error?


In <m2y62g7v92.fsf@pushface.org>, Simon Wright <simon@pushface.org> writes:
>anon@att.net writes:
>
>> Your two programs has pointed out a puzzle in the RM-2005.  And that is 
>> does the definition of the standard Generic package Unchecked_Conversion 
>> violate the RM (6.5/(5.5/2). 
>
>"I beseech you, in the bowels of Christ, think it possible that you may
> be mistaken."
> O. Cromwell, 1650.




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-10  6:27                             ` anon
@ 2011-05-10 14:39                               ` Adam Beneschan
  2011-05-11 20:39                                 ` anon
  0 siblings, 1 reply; 31+ messages in thread
From: Adam Beneschan @ 2011-05-10 14:39 UTC (permalink / raw)


On May 9, 11:27 pm, a...@att.net wrote:
> Better look again!
>
> Even though a compiler emulates the "Unchecked_Conversion" with a built-in
> "pragma inline" being enforced.  The function still must be able to be
> written in Ada.

No, it doesn't.  Show me a rule in the RM that says it does.  You
can't.  There isn't one.

                           -- Adam



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-10 14:39                               ` Adam Beneschan
@ 2011-05-11 20:39                                 ` anon
  2011-05-12  0:51                                   ` Randy Brukardt
  2011-05-12  5:51                                   ` AdaMagica
  0 siblings, 2 replies; 31+ messages in thread
From: anon @ 2011-05-11 20:39 UTC (permalink / raw)


The RM 13.9 (3) defines the Unchecked_Conversion function with

    pragma Convention ( Intrinsic, Ada.Unchecked_Conversion ) ;

Intrinsic is built-in" and RM C.1 ( 10 ) implies inlining to reduce 
overhead of this function and RM 13.8 ( 15 ) helps reduces the code 
to that of an inline Machine Code Insertions.


Proof basically come from RM 6.3.1 ( 4 ), RM 13.9 ( 15 ) and 
C.1 ( 10 ).

RM 6.3.1 Conformance Rules 
   
    4  "The Intrinsic calling convention represents subprograms that 
       are ``built in'' to the compiler." ...

RM 13.9 Unchecked Type Conversions

  15   The implementation should not generate unnecessary run-time 
       checks to ensure that the representation of S is a 
       representation of the target type. It should take advantage of 
       the permission to return by reference when possible.  
       Restrictions on unchecked conversions should be avoided unless
       required by the target environment.

RM C.1 Access to Machine Operations

  10   "The implementation should ensure that little or no overhead 
       is associated with calling intrinsic and machine-code 
       subprograms"



Associative RMs  

RM 13.8 Machine Code Insertions

  11   "(17) Intrinsic subprograms (see 6.3.1, ``Conformance Rules'') 
       can also be used to achieve machine code insertions." ...

RM C.1 Access to Machine Operations

   6   "The implementation shall document the overhead associated 
        with calling machine-code or intrinsic subprograms, as 
        compared to a fully-inlined call, and to a regular 
        out-of-line call."



Now in Ada 2005, RM 7.5 (1/2) states that a routine can not just copy
a "limited private" object. RM 6.5 (5.1/2, 5.c/2 ) states that if 
the target is limited the function "must produce a ""new"" object" 
instead of just copying the object.

Aka the "Unchecked_Conversion" which is a generic function is no 
longer just an inlined expression that is just a type conversions 
with all checks being disable. The function must now return a "new" 
object RM 6.5 (5.5/2, 5.c/2 ), by first requesting an new object 
from the Target's storage pool and then copying the Source data to 
that new object. So, in Ada 2005 the "Unchecked_Conversion" must be 
handled as a true generic function with a true return, instead of a 
built-in inline expression.

But GNAT still just performs a simple copy. So, is GNAT or the RM 
or is the generic "Unchecked_Conversion" function in error?


In <715a5498-095c-4e61-8a09-8510c19b2553@s16g2000prf.googlegroups.com>, Adam Beneschan <adam@irvine.com> writes:
>On May 9, 11:27=A0pm, a...@att.net wrote:
>> Better look again!
>>
>> Even though a compiler emulates the "Unchecked_Conversion" with a built-i=
>n
>> "pragma inline" being enforced. =A0The function still must be able to be
>> written in Ada.
>
>No, it doesn't.  Show me a rule in the RM that says it does.  You
>can't.  There isn't one.
>
>                           -- Adam




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-11 20:39                                 ` anon
@ 2011-05-12  0:51                                   ` Randy Brukardt
  2011-05-13  0:47                                     ` anon
  2011-05-12  5:51                                   ` AdaMagica
  1 sibling, 1 reply; 31+ messages in thread
From: Randy Brukardt @ 2011-05-12  0:51 UTC (permalink / raw)


<anon@att.net> wrote in message news:iqes6i$18g$1@speranza.aioe.org...
> The RM 13.9 (3) defines the Unchecked_Conversion function with
>
>    pragma Convention ( Intrinsic, Ada.Unchecked_Conversion ) ;
>
> Intrinsic is built-in" and RM C.1 ( 10 ) implies inlining to reduce
> overhead of this function and RM 13.8 ( 15 ) helps reduces the code
> to that of an inline Machine Code Insertions.
>
>
> Proof basically come from RM 6.3.1 ( 4 ), RM 13.9 ( 15 ) and
> C.1 ( 10 ).
>
> RM 6.3.1 Conformance Rules
>
>    4  "The Intrinsic calling convention represents subprograms that
>       are ``built in'' to the compiler." ...
>
> RM 13.9 Unchecked Type Conversions
>
>  15   The implementation should not generate unnecessary run-time
>       checks to ensure that the representation of S is a
>       representation of the target type. It should take advantage of
>       the permission to return by reference when possible.
>       Restrictions on unchecked conversions should be avoided unless
>       required by the target environment.
>
> RM C.1 Access to Machine Operations
>
>  10   "The implementation should ensure that little or no overhead
>       is associated with calling intrinsic and machine-code
>       subprograms"
>
>
>
> Associative RMs
>
> RM 13.8 Machine Code Insertions
>
>  11   "(17) Intrinsic subprograms (see 6.3.1, ``Conformance Rules'')
>       can also be used to achieve machine code insertions." ...
>
> RM C.1 Access to Machine Operations
>
>   6   "The implementation shall document the overhead associated
>        with calling machine-code or intrinsic subprograms, as
>        compared to a fully-inlined call, and to a regular
>        out-of-line call."
>
>
>
> Now in Ada 2005, RM 7.5 (1/2) states that a routine can not just copy
> a "limited private" object. RM 6.5 (5.1/2, 5.c/2 ) states that if
> the target is limited the function "must produce a ""new"" object"
> instead of just copying the object.
>
> Aka the "Unchecked_Conversion" which is a generic function is no
> longer just an inlined expression that is just a type conversions
> with all checks being disable. The function must now return a "new"
> object RM 6.5 (5.5/2, 5.c/2 ), by first requesting an new object
> from the Target's storage pool and then copying the Source data to
> that new object. So, in Ada 2005 the "Unchecked_Conversion" must be
> handled as a true generic function with a true return, instead of a
> built-in inline expression.
>
> But GNAT still just performs a simple copy. So, is GNAT or the RM
> or is the generic "Unchecked_Conversion" function in error?

You, of course. :-) Your language-lawyering skills need some work.

13.9(12) (an implementation permission) says that an implementation can 
return the result of an unchecked_conversion "by reference". Especially note 
the second sentence of that rule, which explains the intent.

                            Randy.









^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-11 20:39                                 ` anon
  2011-05-12  0:51                                   ` Randy Brukardt
@ 2011-05-12  5:51                                   ` AdaMagica
  2011-05-12 12:09                                     ` Robert A Duff
  2011-05-12 14:40                                     ` Adam Beneschan
  1 sibling, 2 replies; 31+ messages in thread
From: AdaMagica @ 2011-05-12  5:51 UTC (permalink / raw)


Randy has already given the answer.

Let me add a further remark (but note, I'm no language lawyer):

You argue about the return statement. But there is no return statement
involved in the RM with Unchecked_Conversion, it's just compiler magic
that is being performed. (Being intrinsic, Unchecked_Conversion need
not be implemented in Ada. In fact, I think there is no code at all,
it just takes the bit pattern as is and reinterpretes it.)

Run the following test program:

package UC is

  type LP1 is limited private;

  procedure Set (X: out LP1; to: Integer);

  type LP2 is limited private;

private

  type LP1 is limited record
    I: Integer := 1234;
  end record;

  type LP2 is limited record
    I: Integer := Integer'First;
  end record;

end UC;
package body UC is

  procedure Set (X: out LP1; to: Integer) is
  begin
    X.I := to;
  end Set;

end UC;
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
with UC;

procedure Test_UC is

  function LP1_LP2 is new Ada.Unchecked_Conversion (UC.LP1, UC.LP2);
  function LP2_I   is new Ada.Unchecked_Conversion (UC.LP2, Integer);

  X: UC.LP1;
  Y: constant UC.LP2    :=   LP1_LP2 (X);  -- new object built in
place
  Z:          UC.LP2 renames LP1_LP2 (X);  -- read-only view

begin
 
-- expected result
  Ada.Text_IO.Put_Line (Integer'Image (LP2_I (Y)) & Integer'Image
(LP2_I (Z)));  -- 1234 1234
  UC.Set (X, -100);
  Ada.Text_IO.Put_Line (Integer'Image (LP2_I (Y)) & Integer'Image
(LP2_I (Z)));  -- 1234-100

end Test_UC;



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-12  5:51                                   ` AdaMagica
@ 2011-05-12 12:09                                     ` Robert A Duff
  2011-05-12 14:40                                     ` Adam Beneschan
  1 sibling, 0 replies; 31+ messages in thread
From: Robert A Duff @ 2011-05-12 12:09 UTC (permalink / raw)


AdaMagica <christ-usch.grein@t-online.de> writes:

>... (Being intrinsic, Unchecked_Conversion need
> not be implemented in Ada.

It's true that Unchecked_Conversion need not be implemented in Ada -- it
can be implemented however the compiler writer likes.  But it's got
nothing to do with "intrinsic".  Every feature can be implemented
however the compiler writer likes.  For example, Text_IO.Put_Line, which
is not intrinsic, need not be implemented in Ada.

Intrinsic just means you can't do 'Access and similar things.

- Bob



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  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
  1 sibling, 1 reply; 31+ messages in thread
From: Adam Beneschan @ 2011-05-12 14:40 UTC (permalink / raw)


On May 11, 10:51 pm, AdaMagica <christ-usch.gr...@t-online.de> wrote:
> Randy has already given the answer.
>
> Let me add a further remark (but note, I'm no language lawyer):
>
> You argue about the return statement. But there is no return statement
> involved in the RM with Unchecked_Conversion, it's just compiler magic
> that is being performed. (Being intrinsic, Unchecked_Conversion need
> not be implemented in Ada. In fact, I think there is no code at all,
> it just takes the bit pattern as is and reinterpretes it.)

I think the poster's argument (inasmuch as I could follow it) was that
although Unchecked_Conversion is implemented via compiler magic, it
has to be defined in such a way that it *could* be written in Ada, and
this would be a problem because you couldn't write a RETURN statement
that would make it work.  Or something like that.  The basic problem
is that there is no such rule (and never has been) that the function
has to be writeable in Ada, despite the poster's assertion that "that
goes back to the origins of Ada and has not change", so the whole
argument is based on a false premise.  The poster tried to make an
argument to prove this premise, but I'm still trying to figure out
what this argument was.  It seems to be based on reading much more
into certain language rules than is written there.

                                   -- Adam



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  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
  0 siblings, 2 replies; 31+ messages in thread
From: anon @ 2011-05-13  0:47 UTC (permalink / raw)


--
--  May be this program will help explain the problem.
--
--  Plus, 
--  RM 13.9 (12) -- say the function can copy "by reference, if the 
--  Source type is not a by-copy type." In Ada 2005, the definition
--  of Source type for the Unchecked_Conversion is still a "limited 
--  private" which is a "Limited Type, and all Limited types (RM 7.5) 
--  are now a by-copy type. So, Unchecked_Conversion must now use
--  only "by-copy" type of copying. This suggest that the RM 13.9 (12) 
--  paragraph may be in Error an needs to be update at least for Ada 
--  2012. And corrected in 2005.
--
--  RM 7.5 ( 1.b/2 ), Suggest that the copying "Limited Types" by 
--  reference was for Ada 95. That changes for Ada 2005.
--
--  This may also explain what Robert Dewar was taking about in 
--  AI95-00318-02.
--

--
-- Testing the Generic Unchecked_Conversion function.
-- By copying and renaming the function to Ada05_Conversion.
--
with Interfaces ;
with Text_IO ;
--
procedure Test_UC is

  use Interfaces ;
  --
  package Byte_IO is new Text_IO.Modular_IO ( Unsigned_8 ) ;
  package U32_IO is new Text_IO.Modular_IO ( Unsigned_32 ) ;
  --
  type Boolean_Array is array ( Natural range <> ) of Boolean ;
    pragma Pack ( Boolean_Array ) ;

  --
  -- Limited type: must copy by "by-copy type"
  --
  type Record_Type is limited record
                                Flags : Boolean_Array ( 0 .. 31 ) ;
                              end record ;
    pragma Pack ( Record_Type ) ;


  -- ------------------ --
  --  Ada05_Conversion  --
  -- ------------------ --
  generic
    type Source (<>) is limited private ;
    type Target (<>) is limited private ;
    function Ada05_Conversion ( S : Source ) return Target ;

  function Ada05_Conversion ( S : Source ) return Target is

      pragma Suppress ( All_Checks ) ;

    begin
      -- Compiling Error messages:
      --   (Ada 2005) cannot copy object of a limited type 
      --              (RM-2005 6.5(5.5/2))
      --   consider switching to return of access type
      --
      -- Additional References for reasoning: 
      --   RM 7.5 Limited Types ( 1/2, 1.a, 1.b/2 )
      --
      return Target ( S ) ;
    end Ada05_Conversion ;

  --
  function To_Byte is new Ada05_Conversion
                        ( Source => Unsigned_8, Target => Character ) ;

  function To_Unsigned_32 is new Ada05_Conversion
                     ( Source => Record_Type, Target => Unsigned_32 ) ;

  C  : Character := 'c' ;
  S  : Unsigned_8 := 16#41# ;  -- 'A'

  R0 : Record_Type ;
  R1 : Unsigned_32 ;

begin
  --
  -- Copy a simple unsigned_8 to character
  --
  C := To_Byte ( S ) ;             -- Perform conversion
  --
  -- Should display:
  --     Test 1:  C := 'A'
  --
  Text_IO.Put ( "Test 1:  " ) ;
  Text_IO.Put ( "C := '" ) ;
  Text_IO.Put ( C ) ;
  Text_IO.Put ( ''' ) ;
  Text_IO.New_Line ;
  --
  R0.Flags ( 28 .. 31 ) := ( others => True ) ; 
  R0.Flags ( 00 .. 27 ) := ( others => False ) ; 
  --
  -- Copy a limited record to a Unsigned_32 
  --
  R1 := To_Unsigned_32 ( R0 ) ;    -- Perform conversion
  --
  -- Should display:
  --     Test 2:  R0 := 2#11110000000000000000000000000000#
  --
  Text_IO.Put ( "Test 2:  " ) ;
  Text_IO.Put ( "R0 := " ) ;
  U32_IO.Put ( R1, base => 2 ) ;
  Text_IO.New_Line ;
end Test_UC ;

In <iqfaud$ggn$1@munin.nbi.dk>, "Randy Brukardt" <randy@rrsoftware.com> writes:
><anon@att.net> wrote in message news:iqes6i$18g$1@speranza.aioe.org...
>> The RM 13.9 (3) defines the Unchecked_Conversion function with
>>
>>    pragma Convention ( Intrinsic, Ada.Unchecked_Conversion ) ;
>>
>> Intrinsic is built-in" and RM C.1 ( 10 ) implies inlining to reduce
>> overhead of this function and RM 13.8 ( 15 ) helps reduces the code
>> to that of an inline Machine Code Insertions.
>>
>>
>> Proof basically come from RM 6.3.1 ( 4 ), RM 13.9 ( 15 ) and
>> C.1 ( 10 ).
>>
>> RM 6.3.1 Conformance Rules
>>
>>    4  "The Intrinsic calling convention represents subprograms that
>>       are ``built in'' to the compiler." ...
>>
>> RM 13.9 Unchecked Type Conversions
>>
>>  15   The implementation should not generate unnecessary run-time
>>       checks to ensure that the representation of S is a
>>       representation of the target type. It should take advantage of
>>       the permission to return by reference when possible.
>>       Restrictions on unchecked conversions should be avoided unless
>>       required by the target environment.
>>
>> RM C.1 Access to Machine Operations
>>
>>  10   "The implementation should ensure that little or no overhead
>>       is associated with calling intrinsic and machine-code
>>       subprograms"
>>
>>
>>
>> Associative RMs
>>
>> RM 13.8 Machine Code Insertions
>>
>>  11   "(17) Intrinsic subprograms (see 6.3.1, ``Conformance Rules'')
>>       can also be used to achieve machine code insertions." ...
>>
>> RM C.1 Access to Machine Operations
>>
>>   6   "The implementation shall document the overhead associated
>>        with calling machine-code or intrinsic subprograms, as
>>        compared to a fully-inlined call, and to a regular
>>        out-of-line call."
>>
>>
>>
>> Now in Ada 2005, RM 7.5 (1/2) states that a routine can not just copy
>> a "limited private" object. RM 6.5 (5.1/2, 5.c/2 ) states that if
>> the target is limited the function "must produce a ""new"" object"
>> instead of just copying the object.
>>
>> Aka the "Unchecked_Conversion" which is a generic function is no
>> longer just an inlined expression that is just a type conversions
>> with all checks being disable. The function must now return a "new"
>> object RM 6.5 (5.5/2, 5.c/2 ), by first requesting an new object
>> from the Target's storage pool and then copying the Source data to
>> that new object. So, in Ada 2005 the "Unchecked_Conversion" must be
>> handled as a true generic function with a true return, instead of a
>> built-in inline expression.
>>
>> But GNAT still just performs a simple copy. So, is GNAT or the RM
>> or is the generic "Unchecked_Conversion" function in error?
>
>You, of course. :-) Your language-lawyering skills need some work.
>
>13.9(12) (an implementation permission) says that an implementation can 
>return the result of an unchecked_conversion "by reference". Especially note 
>the second sentence of that rule, which explains the intent.
>
>                            Randy.
>
>
>
>
>
>




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-13  0:47                                     ` anon
@ 2011-05-13  0:58                                       ` Adam Beneschan
  2011-05-13  5:31                                       ` AdaMagica
  1 sibling, 0 replies; 31+ messages in thread
From: Adam Beneschan @ 2011-05-13  0:58 UTC (permalink / raw)


On May 12, 5:47 pm, a...@att.net wrote:
> --
> --  May be this program will help explain the problem.
> --
> --  Plus,
> --  RM 13.9 (12) -- say the function can copy "by reference, if the
> --  Source type is not a by-copy type." In Ada 2005, the definition
> --  of Source type for the Unchecked_Conversion is still a "limited
> --  private" which is a "Limited Type, and all Limited types (RM 7.5)
> --  are now a by-copy type.

Bzzzt!!  Please read 6.2.  If you're going to try be be a language
lawyer, you might want to consult the RM to find out what the terms
you use actually mean, rather than guessing.

                              -- Adam



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-13  0:47                                     ` anon
  2011-05-13  0:58                                       ` Adam Beneschan
@ 2011-05-13  5:31                                       ` AdaMagica
  1 sibling, 0 replies; 31+ messages in thread
From: AdaMagica @ 2011-05-13  5:31 UTC (permalink / raw)


On 13 Mai, 02:47, a...@att.net wrote:
> --
> --  May be this program will help explain the problem.
> --

(erased a lot of irrelevant stuff)

>   -- ------------------ --
>   --  Ada05_Conversion  --
>   -- ------------------ --
>   generic
>     type Source (<>) is limited private ;
>     type Target (<>) is limited private ;
>     function Ada05_Conversion ( S : Source ) return Target ;
>
>   function Ada05_Conversion ( S : Source ) return Target is
>
>       pragma Suppress ( All_Checks ) ;
>
>     begin
>       -- Compiling Error messages:
>       --   (Ada 2005) cannot copy object of a limited type
>       --              (RM-2005 6.5(5.5/2))
>       --   consider switching to return of access type
>       --
>       -- Additional References for reasoning:
>       --   RM 7.5 Limited Types ( 1/2, 1.a, 1.b/2 )
>       --
>       return Target ( S ) ;

What you are writing here is a normal type conversion with certain
rules (RM 4.6), not an unchecked type conversion (RM 13.9). For a type
conversion to be legal, the types involved have to be convertible.
Source and Target are not convertible, so this whole thing is illegal
for several reasons.

>     end Ada05_Conversion ;

RTFM



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-05-12 14:40                                     ` Adam Beneschan
@ 2011-05-14  0:30                                       ` Randy Brukardt
  0 siblings, 0 replies; 31+ messages in thread
From: Randy Brukardt @ 2011-05-14  0:30 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:20de6e7b-8b76-4d84-877b-714e794aa7c1@17g2000prr.googlegroups.com...
...
> It seems to be based on reading much more
> into certain language rules than is written there.

And ignoring the ones that are there. In a standard as large as Ada's, you 
can probably prove that unicorns exist that way...

                          Randy.





^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: A hole in Ada type safety
  2011-04-30 16:16   ` Florian Weimer
  2011-04-30 23:39     ` Randy Brukardt
@ 2011-05-14 23:47     ` anon
  1 sibling, 0 replies; 31+ messages in thread
From: anon @ 2011-05-14 23:47 UTC (permalink / raw)



AdaMagica: Some times a programmer may need a only a few checks 
suppressed instead of all checks as with the RM Unchecked_Conversion 
function. Then there's the idea of creating your own function just 
like some here will say create your own version of an Integer instead 
of using the one defined in the Standard package. Now, I have one 
simple designed Unchecked_Conversion function that work for any Ada 83 
compiler, and a second version that works for any Ada 95 compiler for 
all types used in that version of the language. Include a 
"unconstrained discriminant limited private" type.

Florian Weimer: My design converts all types and I did not need to use 
aliased or tag type to add the discriminant-dependent feature. Just  
play with it a little and you will see the answer.

Note: One thing. Any and all Unchecked_Conversion function just like 
Machine_Code Insertions adds a safety risk to the party. Plus, the 
conversion functions are easier to hide in a large scale project.

This all started because of an answer that "Robert Duff" gave about about 
AARM-3.7.2(4,4.a), which refers to AI83_00585 and "Erroneous Execution".
In looking at that Ada Issue I see only a compiler design error not an 
"Erroneous Execution" error. The fix is for the compiler to add either 
two or three checks in the elaborate code depending how the compiler 
evaluate the equation, which means no "Erroneous Execution". But in 
15 plus years GNAT has not correct this compiler identifiable error which 
makes me think how many more "Erroneous Execution" has GNAT and other
Ada venders skip fixing making the language less secure.

Also, I knew that Adam and Randy were just talk!!! Makes me think that 
they are waiting for someone to create an example of the "extended return
statement" so, they can learn how to use it. Because in looking at the 
AIs for 95 and 2005 and the ACVC 3.0 there is no example of an "extended 
return statement" for any "unconstrained discriminant limited private" 
except for those that call a function. But that not always possible.

In <87tydfbtp3.fsf@mid.deneb.enyo.de>, Florian Weimer <fw@deneb.enyo.de> writes:
>* Robert A. Duff:
>
>> Florian Weimer <fw@deneb.enyo.de> writes:
>>
>>> I don't know if this is a new observation---I couldn't find
>>> documentation for it.
>>
>> It's not new.  It is documented in AARM-3.7.2(4,4.a),
>> which dates back to Ada 83 days.
>
>Ah.  I didn't realize that call to Convert was already erroneous.
>
>It does not seem possible to extend the restrictions on 'Access
>prefixes to to subprogram parameters (due to the way controlled types
>are implemented, for example).
>
>>> 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.
>>
>> Yes.  Anything that is erroneous necessarily breaks type safety.
>> If you look up "erroneous execution" in the index, you'll find
>> them all.
>
>My concern was that this was not explicitly labeled as erroneous. 8-)
>
>> Your comment, "This note shows that a combination of safe-looking
>> language features can be used to undermine type safety, too."
>> is the key point.  It is indeed unfortunate when "safe-looking"
>> features can be erroneous.
>
>And once there is something like this in the language, it is difficult
>to decide if a new addition (such as aliased parameters) make things
>worse or not.




^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2011-05-14 23:47 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-30  8:41 A hole in Ada type safety Florian Weimer
2011-04-30 11:56 ` 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

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