jessedoyle / duktape.cr

Evaluate JavaScript from Crystal!
MIT License
137 stars 17 forks source link

Possible to disable the print command? #37

Closed g33kidd closed 7 years ago

g33kidd commented 7 years ago

Is it possible? I was just toying around with a discord bot and a simple thing I was messing around with was eval for javascript code. I want to disable the print command if that's possible.

jessedoyle commented 7 years ago

Hi @g33kidd! Thanks for using Duktape!

You can definitely disable any global functions you wish inside the Duktape engine.

Here's one way to remove the function:

sbx = Duktape::Sandbox.new
sbx.push_global_object # push the global object to Duktape's stack
sbx.del_prop_string(-1, "print") # delete the "print" property from the last object on the stack
sbx.pop # cleanup the stack
sbx.eval!("print('Hello');") # => Duktape::ReferenceError "identifier 'print' undefined"

Note that you will likely also want to disable the "alert" function as well as this will print to standard error.

Although it doesn't explicitly mention this approach, Duktape provides great documentation on sandboxing the interpreter here: https://github.com/svaarala/duktape/blob/master/doc/sandboxing.rst.

Furthermore, Duktape 2.X has removed the print and alert functions from the default global object. As I'm working on integrating Duktape 2.0, we may be able to make some of the standard library functions configurable here: https://github.com/jessedoyle/duktape.cr/blob/duktape-2.0/src/duktape/context.cr#L87-L91.

I hope this helps! Please let me know if you have any questions.

jessedoyle commented 7 years ago

@g33kidd - I took a look at your discord bot and I have a few suggestions!

It'll be quite a bit easier to work with the values returned from the interpreter using a Duktape::Runtime instead of directly working with Duktape::Sandbox here.

Something like this may work for you:

require "duktape/runtime"
sbx = Duktape::Sandbox.new(100)
sbx.push_global_object
sbx.del_prop_string(-1, "print")
sbx.del_prop_string(-1, "alert")
sbx.pop
rt = Duktape::Runtime.new(sbx)
code = "['an', 'array', { number: 1 }]"
result = rt.eval(code)
puts result # => ["an", "array", {"number" => 1.0}]

The code above is a demo more than anything, you'll probably have to adapt it to your use case!

g33kidd commented 7 years ago

Oh sweet, thanks! This is exactly what I was looking for. I feel like I've tried to use the RT, but I didn't realize that you can pass in a Sandbox instance. That's cool. Love the lib!