From: mrdudz Date: Fri, 10 Jul 2015 12:27:49 +0000 (+0200) Subject: patch from Uz that makes some illegal operations on pointers error out X-Git-Tag: V2.16~250^2^2~1 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6ab197f364571f370604bb10b68e54dc5ecdd208;p=cc65 patch from Uz that makes some illegal operations on pointers error out --- diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 9971a9569..8c9d6dcb0 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -391,6 +391,12 @@ unsigned SizeOf (const Type* T) case T_VOID: return 0; /* Assume voids have size zero */ + /* Beware: There's a chance that this triggers problems in other parts + of the compiler. The solution is to fix the callers, because calling + SizeOf() with a function type as argument is bad. */ + case T_FUNC: + return 0; /* Size of function is unknown */ + case T_SCHAR: case T_UCHAR: return SIZEOF_CHAR; @@ -404,7 +410,6 @@ unsigned SizeOf (const Type* T) return SIZEOF_INT; case T_PTR: - case T_FUNC: /* Maybe pointer to function */ return SIZEOF_PTR; case T_LONG: diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 7563645ff..b82dff10d 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -50,6 +50,7 @@ /* Generator attributes */ #define GEN_NOPUSH 0x01 /* Don't push lhs */ #define GEN_COMM 0x02 /* Operator is commutative */ +#define GEN_NOFUNC 0x04 /* Not allowed for function pointers */ /* Map a generator function and its attributes to a token */ typedef struct { @@ -2042,6 +2043,11 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ Tok = CurTok.Tok; NextToken (); + /* If lhs is a function, convert it to pointer to function */ + if (IsTypeFunc (Expr->Type)) { + Expr->Type = PointerTo (Expr->Type); + } + /* Get the lhs on stack */ GetCodePos (&Mark1); ltype = TypeOf (Expr->Type); @@ -2059,6 +2065,11 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ /* Get the right hand side */ MarkedExprWithCheck (hienext, &Expr2); + /* If rhs is a function, convert it to pointer to function */ + if (IsTypeFunc (Expr2.Type)) { + Expr2.Type = PointerTo (Expr2.Type); + } + /* Check for a constant expression */ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)); if (!rconst) { @@ -2066,6 +2077,22 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ LoadExpr (CF_NONE, &Expr2); } + /* Some operations aren't allowed on function pointers */ + if ((Gen->Flags & GEN_NOFUNC) != 0) { + /* Output only one message even if both sides are wrong */ + if (IsTypeFuncPtr (Expr->Type)) { + Error ("Invalid left operand for relational operator"); + /* Avoid further errors */ + ED_MakeConstAbsInt (Expr, 0); + ED_MakeConstAbsInt (&Expr2, 0); + } else if (IsTypeFuncPtr (Expr2.Type)) { + Error ("Invalid right operand for relational operator"); + /* Avoid further errors */ + ED_MakeConstAbsInt (Expr, 0); + ED_MakeConstAbsInt (&Expr2, 0); + } + } + /* Make sure, the types are compatible */ if (IsClassInt (Expr->Type)) { if (!IsClassInt (Expr2.Type) && !(IsClassPtr(Expr2.Type) && ED_IsNullPtr(Expr))) { @@ -2600,6 +2627,13 @@ static void parsesub (ExprDesc* Expr) int rscale; /* Scale factor for the result */ + /* lhs cannot be function or pointer to function */ + if (IsTypeFunc (Expr->Type) || IsTypeFuncPtr (Expr->Type)) { + Error ("Invalid left operand for binary operator `-'"); + /* Make it pointer to char to avoid further errors */ + Expr->Type = type_uchar; + } + /* Skip the MINUS token */ NextToken (); @@ -2616,6 +2650,13 @@ static void parsesub (ExprDesc* Expr) /* Parse the right hand side */ MarkedExprWithCheck (hie9, &Expr2); + /* rhs cannot be function or pointer to function */ + if (IsTypeFunc (Expr2.Type) || IsTypeFuncPtr (Expr2.Type)) { + Error ("Invalid right operand for binary operator `-'"); + /* Make it pointer to char to avoid further errors */ + Expr2.Type = type_uchar; + } + /* Check for a constant rhs expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { @@ -2775,10 +2816,10 @@ static void hie6 (ExprDesc* Expr) /* Handle greater-than type comparators */ { static const GenDesc hie6_ops [] = { - { TOK_LT, GEN_NOPUSH, g_lt }, - { TOK_LE, GEN_NOPUSH, g_le }, - { TOK_GE, GEN_NOPUSH, g_ge }, - { TOK_GT, GEN_NOPUSH, g_gt }, + { TOK_LT, GEN_NOPUSH | GEN_NOFUNC, g_lt }, + { TOK_LE, GEN_NOPUSH | GEN_NOFUNC, g_le }, + { TOK_GE, GEN_NOPUSH | GEN_NOFUNC, g_ge }, + { TOK_GT, GEN_NOPUSH | GEN_NOFUNC, g_gt }, { TOK_INVALID, 0, 0 } }; hie_compare (hie6_ops, Expr, ShiftExpr); diff --git a/test/val/cc65150311.c b/test/val/cc65150311.c new file mode 100644 index 000000000..cd644f491 --- /dev/null +++ b/test/val/cc65150311.c @@ -0,0 +1,38 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + +/* the following are not valid C and should go into seperate tests that MUST fail */ +/* + ++p; + n = (p > &func); + n = (p > func); + n = func - func; + n = func - &func; + n = &func - func; + n = &func - &func; + n = p - &func; + n = p - func; + n = &func - p; + n = func - p; +*/ + return 0; +}