What is Type Safety?
Type safe means preventing programs from accessing memory outside the bounds of an object’s public properties A programming language is type safe when the language defines the behavior for when the programmer treats a value as a type to which it does not belong. Type safety requires that well-typed programs have no unspecified behavior (i.e., their semantics are complete). Languages such as C and C++, which allow programmers to access arbitrary memory locations, are not type safe. An unsafe programming language supports operations (such as accessing arbitrary memory locations), which are not defined in terms of the language semantics. Type safety is a property of the programming language, and not of the programs themselves.
How does Type Safety affect us?
1) Type-safe code accesses only the memory locations it is authorized to access.
2) For example, type-safe code cannot directly read values from another object’s private fields or code areas.
3) It accesses types only in well-defined, allowable ways, thereby preventing overrun security breaches.
4) Type safety helps isolate objects from each other and therefore helps protect them from inadvertent or malicious corruption.
5) It also provides assurance that security restrictions on code can be reliably enforced.
Why is Type Safety Important?
1) Type-safety is important for assembly isolation and security enforcement.
2) When code is type- safe, the common language runtime can completely isolate assemblies from each other.
3) This isolation helps ensure that assemblies cannot adversely affect each other and it increases application reliability.
4) Type-safe components can execute safely in the same process even if they are trusted at different levels.
Writing Type-Safe Code
Type-safe code is code that accesses types only in well-defined, allowable ways. Given a valid object reference, type-safe code can access memory at fixed offsets corresponding to actual field members. However, if the code accesses memory at arbitrary offsets outside the range of memory that belongs to that object’s publicly exposed fields, it is not type-safe.
How is Type Safety ensured?
The Common Language runtime manages code at execution time. It provides core services such as ‘memory management’, ‘thread management’ and remoting. It also enforces strict type safety and promotes security and robustness.
1) During just-in-time compilation, an optional verification process examines the metadata and intermediate language of a method to verify that they are type-safe.
2) If the code has permission to bypass verification, then this process is skipped.
3) The common language runtime manages code at execution time, providing core services such as memory management, thread management, and remoting, and enforces strict type safety and other forms of code accuracy that promote security and robustness.
intY = dblX; / / this causes an Error
What is Verifiable Type Safe Code?
JIT compilation performs a process called verification that examines code and attempts to determine whether the code is type-safe.
Code that is proven during verification to be type-safe is called verifiably type- safe code.
Code can be type-safe, yet not be verifiably type-safe, due to the limitations of the verification process or of the compiler. Not all languages are type-safe, and some language compilers cannot generate verifiably type-safe managed code.
As part of compiling MSIL to native code, code must pass a verification process unless an administrator has established a security policy that allows code to bypass verification. Verification examines MSIL and metadata to find out whether the code is type safe, which means that it only accesses the memory locations it is authorized to access. The runtime relies on the fact that the following statements are true for code that is verifiably type safe:
a) A reference to a type is strictly compatible with the type being referenced
b) Only appropriately defined operations are invoked on an object
c) Identities are what they claim to be.
During the verification process, MSIL code is examined in an attempt to confirm that the code can access memory locations and call methods only through properly defined types.
Additionally, verification inspects code to determine whether the MSIL has been correctly generated, because incorrect MSIL can lead to a violation of the type safety rules. The verification process passes a well-defined set of type-safe code, and it passes only code that is type safe. However, some type-safe code might not pass verification because of limitations of the verification process, and some languages, by design, do not produce verifiably type-safe code. If type-safe code is required by security policy and the code does not pass verification, an exception is thrown when the code is run.
Tools: How to determine if the code is type safe?
Some language compilers generate verifiably type-safe code only when you avoid certain language constructs. The .NET Framework SDK PEVerify tool can be used to determine whether the code is verifiably type-safe.
What can happen if the Code is not verifiably type safe?
1) When code is not type-safe, unwanted side effects can occur.
2) The runtime cannot prevent unsafe code from calling into native (unmanaged) code and performing malicious operations.
3) When code is type-safe, the runtime’s security enforcement mechanism ensures that it does not access native code unless it has permission to do so.