Преглед изворни кода

be more pedantic about correct types in pointer initialisation and assignment unless the value is (void *)0

master
Ian Piumarta пре 3 месеци
родитељ
комит
c12fa4fdad
4 измењених фајлова са 85 додато и 28 уклоњено
  1. +1
    -1
      demofiles/memory-leak.c
  2. +5
    -5
      demofiles/multiple-free.c
  3. +10
    -9
      demofiles/use-after-free.c
  4. +69
    -13
      main.leg

+ 1
- 1
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;

+ 5
- 5
demofiles/multiple-free.c Прегледај датотеку

@ -5,9 +5,9 @@
#include <assert.h>
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;
}

+ 10
- 9
demofiles/use-after-free.c Прегледај датотеку

@ -5,13 +5,14 @@
#include <assert.h>
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;
}

+ 69
- 13
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));

Loading…
Откажи
Сачувај