diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1c025179..fe80a5ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -67,7 +67,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } try { - DATA->m_vColors.push_back(CColor(configStringToInt(var))); + DATA->m_vColors.push_back(CColor(*configStringToInt(var))); } catch (std::exception& e) { Debug::log(WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); @@ -2615,7 +2615,14 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin const static std::string ruleOnCreatedEmpty = "on-created-empty:"; const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); - auto assignRule = [&](std::string rule) -> std::optional { +#define CHECK_OR_THROW(expr) \ + \ + auto X = expr; \ + if (!X) { \ + return "Failed parsing a workspace rule"; \ + } + + auto assignRule = [&](std::string rule) -> std::optional { size_t delim = std::string::npos; if ((delim = rule.find("gapsin:")) != std::string::npos) { CVarList varlist = CVarList(rule.substr(delim + 7), 0, ' '); @@ -2633,25 +2640,32 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin try { wsRule.borderSize = std::stoi(rule.substr(delim + 11)); } catch (...) { return "Error parsing workspace rule bordersize: {}", rule.substr(delim + 11); } - else if ((delim = rule.find("border:")) != std::string::npos) - wsRule.noBorder = !configStringToInt(rule.substr(delim + 7)); - else if ((delim = rule.find("shadow:")) != std::string::npos) - wsRule.noShadow = !configStringToInt(rule.substr(delim + 7)); - else if ((delim = rule.find("rounding:")) != std::string::npos) - wsRule.noRounding = !configStringToInt(rule.substr(delim + 9)); - else if ((delim = rule.find("decorate:")) != std::string::npos) - wsRule.decorate = configStringToInt(rule.substr(delim + 9)); - else if ((delim = rule.find("monitor:")) != std::string::npos) + else if ((delim = rule.find("border:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 7))) + wsRule.noBorder = !*X; + } else if ((delim = rule.find("shadow:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 7))) + wsRule.noShadow = !*X; + } else if ((delim = rule.find("rounding:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 9))) + wsRule.noRounding = !*X; + } else if ((delim = rule.find("decorate:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 9))) + wsRule.decorate = *X; + } else if ((delim = rule.find("monitor:")) != std::string::npos) wsRule.monitor = rule.substr(delim + 8); - else if ((delim = rule.find("default:")) != std::string::npos) - wsRule.isDefault = configStringToInt(rule.substr(delim + 8)); - else if ((delim = rule.find("persistent:")) != std::string::npos) - wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); - else if ((delim = rule.find("defaultName:")) != std::string::npos) + else if ((delim = rule.find("default:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 8))) + wsRule.isDefault = *X; + } else if ((delim = rule.find("persistent:")) != std::string::npos) { + CHECK_OR_THROW(configStringToInt(rule.substr(delim + 11))) + wsRule.isPersistent = *X; + } else if ((delim = rule.find("defaultName:")) != std::string::npos) wsRule.defaultName = rule.substr(delim + 12); - else if ((delim = rule.find(ruleOnCreatedEmpty)) != std::string::npos) - wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmptyLen)); - else if ((delim = rule.find("layoutopt:")) != std::string::npos) { + else if ((delim = rule.find(ruleOnCreatedEmpty)) != std::string::npos) { + CHECK_OR_THROW(cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmptyLen))) + wsRule.onCreatedEmptyRunCmd = *X; + } else if ((delim = rule.find("layoutopt:")) != std::string::npos) { std::string opt = rule.substr(delim + 10); if (!opt.contains(":")) { // invalid @@ -2668,6 +2682,8 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin return {}; }; +#undef CHECK_OR_THROW + CVarList rulesList{rules, 0, ',', true}; for (auto const& r : rulesList) { const auto R = assignRule(r); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 1b94296f..4d3c2be4 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1286,7 +1286,7 @@ std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { return "ok"; } - const CColor COLOR = configStringToInt(vars[1]); + const CColor COLOR = configStringToInt(vars[1]).value_or(0); for (size_t i = 2; i < vars.size(); ++i) errorMessage += vars[i] + ' '; @@ -1539,7 +1539,7 @@ std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { time = std::stoi(TIME); } catch (std::exception& e) { return "invalid arg 2"; } - CColor color = configStringToInt(vars[3]); + CColor color = configStringToInt(vars[3]).value_or(0); size_t msgidx = 4; float fontsize = 13.f; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index cd1c4742..40491123 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -400,7 +400,7 @@ void CLayerSurface::applyRules() { } else if (rule.rule.starts_with("xray")) { CVarList vars{rule.rule, 0, ' '}; try { - xray = configStringToInt(vars[1]); + xray = configStringToInt(vars[1]).value_or(false); } catch (...) {} } else if (rule.rule.starts_with("animation")) { CVarList vars{rule.rule, 2, 's'}; diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index e74e13a2..33e6a5f8 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -672,8 +672,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { // Basic form has only two colors, everything else can be parsed as a gradient if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { - m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority); - m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority); + m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority); + m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority); return; } @@ -685,9 +685,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } else if (token.contains("deg")) inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0); else if (active) - activeBorderGradient.m_vColors.push_back(configStringToInt(token)); + activeBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); else - inactiveBorderGradient.m_vColors.push_back(configStringToInt(token)); + inactiveBorderGradient.m_vColors.push_back(configStringToInt(token).value_or(0)); } // Includes sanity checks for the number of colors in each gradient diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 80681826..fa2f84ab 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -691,15 +691,15 @@ int64_t getPPIDof(int64_t pid) { #endif } -int64_t configStringToInt(const std::string& VALUE) { - auto parseHex = [](const std::string& value) -> int64_t { +std::expected configStringToInt(const std::string& VALUE) { + auto parseHex = [](const std::string& value) -> std::expected { try { size_t position; auto result = stoll(value, &position, 16); if (position == value.size()) return result; } catch (const std::exception&) {} - throw std::invalid_argument("invalid hex " + value); + return std::unexpected("invalid hex " + value); }; if (VALUE.starts_with("0x")) { // Values with 0x are hex @@ -718,18 +718,25 @@ int64_t configStringToInt(const std::string& VALUE) { auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); rolling = rolling.substr(rolling.find(',') + 1); uint8_t a = 0; + + if (!r || !g || !b) + return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); + try { a = std::round(std::stof(trim(rolling.substr(0, rolling.find(',')))) * 255.f); - } catch (std::exception& e) { throw std::invalid_argument("failed parsing " + VALUEWITHOUTFUNC); } + } catch (std::exception& e) { return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); } - return a * (Hyprlang::INT)0x1000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + return a * (Hyprlang::INT)0x1000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b; } else if (VALUEWITHOUTFUNC.length() == 8) { const auto RGBA = parseHex(VALUEWITHOUTFUNC); + + if (!RGBA) + return RGBA; // now we need to RGBA -> ARGB. The config holds ARGB only. - return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); + return (*RGBA >> 8) + 0x1000000 * (*RGBA & 0xFF); } - throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); + return std::unexpected("rgba() expects length of 8 characters (4 bytes) or 4 comma separated values"); } else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) { const auto VALUEWITHOUTFUNC = trim(VALUE.substr(4, VALUE.length() - 5)); @@ -744,12 +751,16 @@ int64_t configStringToInt(const std::string& VALUE) { rolling = rolling.substr(rolling.find(',') + 1); auto b = configStringToInt(trim(rolling.substr(0, rolling.find(',')))); - return (Hyprlang::INT)0xFF000000 + r * (Hyprlang::INT)0x10000 + g * (Hyprlang::INT)0x100 + b; + if (!r || !g || !b) + return std::unexpected("failed parsing " + VALUEWITHOUTFUNC); + + return (Hyprlang::INT)0xFF000000 + *r * (Hyprlang::INT)0x10000 + *g * (Hyprlang::INT)0x100 + *b; } else if (VALUEWITHOUTFUNC.length() == 6) { - return parseHex(VALUEWITHOUTFUNC) + 0xFF000000; + auto r = parseHex(VALUEWITHOUTFUNC); + return r ? *r + 0xFF000000 : r; } - throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); + return std::unexpected("rgb() expects length of 6 characters (3 bytes) or 3 comma separated values"); } else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) { return 1; } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { @@ -757,14 +768,14 @@ int64_t configStringToInt(const std::string& VALUE) { } if (VALUE.empty() || !isNumber(VALUE, false)) - throw std::invalid_argument("cannot parse \"" + VALUE + "\" as an int."); + return std::unexpected("cannot parse \"" + VALUE + "\" as an int."); try { const auto RES = std::stoll(VALUE); return RES; - } catch (std::exception& e) { throw std::invalid_argument(std::string{"stoll threw: "} + e.what()); } + } catch (std::exception& e) { return std::unexpected(std::string{"stoll threw: "} + e.what()); } - return 0; + return std::unexpected("parse error"); } Vector2D configStringToVector2D(const std::string& VALUE) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 34b23746..bb686df4 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -6,6 +6,7 @@ #include "math/Math.hpp" #include #include +#include #include "../SharedDefs.hpp" #include "../macros.hpp" @@ -19,28 +20,28 @@ struct SWorkspaceIDName { std::string name; }; -std::string absolutePath(const std::string&, const std::string&); -void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); -void removeWLSignal(wl_listener*); -std::string escapeJSONStrings(const std::string& str); -bool isDirection(const std::string&); -bool isDirection(const char&); -SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); -std::optional cleanCmdForWorkspace(const std::string&, std::string); -float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); -void logSystemInfo(); -std::string execAndGet(const char*); -int64_t getPPIDof(int64_t pid); -int64_t configStringToInt(const std::string&); -Vector2D configStringToVector2D(const std::string&); -std::optional getPlusMinusKeywordResult(std::string in, float relative); -double normalizeAngleRad(double ang); -std::vector getBacktrace(); -void throwError(const std::string& err); -bool envEnabled(const std::string& env); -int allocateSHMFile(size_t len); -bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); -float stringToPercentage(const std::string& VALUE, const float REL); +std::string absolutePath(const std::string&, const std::string&); +void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); +void removeWLSignal(wl_listener*); +std::string escapeJSONStrings(const std::string& str); +bool isDirection(const std::string&); +bool isDirection(const char&); +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); +std::optional cleanCmdForWorkspace(const std::string&, std::string); +float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); +void logSystemInfo(); +std::string execAndGet(const char*); +int64_t getPPIDof(int64_t pid); +std::expected configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); +std::optional getPlusMinusKeywordResult(std::string in, float relative); +double normalizeAngleRad(double ang); +std::vector getBacktrace(); +void throwError(const std::string& err); +bool envEnabled(const std::string& env); +int allocateSHMFile(size_t len); +bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 995fee17..c9ca90e5 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2972,11 +2972,14 @@ SDispatchResult CKeybindManager::setProp(std::string args) { const auto TOKEN = vars[i]; if (TOKEN.ends_with("deg")) colorData.m_fAngle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0); - else - colorData.m_vColors.push_back(configStringToInt(TOKEN)); + else if (const auto V = configStringToInt(TOKEN); V) + colorData.m_vColors.push_back(*V); } - } else if (VAL != "-1") - colorData.m_vColors.push_back(configStringToInt(VAL)); + } else if (VAL != "-1") { + const auto V = configStringToInt(VAL); + if (V) + colorData.m_vColors.push_back(*V); + } if (PROP == "activebordercolor") PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP); @@ -2993,8 +2996,8 @@ SDispatchResult CKeybindManager::setProp(std::string args) { } else if (auto search = g_pConfigManager->miWindowProperties.find(PROP); search != g_pConfigManager->miWindowProperties.end()) { if (VAL == "unset") search->second(PWINDOW)->unset(PRIORITY_SET_PROP); - else - *(search->second(PWINDOW)) = CWindowOverridableVar((int)configStringToInt(VAL), PRIORITY_SET_PROP); + else if (const auto V = configStringToInt(VAL); V) + *(search->second(PWINDOW)) = CWindowOverridableVar((int)*V, PRIORITY_SET_PROP); } else { return {.success = false, .error = "Prop not found"}; } diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 745b2593..69ca81cb 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -90,11 +90,14 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr std::string code = probe.assembly.substr(lastAsmNewline, probe.assembly.find("\n", lastAsmNewline) - lastAsmNewline); if (code.contains("%rip")) { - CVarList tokens{code, 0, 's'}; - size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; - size_t minusPresent = tokens[1][0] == '-' ? 1 : 0; - std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent)); - const int32_t OFFSET = (minusPresent ? -1 : 1) * configStringToInt(addr); + CVarList tokens{code, 0, 's'}; + size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; + size_t minusPresent = tokens[1][0] == '-' ? 1 : 0; + std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent)); + auto addrResult = configStringToInt(addr); + if (!addrResult) + return {}; + const int32_t OFFSET = (minusPresent ? -1 : 1) * *addrResult; if (OFFSET == 0) return {}; const uint64_t DESTINATION = currentAddress + OFFSET + len;