Extraordinary project. I had several questions which I believe I have answered for myself (pizlonator please correct if wrong):
1. How do we prevent loading a bogus lower through misaligned store or load?
Answer: Misaligned pointer load/stores are trapped; this is simply not allowed.
2. How are pointer stores through a pointer implemented (e.g. `*(char **)p = s`) - does the runtime have to check if *p is "flight" or "heap" to know where to store the lower?
Answer: no. Flight (i.e. local) pointers whose address is taken are not literally implemented as two adjacent words; rather the call frame is allocated with the same object layout as a heap object. The flight pointer is its "intval" and its paired "lower" is at the same offset in the "aux" allocation (presumably also allocated as part of the frame?).
3. How are use-after-return errors prevented? Say I store a local pointer in a global variable and then return. Later, I call a new function which overwrites the original frame - can't I get a bogus `lower` this way?
Answer: no. Call frames are allocated by the GC, not the usual C stack. The global reference will keep the call frame alive.
That leads to the following program, which definitely should not work, and yet does. ~Amazing~ Unbelievable:
#include <stdio.h>
char *bottles[100];
__attribute__((noinline))
void beer(int count) {
char buf[64];
sprintf(buf, "%d bottles of beer on the wall", count);
bottles[count] = buf;
}
int main(void) {
for (int i=0; i < 100; i++) beer(i);
for (int i=99; i >= 0; i--) puts(bottles[i]);
}
Hmmm ... there's a danger here that people will test their programs compiled with Fil-C and think that they are safe to compile with a "normal" compiler. I would hope for an option to flag any undefined behavior.
1. How do we prevent loading a bogus lower through misaligned store or load?
Answer: Misaligned pointer load/stores are trapped; this is simply not allowed.
2. How are pointer stores through a pointer implemented (e.g. `*(char **)p = s`) - does the runtime have to check if *p is "flight" or "heap" to know where to store the lower?
Answer: no. Flight (i.e. local) pointers whose address is taken are not literally implemented as two adjacent words; rather the call frame is allocated with the same object layout as a heap object. The flight pointer is its "intval" and its paired "lower" is at the same offset in the "aux" allocation (presumably also allocated as part of the frame?).
3. How are use-after-return errors prevented? Say I store a local pointer in a global variable and then return. Later, I call a new function which overwrites the original frame - can't I get a bogus `lower` this way?
Answer: no. Call frames are allocated by the GC, not the usual C stack. The global reference will keep the call frame alive.
That leads to the following program, which definitely should not work, and yet does. ~Amazing~ Unbelievable: