This came up when when I was reading the section of RM22 on accessibility levels (3.10.2) and then trying to use GNAT to confirm my understanding. GNAT does not agree with my understanding, however I believe this is a GNAT bug rather than a hole in my understanding or a hole in the RM. I’d appreciate if someone more familiar with the rules in 3.10.2 could check that my reasoning here is correct. @sttaft perhaps as the only ARG member that is active here as far as I know.
Take the below program:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Ordered_Maps;
procedure Example is
type R is record
X : aliased Integer;
end record;
package R_Maps is new Ada.Containers.Ordered_Maps (Positive, R);
M : R_Maps.Map := [1 => (X => 1)];
type Integer_Access is access all Integer;
A : Integer_Access := M (1).X'Access;
-- An explicit `.Element` also triggers the bug.
begin
Put_Line (A.all'Image);
M.Clear;
Put_Line (A.all'Image);
M.Insert (1, R'(X => 2));
Put_Line (A.all'Image);
end Example;
This will show a use-after-free when running with Valgrind. Notably this program is accepted both when using No_Dynamic_Accessibility_Checks and when not using it.
This program should not be accepted by a conforming Ada compiler for the following reasons:
RM22 7.6.1(3/5) states that “… in the case of the execution of a master construct: a body other than a package_body; a statement; or an expression …”
The initialiser for A here is an expression.
RM22 3.10.2(18/5) states that “For a master construct that is statically nested within another master construct, the accessibility level of the inner master construct is statically deeper than that of the outer master construct.”
This means that the accessibility level of initialiser for A is deeper than the declarative region of Example.
RM22 3.10.2(12.5/3) states that “The accessibility level of the anonymous access type of an access discriminant in any other context is that of the enclosing object.”
The enclosing object here is the temporary Reference_Type object created within the initialiser of A, therefore the accessibility level of the temporary Reference_Type object is that of the initialiser of A.
RM22 4.1.5(6/3) states that “A generalized_reference denotes a view equivalent to that of a dereference of the reference discriminant of the reference object.”
RM22 3.10.2(28/3) states in regards to X’Access that “The accessibility level of the view shall not be statically deeper than that of the access type A.”
Therefore the assignment should be invalid.