Memory Safety
and theD Programming Language

by Walter Brightdlang.org

What's Hot●

1970s– Structured Programming

●

1980s
– User Friendly

●

1990s
– Object Oriented Programming●2000s– Generic/Meta Programming

And Now...

SECURITYhttps://krebsonsecurity.com/2016/10/hacked-cameras-dvrs-powered-todays-massive-internet-outage

Prediction

Memory safety will become a requirement forprogramming languages

Memory Safety“a concern in software development that aims toavoid software bugs that cause security
vulnerabilities dealing with random-accessmemory (RAM) access, such as buffer overflows
and dangling pointers”

https://en.wikipedia.org/wiki/Memory_Safetya.k.a.

Pointers Gone Wild!

The Usual Suspects●

Buffer overflow●

Pointer arithmetic●

Uninitialized pointers●Casting●

Misaligned pointers●

Pointers to expired stack frames●

Dangling pointersBuffer Overflow

int[10] a;for (size_t i = 0; i <= 10; ++i)a[i] = …;

Solution●arrays do not decay to pointers– array dimension is carried with it●

runtime array bounds checking

Arrays Look Likestruct Array{size_t length;
T* ptr;}Pointer Arithmetic

int[10] a;
int* p = &a[0];for (size_t i = 0; i <= 10; ++i)p[i] = …;Lost the array bounds checking

Solution

Pointer arithmetic is not allowedUninitialized Pointers

int p;…
*p = …;Solution

Default initialize to null

Uninitialized Pointers 2
struct S{
int i;
char* p;this(int x) { this.i = x; }}S s = S(3);*s.p = …; // error, p not initializedSame Solution

Default initialize the fields

No Initialization

S s = void;(But not allowed in @safe code)

Casting

int* p = cast(int*) 1234; // error
int i = cast(int) p;// okUnionsunion U{
int* p;int i;}U u;
u.i = 1234;
int* p = u.p; // error

Size Casts

char* pc;
byte* pb = cast(byte*) pc; // ok
int* pi = cast(int*) pc;// nopeMisaligned Pointersstruct S{align (1):byte b;
int i;}
S s;
int* p = &s.i; // error

Pointers To Expired Stack Frames

int* foo(){
int i;
return &i; // error}

Easily Defeated
int* foo(){int i;int* p = &i;return p;}

Using ref Instead●

ref is a restricted pointer– can only use ref for parameters/returns– no arithmetic– no escaperef int foo(){int i;
ref int p = i; // not allowed!
return p;}

But Need Identity Function

ref int foo(ref int i){return i;}Leading To
ref int foo(ref int i){return i;}
ref int bar(){int i;return foo(i); // uh-oh!
}Introducing return ref
ref int foo(return ref int i){return i;}
ref int bar(){
int i;
int j = foo(i); // ok
return foo(i); // error}

Back To Pointers
int* foo(int* i){return i;}
int* bar(){
int i;return foo(&i); // boom!
}

Introducing scope
void abc(int*);
int* q;int* foo(scope int* p, int** pp){abc(p); // error
q = p;// nope*pp = p; // nice try
return p; // no way}

Locals Can Be scope

void foo(scope int* p){
scope int* q = p; // ok
int* s = p; // ok, scope is inferred}int j;scope int* p;
int i;
p = &j; // ok
p = &i; // error
p = c ? &i : &j; // error

More Inference

void foo( )(int* p){*p = 3;// 'p' is inferred as scope}

Lambdas too

return scope Like return refint* foo(return scope int* p) {return p;}
int* bar(int* q) {int i;*foo(&i) = 3; // ok
return foo(q); // ok
return foo(&i); // error}

What About●

dynamic arrays– ptr / length pair●delegates– ptr / funcptr pair●this– ptr or ref

Dangling Pointers

int* p = cast(int*) malloc(5 * int.sizeof);…
free(p);*p = 3; // Boom!

“Oh I don't think there's anything in that black bag for me.” – Dorothy

Containers●

Use RAII (scoped destruction)●

prevent general escape of pointers●

use return scope and return ref

But still some work to be done

Conclusion●

wild pointers can be corralled●

simple annotations are possible●

many (most?) annotations can be inferred●system code still allowedhttp://dlangcomicstrips.tumblr.com