Rationale for Ada 2012
6.5 Restrictions
Restrictions provide a valuable way of increasing
security. Ada is a rich language and even richer with Ada 2012 and although
individual features are straightforward, certain combinations can cause
problems.
The new restrictions introduced into Ada 2012 have
already been described in this or earlier chapters such as the Introduction
(see
1.3.5). However, for convenience
here is a complete list giving the annex where appropriate.
The new Restrictions
identifiers are
No_Access_Parameter_Allocators High-Integrity
No_Anonymous_Allocators High-Integrity
No_Coextensions High-Integrity
No_Implementation_Aspect_Specifications
No_Implementation_Identifiers
No_Implementation_Units
No_Specification_Of_Aspect
No_Standard_Allocators_After_Elaboration Real-Time
No_Use_Of_Attribute
No_Use_Of_Pragma
Some of the new Restrictions
identifiers are in the High-Integrity annex. They are
pragma Restrictions(No_Access_Parameter_Allocators);
pragma Restrictions(No_Anonymous_Allocators);
pragma Restrictions(No_Coextensions);
and these were discussed in the previous section.
In a similar vein there
is one new restriction in the Real-Time annex, namely
pragma Restrictions(No_Standard_Allocators_After_Elaboration);
and this was also discussed in the previous section.
A number of restrictions
prevent the use of implementation-defined features. They are
pragma Restrictions(No_Implementation_Aspect_Specifications);
pragma Restrictions(No_Implementation_Identifiers);
pragma Restrictions(No_Implementation_Units);
These do not apply to the whole partition but only
to the compilation or environment concerned. This helps us to ensure
that implementation dependent areas of a program are identified. They
were discussed in the Introduction (see
1.3.5)
and join similar restrictions
No_Implementation_Attributes
and
No_Implementation_Pragmas introduced in
Ada 2005.
The restrictions on implementation-defined aspect
specifications, attributes and pragmas are obvious but some clarification
of what is meant by the restrictions on units and identifiers might be
helpful.
It will be recalled that the predefined packages
are Ada, System
and Interfaces plus various children. In the
so-called standard mode, implementations are not permitted to add their
own child packages of Ada but can add grandchildren.
Thus an implementation might add an additional container package called
perhaps Ada.Containers.Slopbucket. If a program
were to use this grandchild then clearly it would be unlikely to be portable
to other implementations. Accordingly, giving the restriction No_Implementation_Units
prevents such potential difficulties. Similarly, this restriction prevents
the use of implementation-defined child units of System
and Interfaces.
The restriction No_Implementation_Identifiers
is more subtle. It will be recalled that several predefined packages
are permitted to add implementation-defined identifiers. They are
Standard,
System,
Ada.Command_Line,
Interfaces.C,
Interfaces.C.Strings,
Interfaces.C.Pointers,
Interfaces.COBOL,
and Interfaces.Fortran.
Moreover, the following
predefined packages only contain implementation-defined identifiers
Interfaces,
System.Machine_Code,
Ada.Directories.Information,
Ada.Directories.Names,
and the packages Implementation nested in the queue containers.
The restriction No_Implementation_Identifiers
prevents the use of any of these.
There is a slight subtlety regarding Long_Integer
and Long_Float in Standard.
The types Integer and Float
must be provided. Types such as Short_Integer
and Long_Long_Float may be provided but are
definitely considered to be implementation-defined and so excluded by
the restriction on implementation identifiers. However, Long_Integer
and Long_Float should be provided (if the
hardware is capable) and so are considered to be predefined and not covered
by the restriction. Nevertheless, an implementation on a specialized
small machine might not provide them.
Finally, there are
restrictions preventing the use of particular facilities
pragma Restrictions(No_Specification_Of_Aspect => X);
pragma Restrictions(No_Use_Of_Attribute => X);
pragma Restrictions(No_Use_Of_Pragma => X);
where X is the name of
a specific aspect, attribute or pragma respectively. They are similar
to the restriction No_Dependence introduced
in Ada 2005. They apply to a complete partition.
Note that No_Specification_Of_Aspect
prevents the specification of an aspect by any means. Remember that some
aspects can be specified by an aspect specification or by a pragma or
by an attribute definition clause. Thus we mentioned above that a storage
pool could be given by an attribute definition clause thus
type Cell_Ptr is access Cell;
for Cell_Ptr'Storage_Pool use Cell_Ptr_Pool;
or by using an aspect
specification thus
type Cell_Ptr is access Cell
with Storage_Pool => Cell_Ptr_Pool;
Writing
pragma Restrictions(No_Specification_Of_Aspect => Storage_Pool);
prevents both of these
whereas
pragma Restrictions(No_Use_Of_Attribute => Strorage_Pool);
prevents only the first. Naturally, No_Use_Of_Attribute
prevents both setting an attribute and reading it whereas No_Specification_Of_Aspect
prevents just setting it. Thus we might want to read 'Size
but prevent setting it.
Similarly
pragma Restrictions(No_Specification_Of_Aspect => Pack);
prevents both
type Flags is array (1 .. 8) of Boolean
with Pack;
and
type Flags is array (1 .. 8) of Boolean;
pragma Pack(Flags);
whereas
pragma Restrictions(No_Use_Of_Pragma => Pack);
prevents only the latter.
In summary, No_Specification_Of_Aspect
does not mean No_Aspect_Specification (which
does not exist).
Remember that several
restrictions can be given in one pragma, so we might have
pragma Restrictions(No_Use_Of_Pragma => P,
No_Use_Of_Attribute => A);
As mentioned in the
Introduction (see
1.3.5) there is also
a new profile
No_Implementation_Extensions.
This is specified by
pragma Profile(No_Implementation_Extensions);
and is equivalent to
writing
pragma Restrictions(
No_Implementation_Aspect_Specifications,
No_Implementation_Attributes,
No_Implementation_Identifiers,
No_Implementation_Pragmas,
No_Implementation_Units);
thus providing blanket security against writing programs
that use language extensions. This profile is defined in the core language.
The only other profile defined in Ada 2012 is
Ravenscar
which was introduced in Ada 2005 and is in the Real-Time systems annex.
Remember that the pragma
Profile is a configuration
pragma.
Finally, those of a
recursive nature might note that writing
pragma Restrictions(No_Use_Of_Pragma => Restrictions);
is illegal (this prevents the risk that the compiler
might melt down). More curiously, there is not a restriction No_Implementation_Restrictions.
This might be because of similar concern regarding what would happen
with its recursive use.
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by: