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

1

2 Answers 2

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: !
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks but how to i change the operator and numbers to user input?
@zai-tm can't you just pass your user input to applyOperator?
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);

4 Comments

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.
I've added a guard against code injection, which drastically reduces (remove?) the risk
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
That's probably because it runs in a sandboxed environment with eval and new Function disabled, you should consider the other answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.