From ca9e7094d1c2eebbd37b3e27f7b60900242ed823 Mon Sep 17 00:00:00 2001 From: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> Date: Thu, 7 Aug 2025 01:03:08 +0300 Subject: Sec: Compiler Frontend Patched buffer overflows and errors in the AMD64 compiler that could lead to crashes or undefined behavior. Signed-off-by: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> --- .../src/Frontend/CPlusPlusCompilerAMD64.cc | 103 +++++++++++---------- 1 file changed, 56 insertions(+), 47 deletions(-) (limited to 'dev/CompilerKit/src') diff --git a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc index 98a8018..b83f290 100644 --- a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc +++ b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc @@ -19,6 +19,8 @@ #include #include #include +#include +#include /* NeKernel C++ Compiler Driver */ /* This is part of the CompilerKit. */ @@ -27,8 +29,6 @@ /// @author EL Mahrouss Amlal (amlal@nekernel.org) /// @file CPlusPlusCompilerAMD64.cxx /// @brief Optimized C++ Compiler Driver. -/// @todo Throw error for scoped inside scoped variables when they get referenced outside. -/// @todo Add class/struct/enum support. /////////////////////// @@ -84,11 +84,29 @@ struct CompilerState final { CompilerKit::STLString fLastFile; CompilerKit::STLString fLastError; }; + +/// @brief prints an error into stdout. +/// @param reason the reason of the error. +/// @param file where does it originate from? +void p_error(const CompilerKit::STLString& reason, const CompilerKit::STLString& file) noexcept { + std::cerr << kRed << "Error in " << file << ": " << reason << kWhite << std::endl; +} + +/// @brief crash handler for segmentation faults +/// @param signal the signal number +void drvi_crash_handler(int signal) noexcept { + std::cerr << kRed << "Compiler crashed with signal: " << signal << kWhite << std::endl; + std::cerr << "Last file: " << kState.fLastFile << std::endl; + std::cerr << "Last error: " << kState.fLastError << std::endl; + std::exit(EXIT_FAILURE); +} } // namespace Detail static Detail::CompilerState kState; static Int32 kOnClassScope = 0; +static Boolean kVerbose = false; +static Int32 kErrorLimit = 0; ///////////////////////////////////////////////////////////////////////////////////////// @@ -222,7 +240,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( if (keywordPos == CompilerKit::STLString::npos || openParen == CompilerKit::STLString::npos || closeParen == CompilerKit::STLString::npos || closeParen <= openParen) { - Detail::print_error("Malformed if expression: " + text, file); + Detail::p_error("Malformed if expression: " + text, file); break; } @@ -234,37 +252,26 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( expr.find("<=") + strlen("<=")); auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1); - size_t i = right.size() - 1; - - if (i < 1) break; - - try { - while (!std::isalnum(right[i])) { - right.erase(i, 1); - --i; - } - - right.erase(0, i); - } catch (...) { - right.erase(0, i); + // trim non-alphanumeric characters from right + while (!right.empty() && !std::isalnum(right.back())) { + right.pop_back(); + } + while (!right.empty() && !std::isalnum(right.front())) { + right.erase(0, 1); } - i = left.size() - 1; - try { - while (!std::isalnum(left[i])) { - left.erase(i, 1); - --i; - } - - left.erase(0, i); - } catch (...) { - left.erase(0, i); + // trim non-alphanumeric characters from left + while (!left.empty() && !std::isalnum(left.back())) { + left.pop_back(); + } + while (!left.empty() && !std::isalnum(left.front())) { + left.erase(0, 1); } - if (!isdigit(left[0]) || !isdigit(right[0])) { + if ((!left.empty() && !isdigit(left[0])) || (!right.empty() && !isdigit(right[0]))) { auto indexRight = 0UL; - auto& valueOfVar = !isdigit(left[0]) ? left : right; + auto& valueOfVar = (!left.empty() && !isdigit(left[0])) ? left : right; if (!valueOfVar.empty()) { for (auto pairRight : kRegisterMap) { @@ -273,7 +280,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( CompilerKit::STLString instr = "mov "; if (pairRight != valueOfVar) { - auto& valueOfVarOpposite = isdigit(left[0]) ? left : right; + auto& valueOfVarOpposite = (!left.empty() && isdigit(left[0])) ? left : right; syntax_tree.fUserValue += instr + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n"; @@ -283,7 +290,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( goto lc_done_iterarting_on_if; } - auto& valueOfVarOpposite = isdigit(left[0]) ? left : right; + auto& valueOfVarOpposite = (!left.empty() && isdigit(left[0])) ? left : right; syntax_tree.fUserValue += instr + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n"; @@ -345,14 +352,14 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( if (text.ends_with(";") && text.find("return") == CompilerKit::STLString::npos) goto lc_write_assembly; else if (text.size() <= indexFnName) - Detail::print_error("Invalid function name: " + symbol_name_fn, file); + Detail::p_error("Invalid function name: " + symbol_name_fn, file); indexFnName = 0; for (auto& ch : symbol_name_fn) { if (ch == ' ' || ch == '\t') { if (symbol_name_fn[indexFnName - 1] != ')') - Detail::print_error("Invalid function name: " + symbol_name_fn, file); + Detail::p_error("Invalid function name: " + symbol_name_fn, file); } ++indexFnName; @@ -470,10 +477,8 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( varName.erase(varName.find("\t"), 1); } - for (size_t i = 0; !isalnum(valueOfVar[i]); i++) { - if (i > valueOfVar.size()) break; - - valueOfVar.erase(i, 1); + // Remove leading non-alphanumeric characters while (!valueOfVar.empty() && !isalnum(valueOfVar[0])) { + valueOfVar.erase(0, 1); } constexpr auto kTrueVal = "true"; @@ -523,12 +528,12 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( goto done; } - if (valueOfVar[0] != '\"' && valueOfVar[0] != '\'' && !isdigit(valueOfVar[0])) { + if (!valueOfVar.empty() && valueOfVar[0] != '\"' && valueOfVar[0] != '\'' && !isdigit(valueOfVar[0])) { for (auto pair : kRegisterMap) { if (pair == valueOfVar) goto done; } - Detail::print_error("Variable not declared: " + varName, file); + Detail::p_error("Variable not declared: " + varName, file); break; } @@ -579,10 +584,8 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( std::size_t indxReg = 0UL; - for (size_t i = 0; !isalnum(valueOfVar[i]); i++) { - if (i > valueOfVar.size()) break; - - valueOfVar.erase(i, 1); + // Remove leading non-alphanumeric characters while (!valueOfVar.empty() && !isalnum(valueOfVar[0])) { + valueOfVar.erase(0, 1); } while (valueOfVar.find(" ") != CompilerKit::STLString::npos) { @@ -632,7 +635,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( } if (syntax_tree.fUserValue.empty()) { - Detail::print_error("Variable not declared: " + varName, file); + Detail::p_error("Variable not declared: " + varName, file); } kRegisterMap.insert(kRegisterMap.end(), newVars.begin(), newVars.end()); @@ -646,7 +649,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( subText = subText.erase(subText.find(";")); size_t indxReg = 0UL; - if (subText[0] != '\"' && subText[0] != '\'') { + if (!subText.empty() && subText[0] != '\"' && subText[0] != '\'') { if (!isdigit(subText[0])) { for (auto pair : kRegisterMap) { ++indxReg; @@ -684,7 +687,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( }); if (it == kOriginMap.end()) - Detail::print_error("Invalid return value: " + subText, file); + Detail::p_error("Invalid return value: " + subText, file); std::stringstream ss; ss << it->second; @@ -821,6 +824,12 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { kCompilerFrontend = new CompilerFrontendCPlusPlusAMD64(); kFactory.Mount(new AssemblyCPlusPlusInterfaceAMD64()); + + // Ensure cleanup on exit + std::atexit([]() { + delete kCompilerFrontend; + kCompilerFrontend = nullptr; + }); CompilerKit::install_signal(SIGSEGV, Detail::drvi_crash_handler); @@ -862,7 +871,7 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { CompilerKit::STLString err = "Unknown option: "; err += argv[index]; - Detail::print_error(err, "cxxdrv"); + Detail::p_error(err, "cxxdrv"); continue; } @@ -888,5 +897,5 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { } // -// Last rev 23-5-25 +// Last rev 25-8-7 // -- cgit v1.2.3 From afd704793a8779642094202fe6ac8acf9073140b Mon Sep 17 00:00:00 2001 From: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> Date: Thu, 7 Aug 2025 20:04:23 +0300 Subject: Update for consistency Signed-off-by: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> --- .../src/Frontend/CPlusPlusCompilerAMD64.cc | 68 +++++++++++----------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'dev/CompilerKit/src') diff --git a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc index b83f290..5897030 100644 --- a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc +++ b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc @@ -10,6 +10,7 @@ /// BUGS: 0 #define kPrintF printf +#define kStdErr std::cerr #define kExitOK (EXIT_SUCCESS) #define kExitNO (EXIT_FAILURE) @@ -48,21 +49,22 @@ /// @internal namespace Detail { -std::filesystem::path expand_home(const std::filesystem::path& p) { - if (!p.empty() && p.string()[0] == '~') { - const char* home = std::getenv("HOME"); // For Unix-like systems +// Avoids relative_path which could discard parts of the original. +std::filesystem::path expand_home(const std::filesystem::path& input) { + const std::string& raw = input.string(); - if (!home) { - home = std::getenv("USERPROFILE"); // For Windows - } + if (!raw.empty() && raw[0] == '~') { + const char* home = std::getenv("HOME"); + if (!home) home = std::getenv("USERPROFILE"); - if (home) { - return std::filesystem::path(home) / p.relative_path().string().substr(1); - } else { + if (!home) throw std::runtime_error("Home directory not found in environment variables"); - } + + return std::filesystem::path(home) / raw.substr(1); + } + + return input; } - return p; } struct CompilerRegisterMap final { @@ -88,16 +90,16 @@ struct CompilerState final { /// @brief prints an error into stdout. /// @param reason the reason of the error. /// @param file where does it originate from? -void p_error(const CompilerKit::STLString& reason, const CompilerKit::STLString& file) noexcept { - std::cerr << kRed << "Error in " << file << ": " << reason << kWhite << std::endl; +void print_error(const CompilerKit::STLString& reason, const CompilerKit::STLString& file) noexcept { + kStdErr << kRed << "Error in " << file << ": " << reason << kWhite << std::endl; } /// @brief crash handler for segmentation faults /// @param signal the signal number void drvi_crash_handler(int signal) noexcept { - std::cerr << kRed << "Compiler crashed with signal: " << signal << kWhite << std::endl; - std::cerr << "Last file: " << kState.fLastFile << std::endl; - std::cerr << "Last error: " << kState.fLastError << std::endl; + kStdErr << kRed << "Compiler crashed with signal: " << signal << kWhite << std::endl; + kStdErr << "Last file: " << kState.fLastFile << std::endl; + kStdErr << "Last error: " << kState.fLastError << std::endl; std::exit(EXIT_FAILURE); } } // namespace Detail @@ -204,7 +206,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( std::size_t pos = text.find(keyword.keyword_name); if (pos == std::string::npos) continue; - // Safe guard: can't go before start of string + // can't go before start of string if (pos > 0 && text[pos - 1] == '+' && keyword.keyword_kind == CompilerKit::kKeywordKindVariableAssign) continue; @@ -213,7 +215,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( keyword.keyword_kind == CompilerKit::kKeywordKindVariableAssign) continue; - // Safe guard: don't go out of range + // don't go out of range if ((pos + keyword.keyword_name.size()) < text.size() && text[pos + keyword.keyword_name.size()] == '=' && keyword.keyword_kind == CompilerKit::kKeywordKindVariableAssign) @@ -240,7 +242,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( if (keywordPos == CompilerKit::STLString::npos || openParen == CompilerKit::STLString::npos || closeParen == CompilerKit::STLString::npos || closeParen <= openParen) { - Detail::p_error("Malformed if expression: " + text, file); + Detail::print_error("Malformed if expression: " + text, file); break; } @@ -252,19 +254,18 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( expr.find("<=") + strlen("<=")); auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1); - // trim non-alphanumeric characters from right - while (!right.empty() && !std::isalnum(right.back())) { + // Trim whitespace + while (!right.empty() && (right.back() == ' ' || right.back() == '\t')) { right.pop_back(); } - while (!right.empty() && !std::isalnum(right.front())) { + while (!right.empty() && (right.front() == ' ' || right.front() == '\t')) { right.erase(0, 1); } - // trim non-alphanumeric characters from left - while (!left.empty() && !std::isalnum(left.back())) { + while (!left.empty() && (left.back() == ' ' || left.back() == '\t')) { left.pop_back(); } - while (!left.empty() && !std::isalnum(left.front())) { + while (!left.empty() && (left.front() == ' ' || left.front() == '\t')) { left.erase(0, 1); } @@ -352,14 +353,14 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( if (text.ends_with(";") && text.find("return") == CompilerKit::STLString::npos) goto lc_write_assembly; else if (text.size() <= indexFnName) - Detail::p_error("Invalid function name: " + symbol_name_fn, file); + Detail::print_error("Invalid function name: " + symbol_name_fn, file); indexFnName = 0; for (auto& ch : symbol_name_fn) { if (ch == ' ' || ch == '\t') { if (symbol_name_fn[indexFnName - 1] != ')') - Detail::p_error("Invalid function name: " + symbol_name_fn, file); + Detail::print_error("Invalid function name: " + symbol_name_fn, file); } ++indexFnName; @@ -477,7 +478,8 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( varName.erase(varName.find("\t"), 1); } - // Remove leading non-alphanumeric characters while (!valueOfVar.empty() && !isalnum(valueOfVar[0])) { + // Remove whitespace only (keep operators and quotes) + while (!valueOfVar.empty() && (valueOfVar[0] == ' ' || valueOfVar[0] == '\t')) { valueOfVar.erase(0, 1); } @@ -533,7 +535,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( if (pair == valueOfVar) goto done; } - Detail::p_error("Variable not declared: " + varName, file); + Detail::print_error("Variable not declared: " + varName, file); break; } @@ -584,7 +586,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( std::size_t indxReg = 0UL; - // Remove leading non-alphanumeric characters while (!valueOfVar.empty() && !isalnum(valueOfVar[0])) { + while (!valueOfVar.empty() && (valueOfVar[0] == ' ' || valueOfVar[0] == '\t')) { valueOfVar.erase(0, 1); } @@ -635,7 +637,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( } if (syntax_tree.fUserValue.empty()) { - Detail::p_error("Variable not declared: " + varName, file); + Detail::print_error("Variable not declared: " + varName, file); } kRegisterMap.insert(kRegisterMap.end(), newVars.begin(), newVars.end()); @@ -687,7 +689,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlusAMD64::Compile( }); if (it == kOriginMap.end()) - Detail::p_error("Invalid return value: " + subText, file); + Detail::print_error("Invalid return value: " + subText, file); std::stringstream ss; ss << it->second; @@ -871,7 +873,7 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { CompilerKit::STLString err = "Unknown option: "; err += argv[index]; - Detail::p_error(err, "cxxdrv"); + Detail::print_error(err, "cxxdrv"); continue; } -- cgit v1.2.3 From 870e0e02f171f2f77057fe0d02627214a4f09ae1 Mon Sep 17 00:00:00 2001 From: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:16:24 +0300 Subject: :) Signed-off-by: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> --- dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'dev/CompilerKit/src') diff --git a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc index 5897030..c31a81c 100644 --- a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc +++ b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc @@ -10,7 +10,7 @@ /// BUGS: 0 #define kPrintF printf -#define kStdErr std::cerr +#define kPrintErr std::cerr #define kExitOK (EXIT_SUCCESS) #define kExitNO (EXIT_FAILURE) @@ -91,16 +91,7 @@ struct CompilerState final { /// @param reason the reason of the error. /// @param file where does it originate from? void print_error(const CompilerKit::STLString& reason, const CompilerKit::STLString& file) noexcept { - kStdErr << kRed << "Error in " << file << ": " << reason << kWhite << std::endl; -} - -/// @brief crash handler for segmentation faults -/// @param signal the signal number -void drvi_crash_handler(int signal) noexcept { - kStdErr << kRed << "Compiler crashed with signal: " << signal << kWhite << std::endl; - kStdErr << "Last file: " << kState.fLastFile << std::endl; - kStdErr << "Last error: " << kState.fLastError << std::endl; - std::exit(EXIT_FAILURE); + kPrintErr << kRed << "Error in " << file << ": " << reason << kWhite << std::endl; } } // namespace Detail @@ -833,7 +824,7 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { kCompilerFrontend = nullptr; }); - CompilerKit::install_signal(SIGSEGV, Detail::drvi_crash_handler); + for (auto index = 1UL; index < argc; ++index) { if (!argv[index]) break; -- cgit v1.2.3 From 00ca2763dc843d9127376b8e5c5a133659a56a75 Mon Sep 17 00:00:00 2001 From: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> Date: Fri, 8 Aug 2025 15:36:56 +0300 Subject: CPlusPlusCompilerAMD64.cc Signed-off-by: 0xf00sec <159052166+0xf00sec@users.noreply.github.com> --- dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'dev/CompilerKit/src') diff --git a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc index c31a81c..ad2b8e1 100644 --- a/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc +++ b/dev/CompilerKit/src/Frontend/CPlusPlusCompilerAMD64.cc @@ -817,6 +817,8 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { kCompilerFrontend = new CompilerFrontendCPlusPlusAMD64(); kFactory.Mount(new AssemblyCPlusPlusInterfaceAMD64()); + + CompilerKit::install_signal(SIGSEGV, Detail::drvi_crash_handler); // Ensure cleanup on exit std::atexit([]() { @@ -825,7 +827,6 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { }); - for (auto index = 1UL; index < argc; ++index) { if (!argv[index]) break; @@ -834,6 +835,7 @@ NECTI_MODULE(CompilerCPlusPlusAMD64) { skip = false; continue; } + if (strcmp(argv[index], "-cxx-verbose") == 0) { kVerbose = true; -- cgit v1.2.3