UndefinedBehaviorSanitizer (GNAT User’s Guide for Native Platforms)

#### 6.8.2 UndefinedBehaviorSanitizer ¶

UndefinedBehaviorSanitizer (aka UBSan) modifies the program at compile-time to catch various kinds of undefined behavior during program execution.

Different sanitize options (`-fsanitize=alignment,float-cast-overflow,signed-integer-overflow`) detect the following types of problems:

- Wrong alignment

  The `-fsanitize=alignment` flag (included also in `-fsanitize=undefined`) enables run-time checks for misaligned memory accesses, ensuring that objects are accessed at addresses that conform to the alignment constraints of their declared types. Violations may lead to crashes or performance penalties on certain architectures.

  In the following example:

  >     with Ada.Text_IO; use Ada.Text_IO;
  >     with System.Storage_Elements; use System.Storage_Elements;

  >     procedure Misaligned_Address is
  >        type Aligned_Integer is new Integer with
  >          Alignment => 4;  -- Ensure 4-byte alignment

  >        Reference : Aligned_Integer := 42;  -- Properly aligned object

  >        -- Create a misaligned object by modifying the address manually
  >        Misaligned : Aligned_Integer with Address => Reference'Address + 1;

  >     begin
  >        -- This causes undefined behavior or an alignment exception on strict architectures
  >        Put_Line ("Misaligned Value: " & Aligned_Integer'Image (Misaligned));
  >     end Misaligned_Address;

  If the code is built with the `-fsanitize=alignment` and `-g` options, the following error is shown at execution time.

  >     misaligned_address.adb:15:51: runtime error: load of misaligned address 0xffffd836dd45 for type 'volatile misaligned_address__aligned_integer', which requires 4 byte alignment

- Signed integer overflow

  Ada performs range checks at runtime in arithmetic operation on signed integers to ensure the value is within the target type’s bounds. If this check is removed, the `-fsanitize=signed-integer-overflow` flag (included also in `-fsanitize=undefined`) enables run-time checks for signed integer overflows.

  In the following example:

  >     procedure Signed_Integer_Overflow is
  >        type Small_Int is range -128 .. 127;
  >        X, Y, Z : Small_Int with Export;
  >     begin
  >        X := 100;
  >        Y := 50;
  >        -- This addition will exceed 127, causing an overflow
  >        Z := X + Y;
  >     end Signed_Integer_Overflow;

  If the code is built with the `-fsanitize=signed-integer-overflow` and `-g` options, the following error is shown at execution time.

  >     signed_integer_overflow.adb:8:11: runtime error: signed integer overflow: 100 + 50 cannot be represented in type 'signed_integer_overflow__small_int'

- Float to integer overflow

  When converting a floating-point value to an integer type, Ada performs a range check at runtime to ensure the value is within the target type’s bounds. If this check is removed, the sanitizer can detect overflows in conversions from floating point to integer types.

  In the following code:

  >     procedure Float_Cast_Overflow is
  >        Flt : Float := Float'Last with Export;
  >        Int : Integer;
  >     begin
  >        Int := Integer (Flt); --  Overflow
  >     end Float_Cast_Overflow;

  If the code is built with the `-fsanitize=float-cast-overflow` and `-g` options, the following error is shown at execution time.

  >     float_cast_overflow.adb:5:20: runtime error: 3.40282e+38 is outside the range of representable values of type 'integer'