From 6481e119e474ae58fa2b8b2c4c898b0d2e9784b3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 17 Oct 2021 18:20:44 +0200 Subject: [PATCH] Fix various errors triggered by fuzzing --- oscar64/Declaration.cpp | 27 +++++++++++++++--- oscar64/Declaration.h | 4 ++- oscar64/Errors.cpp | 2 +- oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 5 ++-- oscar64/InterCodeGenerator.cpp | 22 +++++++++++---- oscar64/Parser.cpp | 50 ++++++++++++++++++++++++---------- oscar64/Preprocessor.cpp | 13 +++++++-- oscar64/Scanner.cpp | 10 +++++-- 9 files changed, 101 insertions(+), 33 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 3c4c185..0446ffd 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -142,11 +142,12 @@ Expression* Expression::LogicInvertExpression(void) { Expression* ex = new Expression(mLocation, EX_LOGICAL_NOT); ex->mLeft = this; + ex->mDecType = TheBoolTypeDeclaration; return ex; } } -Expression* Expression::ConstantFold(void) +Expression* Expression::ConstantFold(Errors * errors) { if (mType == EX_PREFIX && mLeft->mType == EX_CONSTANT) { @@ -249,7 +250,7 @@ Expression* Expression::ConstantFold(void) { if (mLeft->mDecValue->mType == DT_CONST_INTEGER && mRight->mDecValue->mType == DT_CONST_INTEGER) { - int64 ival, ileft = mLeft->mDecValue->mInteger, iright = mRight->mDecValue->mInteger; + int64 ival = 0, ileft = mLeft->mDecValue->mInteger, iright = mRight->mDecValue->mInteger; switch (mToken) { @@ -263,10 +264,16 @@ Expression* Expression::ConstantFold(void) ival = ileft * iright; break; case TK_DIV: - ival = ileft / iright; + if (iright == 0) + errors->Error(mLocation, EERR_INVALID_VALUE, "Constant division by zero"); + else + ival = ileft / iright; break; case TK_MOD: - ival = ileft % iright; + if (iright == 0) + errors->Error(mLocation, EERR_INVALID_VALUE, "Constant division by zero"); + else + ival = ileft % iright; break; case TK_LEFT_SHIFT: ival = ileft << iright; @@ -498,6 +505,7 @@ bool Declaration::IsNumericType(void) const Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration; Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; +Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; void InitDeclarations(void) { @@ -510,6 +518,17 @@ void InitDeclarations(void) TheVoidPointerTypeDeclaration->mSize = 2; TheVoidPointerTypeDeclaration->mFlags = DTF_DEFINED; + TheVoidFunctionTypeDeclaration = new Declaration(noloc, DT_TYPE_FUNCTION); + TheVoidFunctionTypeDeclaration->mBase = TheVoidTypeDeclaration; + TheVoidFunctionTypeDeclaration->mSize = 2; + TheVoidFunctionTypeDeclaration->mFlags = DTF_DEFINED; + + TheConstVoidValueDeclaration = new Declaration(noloc, DT_CONST_INTEGER); + TheVoidFunctionTypeDeclaration->mBase = TheVoidTypeDeclaration; + TheVoidFunctionTypeDeclaration->mSize = 2; + TheVoidFunctionTypeDeclaration->mInteger = 0; + TheVoidFunctionTypeDeclaration->mFlags = DTF_DEFINED; + TheSignedIntTypeDeclaration = new Declaration(noloc, DT_TYPE_INTEGER); TheSignedIntTypeDeclaration->mSize = 2; TheSignedIntTypeDeclaration->mFlags = DTF_DEFINED | DTF_SIGNED; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index b850709..ea11500 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -150,7 +150,7 @@ public: bool mConst; Expression* LogicInvertExpression(void); - Expression* ConstantFold(void); + Expression* ConstantFold(Errors * errors); }; class Declaration @@ -188,3 +188,5 @@ void InitDeclarations(void); extern Declaration* TheVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration; extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; +extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; + diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index edc57df..cf765e1 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -27,7 +27,7 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char printf("%s(%d, %d) : %s %d: %s\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg); if (mErrorCount > 10) - exit(10); + exit(20); } diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 73b80d0..4b46761 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -31,6 +31,7 @@ enum ErrorID EERR_CONSTANT_INITIALIZER, EERR_CONSTANT_TYPE, EERR_VARIABLE_TYPE, + EERR_INVALID_VALUE, EERR_INCOMPATIBLE_TYPES, EERR_INCOMPATIBLE_OPERATOR, EERR_CONST_ASSIGN, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index f4aab52..13a675f 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -168,7 +168,7 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec) if (procDec) procDec->mComplexity += 2; - if (exp->mLeft) + if (exp->mLeft && exp->mLeft->mDecValue) { Declaration* adec = exp->mLeft->mDecValue; if (adec->mType == DT_LABEL_REF) @@ -306,7 +306,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) case EX_SEQUENCE: do { - ldec = Analyze(exp->mLeft, procDec); + if (exp->mLeft) + ldec = Analyze(exp->mLeft, procDec); exp = exp->mRight; } while (exp); break; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 6bb4377..2ae61d1 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -277,7 +277,9 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex case ASMIM_IMPLIED: break; case ASMIM_IMMEDIATE: - if (aexp->mType == DT_CONST_INTEGER) + if (!aexp) + mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand"); + else if (aexp->mType == DT_CONST_INTEGER) d[offset++] = cexp->mLeft->mDecValue->mInteger & 255; else if (aexp->mType == DT_LABEL_REF) { @@ -346,7 +348,9 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex case ASMIM_ZERO_PAGE_X: case ASMIM_INDIRECT_X: case ASMIM_INDIRECT_Y: - if (aexp->mType == DT_VARIABLE_REF) + if (!aexp) + mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand"); + else if (aexp->mType == DT_VARIABLE_REF) { if (refvars) { @@ -405,7 +409,9 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex case ASMIM_INDIRECT: case ASMIM_ABSOLUTE_X: case ASMIM_ABSOLUTE_Y: - if (aexp->mType == DT_CONST_INTEGER) + if (!aexp) + mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand"); + else if (aexp->mType == DT_CONST_INTEGER) { d[offset++] = cexp->mLeft->mDecValue->mInteger & 255; d[offset++] = cexp->mLeft->mDecValue->mInteger >> 8; @@ -535,7 +541,10 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex } break; case ASMIM_RELATIVE: - d[offset] = aexp->mInteger - offset - 1; + if (!aexp) + mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand"); + else + d[offset] = aexp->mInteger - offset - 1; offset++; break; } @@ -928,7 +937,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_ASSIGNMENT: { - if (exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) + if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) { vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper, &vl); @@ -3173,7 +3182,8 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod exitBlock->Append(ins); exitBlock->Close(nullptr, nullptr); - proc->Close(); + if (mErrors->mErrorCount == 0) + proc->Close(); return proc; } diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 0ae4747..fa872ab 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -891,6 +891,7 @@ Expression* Parser::ParseDeclarationExpression(void) nexp->mLeft = new Expression(dec->mLocation, EX_VARIABLE); nexp->mLeft->mDecValue = dec; nexp->mLeft->mDecType = dec->mBase; + nexp->mDecType = nexp->mLeft->mDecType; nexp->mRight = dec->mValue; @@ -1152,7 +1153,7 @@ Expression* Parser::ParseSimpleExpression(void) nexp->mDecType = exp->mDecType; nexp->mLeft = exp; nexp->mRight = ParsePrefixExpression(); - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } break; default: @@ -1202,7 +1203,10 @@ Expression* Parser::ParsePostfixExpression(void) { } else + { mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Function expected for call"); + exp->mDecType = TheVoidFunctionTypeDeclaration; + } mScanner->NextToken(); Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); @@ -1332,7 +1336,10 @@ Expression* Parser::ParsePrefixExpression(void) nexp->mDecType = nexp->mLeft->mDecType->mBase; } else + { mErrors->Error(nexp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Pointer or array type expected"); + nexp->mDecType = TheVoidTypeDeclaration; + } } else if (nexp->mToken == TK_BINARY_AND) { @@ -1344,7 +1351,7 @@ Expression* Parser::ParsePrefixExpression(void) else nexp->mDecType = nexp->mLeft->mDecType; } - return nexp->ConstantFold(); + return nexp->ConstantFold(mErrors); } else return ParsePostfixExpression(); @@ -1367,7 +1374,7 @@ Expression* Parser::ParseMulExpression(void) else nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1407,7 +1414,7 @@ Expression* Parser::ParseAddExpression(void) else nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1426,7 +1433,7 @@ Expression* Parser::ParseShiftExpression(void) nexp->mRight = ParseAddExpression(); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1445,7 +1452,7 @@ Expression* Parser::ParseRelationalExpression(void) nexp->mRight = ParseShiftExpression(); nexp->mDecType = TheBoolTypeDeclaration; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1464,7 +1471,7 @@ Expression* Parser::ParseBinaryAndExpression(void) nexp->mRight = ParseRelationalExpression(); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1482,7 +1489,7 @@ Expression* Parser::ParseBinaryXorExpression(void) mScanner->NextToken(); nexp->mRight = ParseBinaryAndExpression(); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1500,7 +1507,7 @@ Expression* Parser::ParseBinaryOrExpression(void) mScanner->NextToken(); nexp->mRight = ParseBinaryXorExpression(); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1518,7 +1525,7 @@ Expression* Parser::ParseLogicAndExpression(void) mScanner->NextToken(); nexp->mRight = ParseBinaryOrExpression(); nexp->mDecType = TheBoolTypeDeclaration; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1536,7 +1543,7 @@ Expression* Parser::ParseLogicOrExpression(void) mScanner->NextToken(); nexp->mRight = ParseLogicAndExpression(); nexp->mDecType = TheBoolTypeDeclaration; - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; @@ -1558,6 +1565,7 @@ Expression* Parser::ParseConditionalExpression(void) ConsumeToken(TK_COLON); texp->mRight = ParseConditionalExpression(); + nexp->mDecType = texp->mLeft->mDecType; exp = nexp; } @@ -1599,6 +1607,7 @@ Expression* Parser::ParseAssignmentExpression(void) nexp->mRight = ParseAssignmentExpression(); nexp->mDecType = exp->mDecType; exp = nexp; + assert(exp->mDecType); } return exp; @@ -1796,6 +1805,7 @@ Expression* Parser::ParseStatement(void) exp = new Expression(mScanner->mLocation, EX_CONTINUE); break; case TK_SEMICOLON: + exp = new Expression(mScanner->mLocation, EX_VOID); break; case TK_ASM: mScanner->NextToken(); @@ -1808,6 +1818,11 @@ Expression* Parser::ParseStatement(void) else mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "'}' expected"); } + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "'{' expected"); + exp = new Expression(mScanner->mLocation, EX_VOID); + } break; default: exp = ParseExpression(); @@ -1816,6 +1831,8 @@ Expression* Parser::ParseStatement(void) mScanner->NextToken(); } + assert(exp); + return exp; } @@ -2045,6 +2062,7 @@ Expression* Parser::ParseAssemblerBaseOperand(void) { exp = new Expression(mScanner->mLocation, EX_VOID); exp->mDecType = TheVoidTypeDeclaration; + exp->mDecValue = TheConstVoidValueDeclaration; } return exp; @@ -2060,7 +2078,7 @@ Expression* Parser::ParseAssemblerMulOperand(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAssemblerBaseOperand(); - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; } @@ -2075,7 +2093,11 @@ Expression* Parser::ParseAssemblerAddOperand(void) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAssemblerMulOperand(); - if (nexp->mLeft->mDecValue->mType == DT_VARIABLE || nexp->mLeft->mDecValue->mType == DT_ARGUMENT) + if (!nexp->mLeft->mDecValue || !nexp->mRight->mDecValue) + { + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Invalid assembler operand"); + } + else if (nexp->mLeft->mDecValue->mType == DT_VARIABLE || nexp->mLeft->mDecValue->mType == DT_ARGUMENT) { if (nexp->mRight->mDecValue->mType == DT_CONST_INTEGER) { @@ -2115,7 +2137,7 @@ Expression* Parser::ParseAssemblerAddOperand(void) mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Integer offset expected"); } else - exp = nexp->ConstantFold(); + exp = nexp->ConstantFold(mErrors); } return exp; } diff --git a/oscar64/Preprocessor.cpp b/oscar64/Preprocessor.cpp index d1e857f..ac11d78 100644 --- a/oscar64/Preprocessor.cpp +++ b/oscar64/Preprocessor.cpp @@ -50,7 +50,10 @@ SourceFile::~SourceFile(void) bool SourceFile::Open(const char* name, const char* path) { - char fname[200]; + char fname[220]; + + if (strlen(name) + strlen(path) > 200) + return false; strcpy_s(fname, path); int n = strlen(fname); @@ -142,6 +145,12 @@ bool Preprocessor::NextLine(void) bool Preprocessor::OpenSource(const char * reason, const char* name, bool local) { + if (strlen(name) > 200) + { + mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Source file path exceeds max path length"); + return false; + } + if (mSource) mSource->mLocation = mLocation; @@ -154,7 +163,7 @@ bool Preprocessor::OpenSource(const char * reason, const char* name, bool local) if (!ok && local && mSource) { - char lpath[200]; + char lpath[220]; strcpy_s(lpath, mSource->mFileName); int i = strlen(lpath); while (i > 0 && lpath[i - 1] != '/') diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index b0df82b..5cf8b28 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -985,7 +985,8 @@ void Scanner::NextRawToken(void) while (NextChar() && IsAlpha(mTokenChar)) { - tkprep[n++] = mTokenChar; + if (n < 127) + tkprep[n++] = mTokenChar; } tkprep[n] = 0; @@ -1070,18 +1071,21 @@ void Scanner::NextRawToken(void) else if (mTokenChar >= 'A' && mTokenChar <= 'Z' || mTokenChar >= 'a' && mTokenChar <= 'z' || mTokenChar == '_') { int n = 0; - char tkident[128]; + char tkident[256]; for (;;) { if (IsIdentChar(mTokenChar)) { - tkident[n++] = mTokenChar; + if (n < 255) + tkident[n++] = mTokenChar; NextChar(); } else break; } tkident[n] = 0; + if (n == 256) + Error("Identifier exceeds max character limit"); if (!strcmp(tkident, "true")) mToken = TK_TRUE;