This is not the current version of the class.

Data representation 5: Integers and undefined behavior

Overview

We explore integer representations and introduce integer undefined behavior.

Readings on undefined behavior

Integer types

Multi-byte integers

int x = 258;
hexdump_object(x);

// => 7ffeea26fac8  02 01 00 00                                       |....|

Overflow in computer arithmetic

unsigned char n = 255;   // range representable in `n` is [0,255]
n = n + 1;               // `n` should be 256, but can’t be represented

unsigned u = 1'000'000;  // range representable in `u` is [0,4'294'967'295]
u = u * 10'000'000;      // `n` should be 10'000'000'000'000,
                         // but can’t be represented

Unsigned integer overflow

unsigned char n = 255;
n = n + 1;

unsigned u = 1'000'000;
u = u * 10'000'000;

printf("n=%u, u=%u\n", (unsigned) n, u);
// => n=0, u=1316134912
  255 =  0b1111'1111
+   1 =  0b0000'0001
       -------------
       0b1'0000'0000
    =>   0b0000'0000 = 0
     1'000'000 =              0b1111'0100'0010'0100'0000
*   10'000'000 =         0b1001'1000'1001'0110'1000'0000
--------------------------------------------------------
0b1001'0001'1000'0100'1110'0111'0010'1010'0000'0000'0000
=>             0b0100'1110'0111'0010'1010'0000'0000'0000 = 1316134912

Unsigned arithmetic overflow, mathematically

The mystery of negative numbers

Negatives and overflow

Two’s complement representation

Signed overflow: here be dragons

The upside down

Undefined behavior and abstract machine

Broad-brush model of programmer psychology

People want their code to:

Priority 1. Work relatively correctly on most inputs

Priority 2. Run fast

Priority 3. Work exactly correctly on all inputs

Why?

Compiler quality

The as-if rule

Undefined behavior

How undefined behavior and optimizing compilers collide

Signed integer overflow is undefined behavior

Example 1: Signed integer overflow

int x_incr = x + 1;
assert(x_incr > x);
printf("assertion passed, so %d > %d\n", x_incr, x);

Sanitizer to the rescue

$ make SAN=1 signedoverflow
...
$ ./signedoverflow 2147483647
signedoverflow.cc:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'

Example 2: Null pointer dereference

static void __devexit agnx_pci_remove (struct pci_dev *pdev)
{
  struct ieee80211_hw *dev = pci_get_drvdata(pdev);
  struct agnx_priv *priv = dev->priv; 

  if (!dev) return;

Example 3: Signed integer overflow in a loop

long sum = 0;
for (int i = n1; i <= n2; ++i) {
    sum += f(i);
}
return sum;

Example 4: Out-of-bounds access

int awesome[4] = {0, 1, 2, 3};

bool is_awesome(int v) {
    for (int i = 0; i <= 4; ++i) {
        if (awesome[i] == v)
            return true;
    }
    return false;
}

More examples of undefined behaviors