This page explaines the memory safety issues of C++ and (to a minor degree) Java
All of these problems can potentially lead to "mysterious" behaviour of a C or C++ program and all of them can potentially be used by an attacker to inject malware into a running process. Data can be exfiltrated, manipulated and deleted. If the process controls a machine, process or vehicle, material, human and environmental damage can result.
None of the above issues exist in Sappeur, due to the type system.
The following C++ program will usually crash, as the heap is being damaged. An equivalent Sappeur program would fail at compile time, until the global_string object is declared as multithreaded. This will insert a Mutex into the object and serialize all thread-global method calls to the object, using the Mutex.
#include#include using namespace std; ::std::string global_string; void* threadFunctionA(void* a) { for(int i=0; i < 1000000; i++) { global_string.append("Wolf"); } return NULL; } void* threadFunctionB(void* a) { for(int i=0; i < 1000000; i++) { global_string.append("Lynx"); } return NULL; } int main() { pthread_t T1, T2; pthread_create(&T1,NULL,threadFunctionA,NULL); pthread_create(&T2,NULL,threadFunctionB,NULL); pthread_join(T1,NULL); pthread_join(T2,NULL); } Compile with $ g++ -Wall -pthread P6.cpp on Unix.
In the real programing world, this kind of "accidental unsafe sharing" can easily happen, especially if complex libraries and data structures are shared between threads.
The following program will update the global counter in non deterministic ways. Each run will generate a different, usually wrong, result. The same problem exists for all languages(Go, Java, C, C++, Swift and many more) which do not have full multithreading support in their type system. Real-world programs contain this type of bug very often in deeply nested data structures, making their manual detection difficult.
class ConcurThread extends Thread { public void run() { try { for(int i=0; i < 10000000; i++) { MTBug.counter++; } } catch(Exception e) { System.out.println("Exception is caught in ConcurThread.run()"); } } } class MTBug { public static int counter; public static void main(String[] args) { try { counter = 0; ConcurThread threads[] = new ConcurThread[20]; for(int i=0; i < threads.length; i++) { threads[i] = new ConcurThread(); threads[i].start(); } for(int i=0; i < threads.length; i++) { threads[i].join(); } System.out.println("counter = " + counter ); } catch(Exception e) { System.out.println("Exception is caught in MTBug.main()"); } } }
Memory Safe Sappeur program of the above:
AppMain.ad:
class MT_String multithreaded { String_16 str_single_threaded; int counter; methods: MT_String(); external void append(&char anotherString[]); external void threadMain(); external void print(); }; class ThreadClass multithreaded { methods: external void threadMain(); }; class Main { static MT_String* global_string; methods: static void append(&char another_string[]); int main(); };
AppMain.ai
class MT_String multithreaded { String_16 str_single_threaded; int counter; methods: MT_String(); external void append(&char anotherString[]); external void threadMain(); external void print(); ~MT_String(); }; class ThreadClass multithreaded { methods: external void threadMain(); }; class Main { static MT_String* global_string; methods: static void append(&char another_string[]); int main(); int main_inner(); };
AppMain.ai
MT_String::MT_String(){counter = 0;} void MT_String::append(&char anotherString[]) { //generated C++ will do pthread_mutex_lock(&_pmutex); str_single_threaded.append(anotherString); counter++; //generated C++ will do pthread_mutex_ulock(&_pmutex); } MT_String::~MT_String() { str_single_threaded.clear(); } void MT_String::threadMain() {} void ThreadClass::threadMain() { for(var int i=0; i < 1000000; i++) { Main::append("Luchs"); } } void MT_String::print() { var PrintfClass pfc; pfc.fstr("counter = $").sa(counter).pr(); } void Main::append(&char str[]) { global_string.append(str); } int Main::main() { return this.main_inner(); } int Main::main_inner() { global_string = new MT_String; var ThreadClass* T1 = new ThreadClass; var ThreadClass* T2 = new ThreadClass; var ThreadInfo* ti1 = new ThreadInfo; var ThreadInfo* ti2 = new ThreadInfo; createThread(T1,ti1); createThread(T2,ti2); ti1.join(); ti2.join(); global_string.print(); T1 = NULL; T2 = NULL; ti1 = NULL; ti2 = NULL; return 1; }