Millions of lines of C code uses things that the spec doesn’t allow and it works because compilers can’t really do all the things that the spec allows without breaking real code. That confirms my understanding, not yours.
Conversation
Sure, and most C code is full of memory corruption bugs even including lots of latent memory corruption that occurs in regular usage rather than just edge cases (like an exploit). I'm well aware that real world C code is filled with lots of undefined behavior. It hinders my work.
1
That's not how undefined behavior is defined. That's your own definition, and it's not clear to me how your definition is meant to work. For example, you seem okay with uninitialized memory from malloc changing value, but yet not local variables, which is very arbitrary.
1
Since you want to permit out-of-bounds accesses, you want to forbid real world partial / full memory safety implementations that are being deployed. You would even forbid _FORTIFY_SOURCE, not just -fsanitize=object-size. Another good example would be function pointer typing.
1
The C standard forbids calling a function pointer that has a mismatched type with the function. So for example, calling a function `void foo(char *)` via `void (*foo)(void *)` is undefined. This is what type-based Control Flow Integrity (CFI) enforces to mitigate exploitation.
1
That's the reality of C. People use implementations including runtime optimizations like MADV_FREE and assorted mitigations that enforce subsets of type and memory safety. There are also implementations without a fixed stack, with garbage collection, etc. It permits all this.
1
It's a large part of why people use C in the first place. It's extremely portable and permits all kinds of different implementations. It can be compiled to the JVM with GC or WebAssembly. It supports architectures with different kinds of stacks or without traditional stacks, etc.
1
When an architecture / platform introduces a change like using shadow stacks (Intel CET, LLVM ShadowCallStack) to protect control flow, it's broadly compatible, because C doesn't permit programs to make all kinds of assumptions about how the stack and function calls work.
2
So? I'm not proposing to exhaustively define how the stack works. It's necessary to say that: (A) the runtime will give you a stack that doesn't overlap with other allocated memory and (B) where any local goes on the stack (if at all) is up to the compiler.
1
So how do you deal with the architecture / platform using tagged pointers that enforce access restrictions, like not being able to access outside of a stack frame with a pointer to that stack frame? You've said you want to permit out-of-bounds accesses, which is incompatible.
Yeah that would be incompatible with that hardware. So what?
1
By the way that hardware is incompatible with JavaScriptCore so it wouldn’t be able to run type-safe languages like JavaScript. It seems that that hardware is incompatible with reality.
1
Show replies

