Better checks on pointers.

Pointer offsets are now honoured.


git-svn-id: http://picoc.googlecode.com/svn/trunk@259 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-04-22 07:23:26 +00:00
parent 8c918707f2
commit e5fa7017f0
5 changed files with 40 additions and 20 deletions

1
TODO
View file

@ -9,6 +9,7 @@ Implement:
* casts
* char access/char array access/char * access
* an easier way of checking pointers in library code
* evaluate only first argument of && and || if possible
Improvements:
* #define with arguments

View file

@ -167,10 +167,11 @@ void ExpressionStackPushValue(struct ParseState *Parser, struct ExpressionStack
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
}
void ExpressionStackPushLValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue)
void ExpressionStackPushLValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue, int Offset)
{
debugf("ExpressionStackPushLValue()\n");
struct Value *ValueLoc = VariableAllocValueShared(Parser, PushValue);
ValueLoc->Val = (void *)ValueLoc->Val + Offset;
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
}
@ -215,19 +216,15 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack
TempLValue = TopValue->LValueFrom;
Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, TopValue->Typ, TypePointer, 0, StrEmpty), FALSE, NULL);
Result->Val->Pointer.Segment = TempLValue;
Result->Val->Pointer.Offset = (void *)Result->Val - (void *)Result->LValueFrom;
if (Result->LValueFrom != NULL)
Result->Val->Pointer.Offset = (void *)Result->Val - (void *)Result->LValueFrom;
ExpressionStackPushValueNode(Parser, StackTop, Result);
break;
case TokenAsterisk:
if (TopValue->Typ->Base != TypePointer)
ProgramFail(Parser, "can't dereference this non-pointer");
if (TopValue->Val->Pointer.Segment == NULL)
ProgramFail(Parser, "can't dereference NULL pointer");
// XXX - should also do offset + checks
ExpressionStackPushLValue(Parser, StackTop, TopValue->Val->Pointer.Segment);
VariableCheckPointer(Parser, TopValue);
ExpressionStackPushLValue(Parser, StackTop, TopValue->Val->Pointer.Segment, TopValue->Val->Pointer.Offset);
break;
case TokenSizeof:
@ -611,19 +608,16 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac
/* look up the struct element */
struct Value *ParamVal = (*StackTop)->p.Val;
struct Value *StructVal = ParamVal;
int StructOffset = 0;
struct Value *MemberValue;
struct Value *Result;
if (Token == TokenArrow)
{
/* dereference the struct pointer first */
if (StructVal->Typ->Base != TypePointer)
ProgramFail(Parser, "can't dereference this non-pointer");
// XXX - should also do offset + checks
VariableCheckPointer(Parser, ParamVal);
StructVal = ParamVal->Val->Pointer.Segment;
if (StructVal == NULL)
ProgramFail(Parser, "can't dereference NULL pointer");
StructOffset = ParamVal->Val->Pointer.Offset;
}
if (StructVal->Typ->Base != TypeStruct && StructVal->Typ->Base != TypeUnion)
@ -637,7 +631,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac
*StackTop = (*StackTop)->Next;
/* make the result value for this member only */
Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, (void *)StructVal->Val + MemberValue->Val->Integer, TRUE, StructVal->LValueFrom);
Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, (void *)StructVal->Val + StructOffset + MemberValue->Val->Integer, TRUE, StructVal->LValueFrom);
ExpressionStackPushValueNode(Parser, StackTop, Result);
}
}
@ -679,7 +673,6 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
{
/* boost the bracket operator precedence, then push */
BracketPrecedence += BRACKET_PRECEDENCE;
// XXX ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence);
}
else
{
@ -741,7 +734,6 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
{
/* boost the bracket operator precedence, then push */
BracketPrecedence += BRACKET_PRECEDENCE;
// XXX ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence);
}
}
else
@ -774,7 +766,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
else if (VariableValue->Typ == TypeVoid)
ProgramFail(Parser, "a void value isn't much use here");
else
ExpressionStackPushLValue(Parser, &StackTop, VariableValue); /* it's a value variable */
ExpressionStackPushLValue(Parser, &StackTop, VariableValue, 0); /* it's a value variable */
}
else /* push a dummy value */
ExpressionPushInt(Parser, &StackTop, 0);

View file

@ -286,6 +286,7 @@ void TypeCleanup();
int TypeSize(struct ValueType *Typ, int ArraySize);
int TypeSizeValue(struct Value *Val);
int TypeStackSizeValue(struct Value *Val);
int TypeLastAccessibleOffset(struct Value *Val);
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ);
void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
void TypeParse(struct ParseState *Parser, struct ValueType **Typ, char **Identifier);
@ -320,6 +321,7 @@ void VariableStackFrameAdd(struct ParseState *Parser, int NumParams);
void VariableStackFramePop(struct ParseState *Parser);
struct Value *VariableStringLiteralGet(char *Ident);
void VariableStringLiteralDefine(char *Ident, struct Value *Val);
void VariableCheckPointer(struct ParseState *Parser, struct Value *PointerValue);
/* library.c */
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]);

9
type.c
View file

@ -75,6 +75,15 @@ int TypeSizeValue(struct Value *Val)
return sizeof(struct ArrayValue) + Val->Typ->FromType->Sizeof * Val->Val->Array.Size;
}
/* the last accessible offset of a value */
int TypeLastAccessibleOffset(struct Value *Val)
{
if (Val->Typ->Base != TypeArray)
return 0;
else
return Val->Typ->FromType->Sizeof * (Val->Val->Array.Size-1);
}
/* memory used by a variable given its type and array size */
int TypeSize(struct ValueType *Typ, int ArraySize)
{

View file

@ -260,3 +260,19 @@ void VariableStringLiteralDefine(char *Ident, struct Value *Val)
{
TableSet(&StringLiteralTable, Ident, Val);
}
/* check a pointer for validity */
void VariableCheckPointer(struct ParseState *Parser, struct Value *PointerValue)
{
struct Value *PointedToValue = PointerValue->Val->Pointer.Segment;
if (PointerValue->Typ->Base != TypePointer)
ProgramFail(Parser, "pointer expected");
if (PointedToValue == NULL)
ProgramFail(Parser, "can't dereference NULL pointer");
if (PointerValue->Val->Pointer.Offset < 0 || PointerValue->Val->Pointer.Offset > TypeLastAccessibleOffset(PointedToValue))
ProgramFail(Parser, "attempt to access invalid pointer");
}