0

How do i convert a string into an operator in javascript without using eval()?

I've tried something like this:

        const num1 = parseInt(args[0])
        const num2 = parseInt(args[2])
        const operation = (args[1])
        const answer = eval(num1 + operation + num2)
        message.channel.send(answer)

But i don't think discord.js accepts eval() because the bot didn't reply

zai-tm
  • 33
  • 5
  • 1
    Does this answer your question? [How can I convert a string into a math operator in javascript](https://stackoverflow.com/questions/13077923/how-can-i-convert-a-string-into-a-math-operator-in-javascript) – Ashish Kadam May 03 '21 at 16:35

2 Answers2

4

You could use the Function constructor, but your shouldn't, as it will attempt to run any arbitrary code contained within the string. A safer choice would be to use a switch statement and whitelist the supported operations -

function applyOperator(op, a, b)
{ switch (op)
  { case "+": return a + b
    case "-": return a - b
    case "*": return a * b
    case "/": return a / b
    case "%": return a % b
    case "^": return Math.pow(a, b)
    default: throw Error(`unsupported operator: ${op}`)
  }
}

console.log(applyOperator("*", 3, 5))
console.log(applyOperator("-", 3, 5))
console.log(applyOperator("+", 3, 5))
console.log(applyOperator("!", 3, 5))
15
-2
8
Error: unsupported operator: !

Another safe option is to define a set of supportedOperations. When calling applyOperation, check if the op is supported and call it, otherwise throw an error -

const supportedOperations =
  { "+": (a, b) => a + b
  , "-": (a, b) => a - b
  , "*": (a, b) => a * b
  , "/": (a, b) => a / b
  , "%": (a, b) => a % b
  , "^": (a, b) => Math.pow(a, b)
  }

function applyOperator(op, a, b)
{ if (op in supportedOperations)
    return supportedOperations[op](a, b)
  else
    throw Error(`unsupported operator: ${op}`)
}

console.log(applyOperator("*", 3, 5))
console.log(applyOperator("-", 3, 5))
console.log(applyOperator("+", 3, 5))
console.log(applyOperator("!", 3, 5))
15
-2
8
Error: unsupported operator: !
Mulan
  • 129,518
  • 31
  • 228
  • 259
1

You could also use the Function constructor:

const num1 = 7
const num2 = 8
const operation = '*'
const allowedOperations = ['*', '+', '/'];

// Mitigate the critical code injection vulnerability
if (!allowedOperations.includes(operation))
  throw 'The operator is not part of the allowed ones';

const applyOperator = new Function('a', 'b', `return a ${operation} b;`);
const answer = applyOperator(num1, num2);

console.log(answer);
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • 1
    `eval` and `Function` execute arbitrary code. i would highly recommend safer alternatives as presented in my answer. because this code is part of a bot, it is crucial to protect against malicious user input. – Mulan May 03 '21 at 16:49
  • I've added a guard against code injection, which drastically reduces (remove?) the risk – Guerric P May 03 '21 at 17:07
  • I'm trying to do it with user input because it's a discord bot. I tried to change the consts to args but it didn't work – zai-tm May 03 '21 at 17:18
  • That's probably because it runs in a sandboxed environment with `eval` and `new Function` disabled, you should consider the other answer – Guerric P May 03 '21 at 17:29