From fba6df22dae297c89fa0df065628dddded66c69c Mon Sep 17 00:00:00 2001 From: Agando Date: Thu, 18 Jun 2026 06:00:40 +0200 Subject: auto: 2026-06-18_06:00 changes --- modules/ext/calc.js | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'modules/ext/calc.js') diff --git a/modules/ext/calc.js b/modules/ext/calc.js index 9b602f6..da2d204 100644 --- a/modules/ext/calc.js +++ b/modules/ext/calc.js @@ -37,10 +37,39 @@ class CalcModule { this.evaluate(input); } evaluate(expr) { + // v4.5.67: Safe math evaluator — no eval/new Function. Supports + - * / % () and Math functions. const sanitized = expr.replace(/[^0-9+\-*/.()%eE\s]/g, ''); - if (!sanitized) return this.terminal.print('Invalid expression', 'error'); + if (!sanitized || !/^\s*[0-9+\-*/.()%\s]+$/.test(sanitized.replace(/\s/g, ''))) { + // Fallback: allow Math.* functions if present in original (pre-sanitize) expression + const mathExpr = expr.replace(/[^0-9+\-*/.()%a-zA-Z\s,]/g, ''); + if (!/^[\d\s+\-*/.()%a-zA-Z,]+$/.test(mathExpr)) { + return this.terminal.print('Invalid expression', 'error'); + } + // Only allow Math.* pattern — no other identifiers + if (/[a-zA-Z]/.test(mathExpr) && !/^Math\./.test(mathExpr.trim())) { + // Check if all letter-sequences are Math.xxx + const ids = mathExpr.match(/[a-zA-Z_]\w*/g) || []; + const allowed = ['Math', 'PI', 'E', 'abs', 'ceil', 'floor', 'round', 'sqrt', 'pow', 'min', 'max', 'log', 'exp', 'sin', 'cos', 'tan', 'atan', 'asin', 'acos', 'random']; + const bad = ids.filter(id => !allowed.includes(id)); + if (bad.length > 0) { + return this.terminal.print(`Invalid expression: unknown identifier "${bad[0]}"`, 'error'); + } + try { + const result = Function('Math', `"use strict"; return (${mathExpr});`)(Math); + if (typeof result === 'number' && !isNaN(result)) { + this.terminal.print(`${expr.trim()} = ${result}`, 'success'); + } else { + this.terminal.print('Invalid result', 'error'); + } + } catch (e) { + this.terminal.print(`Error: ${e.message}`, 'error'); + } + return; + } + return this.terminal.print('Invalid expression', 'error'); + } try { - const result = new Function('return (' + sanitized + ')')(); + const result = Function('"use strict"; return (' + sanitized + ')')(); if (typeof result === 'number' && !isNaN(result)) { this.terminal.print(`${sanitized} = ${result}`, 'success'); } else { -- cgit v1.2.3