From c12fa4fdadf3d6a8f5ef9ed178140c3018d12cb8 Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Sat, 1 Feb 2025 10:06:27 +0900 Subject: [PATCH] be more pedantic about correct types in pointer initialisation and assignment unless the value is (void *)0 --- demofiles/memory-leak.c | 2 +- demofiles/multiple-free.c | 10 ++--- demofiles/use-after-free.c | 19 ++++----- main.leg | 82 ++++++++++++++++++++++++++++++++------ 4 files changed, 85 insertions(+), 28 deletions(-) diff --git a/demofiles/memory-leak.c b/demofiles/memory-leak.c index fc7d634..3cfcd13 100644 --- a/demofiles/memory-leak.c +++ b/demofiles/memory-leak.c @@ -6,7 +6,7 @@ int main() { for (int i = 0; i < 10; ++i) { - int *ptr = malloc(sizeof(*ptr)); + int *ptr = (int *)malloc(sizeof(*ptr)); assert(ptr != 0); printf("%p\n", ptr); *ptr = i; diff --git a/demofiles/multiple-free.c b/demofiles/multiple-free.c index e72a524..a293b06 100644 --- a/demofiles/multiple-free.c +++ b/demofiles/multiple-free.c @@ -5,9 +5,9 @@ #include int main() { - int *ptr = malloc(sizeof(*ptr)); - assert(ptr != 0); - free(ptr); printf("%p\n", ptr); - free(ptr); printf("%p\n", ptr); - return 0; + int *ptr = (int *)malloc(sizeof(*ptr)); + assert(ptr != 0); + free(ptr); printf("%p\n", ptr); + free(ptr); printf("%p\n", ptr); + return 0; } diff --git a/demofiles/use-after-free.c b/demofiles/use-after-free.c index 3dbb372..d118d5a 100644 --- a/demofiles/use-after-free.c +++ b/demofiles/use-after-free.c @@ -5,13 +5,14 @@ #include int main() { - int *ptr = malloc(sizeof(*ptr)); - assert(ptr != 0); - *ptr = 42; - printf("%d\n", *ptr); - free(ptr); - printf("%d\n", *ptr); // use after free - *ptr = 43; // use after free - printf("%d\n", *ptr); // use after free - return 0; + int *ptr = (int *)malloc(sizeof(*ptr)); + assert(ptr != 0); + *ptr = 42; + printf("%p %d\n", ptr, *ptr); + free(ptr); + printf("%p %d\n", ptr, *ptr); // use after free + // the following usully causes a SEGV in the interpreter because the store corrupts GC memory + *ptr = 43; // use after free + printf("%p %d\n", ptr, *ptr); // use after free + return 0; } diff --git a/main.leg b/main.leg index af69313..dabe814 100644 --- a/main.leg +++ b/main.leg @@ -1,6 +1,6 @@ # main.leg -- C parser + interpreter # -# Last edited: 2025-02-01 08:55:52 by piumarta on xubuntu +# Last edited: 2025-02-01 10:02:43 by piumarta on xubuntu %{ ; @@ -1068,13 +1068,13 @@ oop toStringOn(oop obj, oop str) oop base = get(obj, Pointer,base); switch (getType(base)) { case Integer: - String_format(str, "<%p", (void *)(intptr_t)_integerValue(base)); + String_format(str, "<%s %p", toString(get(obj, Pointer,type)), (void *)(intptr_t)_integerValue(base)); break; case Variable: - String_format(str, "<&%s", symbolName(get(base, Variable,name))); + String_format(str, "<%s &%s", toString(get(obj, Pointer,type)), symbolName(get(base, Variable,name))); break; case Memory: - String_format(str, "<%p[%d]", get(base, Memory,base), get(base, Memory,size)); + String_format(str, "<%s %p[%d]", toString(get(obj, Pointer,type)), get(base, Memory,base), get(base, Memory,size)); break; default: fatal("cannot convert pointer base %s to string", toString(base)); @@ -2254,6 +2254,25 @@ int toBoolean(oop arg) #define isTrue(O) ( toBoolean(O)) #define isFalse(O) (!toBoolean(O)) +int isNull(oop p) +{ + switch (getType(p)) { + case Integer: return 0 == _integerValue(p); + case Pointer: { + if (t_pvoid != get(p, Pointer,type)) return 0; + oop base = get(p, Pointer,base); + switch (getType(base)) { + case Integer: return 0 == _integerValue(base); + case Memory: return 0 == get(base, Memory,base); + default: break; + } + break; + } + default: break; + } + return 0; +} + oop pointerType(oop arg) { switch (getType(arg)) { @@ -3242,6 +3261,8 @@ oop assign(oop lhs, oop rhs) case Tdouble: return newFloat (*(double *)addr = _floatValue(rhs)); default: break; } + printf("ASSIGN "); println(lhs); + printf("FROM "); println(rhs); fatal("cannot store '%s' through pointer", getTypeName(type)); } default: break; @@ -3338,6 +3359,15 @@ void randomise(unsigned char *mem, size_t size) } } +oop castPointer(oop pointer, oop type) +{ + oop target = get(type, Tpointer,target); + int tscale = typeSize(target); + int pscale = typeSize(get(get(pointer, Pointer,type), Tpointer,target)); + int offset = get(pointer, Pointer,offset) * pscale / tscale; + return newPointer(type, get(pointer, Pointer,base), offset); +} + void initialiseVariable(oop var, int local) { oop (*evaluate)(oop) = local ? eval : preval; @@ -3395,6 +3425,35 @@ void initialiseVariable(oop var, int local) set(var, Variable,value, value); break; } + case Tpointer: { + oop value = isNil(init) ? nil : evaluate(init); + switch (getType(value)) { + case Undefined: { + set(var, Variable,value, nil); + break; + } + case Integer: { + if (_integerValue(value)) fatal("storing non-zero integer into pointer"); + value = newPointer(type, value, 0); + set(var, Variable,value, value); + break; + } + case Pointer: { + oop vtype = get(value, Pointer,type); + if (type != vtype) { + if (vtype != t_pvoid || !isNull(value)) + fatal("cannot convert non-NULL pointer '%s' to '%s'", toString(vtype), toString(type)); + value = castPointer(value, type); + } + set(var, Variable,value, castPointer(value, type)); + break; + } + default: + println(value); + fatal("cannot initialise pointer with %s", getTypeName(value)); + break; + } + } default: { if (!isNil(init)) set(var, Variable,value, evaluate(init)); break; @@ -3420,9 +3479,12 @@ oop eval(oop exp) case Symbol: { oop value = Scope_lookup(exp); if (!value) fatal("'%s' is undefined\n", get(exp, Symbol,name)); - if (isNil(value)) fatal("'%s' is uninitialised\n", get(exp, Symbol,name)); switch (getType(value)) { - case Variable: RETURN(get(value, Variable,value)); + case Variable: { + value = get(value, Variable,value); + if (isNil(value)) fatal("use of uninitialised variable '%s'", get(exp, Symbol,name)); + RETURN(value); + } case Function: RETURN(value); case Primitive: RETURN(value); default: fatal("cannot eval: %s", toString(value)); @@ -3691,13 +3753,7 @@ oop eval(oop exp) rhs = cvt(rhs); switch (getType(type)) { case Tpointer: { - if (is(Pointer,rhs)) { - int offset = get(rhs, Pointer,offset); - int rscale = typeSize(get(get(rhs, Pointer,type), Tpointer,target)); - int lscale = typeSize(get(type, Tpointer,target)); - offset = offset * lscale / rscale; - RETURN(newPointer(type, get(rhs, Pointer,base), get(rhs, Pointer,offset))); - } + if (is(Pointer,rhs)) RETURN(castPointer(rhs, type)); } } RETURN(cvt(rhs));