3

I was recently asked in the following question in an interview: "What are all the possible ways to achieve memory safety while writing C code?"

I replied about secure versions of APIs. The interviewer said that there are more approaches than that. I want to ask what is the list of ways to achieve memory safety.

Mecki
  • 125,244
  • 33
  • 244
  • 253
Jake
  • 16,329
  • 50
  • 126
  • 202
  • 3
    IMHO, the question itself is already faulty, as the word **all** implies that there exists an upper bound and all possible methods are already known as of today. It's like asking someone to list all possible colors. – Mecki Feb 06 '21 at 22:56
  • 2
    You could talk volumes about error checking, bounds checking, punning, aliasing and so on. But, given it was an interview, maybe the real point was to see how you tactfully answer a silly/impossible question. – dxiv Feb 06 '21 at 23:06
  • The easy way is quite simple: don't use pointers, arrays, or recursion. – Mark Feb 07 '21 at 05:49
  • 1
    ;-) There is just one countable rule, _know **exactly** what you are doing and eliminate all unsafe operations._ @Mark You forgot casts and `scanf()`, at least. – the busybee Feb 08 '21 at 08:22
  • @thebusybee, scanf requires pointers, and I think all the unsafe casts also require pointers. – Mark Feb 09 '21 at 02:13
  • @Mark Hm, what about `unsigned char uc; (unsigned long)uc = 23UL;`, even if it is non-compliant. Actually I saw this kind of cast in safety related production code. =-O If you lower the warning level and/or ignore warnings, you can even call `scanf("%s", 0x314159);` and no (obvious) pointer is involved. -- But here we are entering the area of "war stories"... ;-) – the busybee Feb 09 '21 at 07:21
  • @thebusybee, GCC throws an error (not a warning) if you assign to a numeric cast: `:3:19: error: assignment to cast is illegal, lvalue casts are not supported`. – Mark Feb 09 '21 at 20:55
  • @Mark That's right, and that's another reason (beside of code review) how I found this error when I attempted to test this legacy code. For the target system another non-GCC compiler system had to be used. And that accepted this cast. – the busybee Feb 09 '21 at 21:30

1 Answers1

3
  • NULL out pointers always when freeing memory to avoid Use-After-Free bugs and double free bugs
  • Always perform bound check to avoid OOB (Out-Of-Bounds) read and OOB write vulnerabilities
  • Try not to use recursion, or just use it when knowing your limits, so preventing Stack Exhaustion and Heap Exhaustion vulnerabilities
  • If you suspect a pointer could be NULL at any time, check it always before using it to avoid NULL pointer dereference vulnerabilities
  • Use multi-thread hardening mechanisms to avoid race conditions leading to memory-safety bugs
  • Initialize always pointers and variables, specially if they are going to be used / accessed without prior value assignment
  • Always ensure a string is properly NULL-terminated, to avoid memory leaks and other memory safety issues
  • Be sure copying functions, specially when using loops, are properly designed not to surpass one byte into a subsequent buffer or variable (off-by-one vulnerability)
  • Carefully select types and casts to avoid problems like integer overflows

and a lot more...

  • Some say that you should avoid NULLing freed pointers to avoid double free bugs, because if there is one it is a bug and should be fixed. – SherAndrei May 13 '21 at 23:05
  • Well, for UAF bugs NULLing it out will end up on a segmentation fault crash, so easier to detect. When talking about double free bugs, free() functions usually return if provided pointer is NULL. You can trace those situations, or disable the pointer NULLing when debugging. But for security reasons on production code it is always better a crash (most times not exploitable) than a higher risk bug like a double free is. –  May 14 '21 at 08:07