Merge pull request #3130 from proddy/core3

Core3 - fix divide-by-zero in shuntingyard
This commit is contained in:
Proddy
2026-06-22 22:57:53 +02:00
committed by GitHub
6 changed files with 6085 additions and 6050 deletions
+6022 -6022
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -2136,8 +2136,8 @@ packages:
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
nanoid@3.3.13: nanoid@3.3.14:
resolution: {integrity: sha512-sPdqC6ByMVVGvF1ynvvMo0/o+oD1VX7DaHhijt1bFgjvBkHBib4t49GoNDhf2NDta4oeUNlaGbSt5K7qjZ955Q==} resolution: {integrity: sha512-U9kYi5bpVMEI31yC8iw4bJJp0avcHXA0W8/wNfLfnvJYzihQo2ZRPYPvpAAd570HAcCBjCTN7vnr+v4StKl1IQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
@@ -5100,7 +5100,7 @@ snapshots:
ms@2.1.3: {} ms@2.1.3: {}
nanoid@3.3.13: {} nanoid@3.3.14: {}
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
@@ -5299,7 +5299,7 @@ snapshots:
postcss@8.5.15: postcss@8.5.15:
dependencies: dependencies:
nanoid: 3.3.13 nanoid: 3.3.14
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
+19 -19
View File
@@ -318,10 +318,10 @@ function updateMask(entity: any, de: any, dd: any) {
const old_custom_name = dd.nodes[dd_objIndex].cn; const old_custom_name = dd.nodes[dd_objIndex].cn;
console.log( console.log(
'comparing names, old (' + 'comparing names, old (' +
old_custom_name + old_custom_name +
') with new (' + ') with new (' +
new_custom_name + new_custom_name +
')' ')'
); );
if (old_custom_name !== new_custom_name) { if (old_custom_name !== new_custom_name) {
changed = true; changed = true;
@@ -438,9 +438,9 @@ function upgradeImportantMessages(version: string) {
console.log( console.log(
'upgradeImportantMessageType: version=' + 'upgradeImportantMessageType: version=' +
version + version +
' type=' + ' type=' +
upgradeImportantMessageType_n upgradeImportantMessageType_n
); );
return { upgradeImportantMessageType: upgradeImportantMessageType_n }; return { upgradeImportantMessageType: upgradeImportantMessageType_n };
} }
@@ -487,17 +487,17 @@ function get_versions() {
console.log( console.log(
'getVersions: current=' + 'getVersions: current=' +
THIS_VERSION + THIS_VERSION +
' stable=' + ' stable=' +
LATEST_STABLE_VERSION + LATEST_STABLE_VERSION +
' (upgradeable=' + ' (upgradeable=' +
(STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') +
') dev=' + ') dev=' +
LATEST_DEV_VERSION + LATEST_DEV_VERSION +
' (upgradeable=' + ' (upgradeable=' +
(DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') +
')' + ')' +
(MOCK_OFFLINE ? ' [offline]' : '') (MOCK_OFFLINE ? ' [offline]' : '')
); );
return data; return data;
} }
@@ -4232,7 +4232,7 @@ let emsesp_schedule = {
id: 5, id: 5,
active: false, active: false,
flags: ScheduleFlag.SCHEDULE_CONDITION, flags: ScheduleFlag.SCHEDULE_CONDITION,
time: 'system/network info/rssi < -70', time: 'system/network/rssi < -70',
cmd_name: 'restart_system', cmd_name: 'restart_system',
name: 'bad_wifi' name: 'bad_wifi'
}, },
+3
View File
@@ -25,6 +25,9 @@ pnpm build-webUI
cd .. cd ..
npx cspell "**" npx cspell "**"
# build files that go into docs folder
# platformio run -e build_modbus # platformio run -e build_modbus
# platformio run -e build_standalone # platformio run -e build_standalone
# run tests
# platformio run -e native-test -t exec # platformio run -e native-test -t exec
+21 -5
View File
@@ -334,9 +334,12 @@ std::deque<Token> shuntingYard(const std::deque<Token> & tokens) {
return queue; return queue;
} }
// check if string is a number // check if string is a number. Must contain at least one digit
bool isnum(const std::string & s) { bool isnum(const std::string & s) {
if (!s.empty() && (s.find_first_not_of("0123456789.") == std::string::npos || (s[0] == '-' && s.find_first_not_of("0123456789.", 1) == std::string::npos))) { if (s.empty() || s.find_first_of("0123456789") == std::string::npos) {
return false;
}
if (s.find_first_not_of("0123456789.") == std::string::npos || (s[0] == '-' && s.find_first_not_of("0123456789.", 1) == std::string::npos)) {
return true; return true;
} }
return false; return false;
@@ -499,6 +502,18 @@ std::string calculate(const std::string & expr) {
} }
break; break;
} }
if (token.str[0] == 'h') {
// hex string to number
if (rhs.empty() || rhs.find_first_not_of("0123456789abcdefABCDEF") != std::string::npos) {
return "";
}
stack.push_back(to_string(std::stoi(rhs, 0, 16)));
break;
}
// bail out on non-numeric operand
if (!isnum(rhs)) {
return "";
}
auto rhd = std::stod(rhs); auto rhd = std::stod(rhs);
switch (token.str[0]) { switch (token.str[0]) {
default: default:
@@ -531,9 +546,6 @@ std::string calculate(const std::string & expr) {
case 'p': case 'p':
stack.push_back(to_string(std::pow(rhd, 2))); stack.push_back(to_string(std::pow(rhd, 2)));
break; break;
case 'h':
stack.push_back(to_string(std::stoi(rhs, 0, 16)));
break;
case 'x': case 'x':
stack.push_back(to_hex(static_cast<int>(rhd))); stack.push_back(to_hex(static_cast<int>(rhd)));
break; break;
@@ -641,6 +653,10 @@ std::string calculate(const std::string & expr) {
stack.push_back(lhs + rhs); stack.push_back(lhs + rhs);
break; break;
} }
// bail out on non-numeric operands
if (!isnum(lhs) || !isnum(rhs)) {
return "";
}
auto lhd = std::stod(lhs); auto lhd = std::stod(lhs);
auto rhd = std::stod(rhs); auto rhd = std::stod(rhs);
switch (token.str[0]) { switch (token.str[0]) {
+16
View File
@@ -107,6 +107,19 @@ void shuntingYard_test25() {
run_shuntingYard_test("hello world!", "'hello world!'"); run_shuntingYard_test("hello world!", "'hello world!'");
} }
// non-numeric operands must not crash. should return empty string
void shuntingYard_test26() {
run_shuntingYard_test("", "info/x");
}
void shuntingYard_test27() {
run_shuntingYard_test("", "info-x");
}
void shuntingYard_test28() {
run_shuntingYard_test("", "-x");
}
void run_shuntingYard_tests() { void run_shuntingYard_tests() {
RUN_TEST(shuntingYard_test1); RUN_TEST(shuntingYard_test1);
RUN_TEST(shuntingYard_test2); RUN_TEST(shuntingYard_test2);
@@ -133,4 +146,7 @@ void run_shuntingYard_tests() {
RUN_TEST(shuntingYard_test23); RUN_TEST(shuntingYard_test23);
RUN_TEST(shuntingYard_test24); RUN_TEST(shuntingYard_test24);
RUN_TEST(shuntingYard_test25); RUN_TEST(shuntingYard_test25);
RUN_TEST(shuntingYard_test26);
RUN_TEST(shuntingYard_test27);
RUN_TEST(shuntingYard_test28);
} }