Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eval_in

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eval_in

  • 0.2.0
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Build Status

EvalIn

Safely evaluates code (Ruby and others) by sending it through https://eval.in

Example

It's this simple:

require 'eval_in'

result = EvalIn.call 'puts "hello, #{gets}"', stdin: 'world', language: "ruby/mri-2.1"

result.output             # => "hello, world\n"
result.exitstatus         # => 0
result.url                # => "https://eval.in/182711.json"
result.language           # => "ruby/mri-2.1"
result.language_friendly  # => "Ruby — MRI 2.1"
result.code               # => "puts \"hello, \#{gets}\""
result.status             # => "OK (0.064 sec real, 0.073 sec wall, 9 MB, 21 syscalls)"

Docs are here.

What languages can this run?

Ruby ruby/mri-1.0
ruby/mri-1.8.7
ruby/mri-1.9.3
ruby/mri-2.0.0
ruby/mri-2.1
C c/gcc-4.4.3
c/gcc-4.9.1
C++ c++/c++11-gcc-4.9.1
c++/gcc-4.4.3
c++/gcc-4.9.1
CoffeeScript coffeescript/node-0.10.29-coffee-1.7.1
Fortran fortran/f95-4.4.3
Haskell haskell/hugs98-sep-2006
Io io/io-20131204
JavaScript javascript/node-0.10.29
Lua lua/lua-5.1.5
lua/lua-5.2.3
OCaml ocaml/ocaml-4.01.0
PHP php/php-5.5.14
Pascal pascal/fpc-2.6.4
Perl perl/perl-5.20.0
Python python/cpython-2.7.8
python/cpython-3.4.1
Slash slash/slash-head
x86 Assembly assembly/nasm-2.07

Mocking for non-prod environments

Wiring the mock in

The mock that is provided will need to be set into place. If the code is directly doing EvalIn.call(...), then it is a hard dependency, and there is no ablity to set the mock into place.

You will need to structure your code such that it receives the eval_in service as an argument, or looks it up in some configuration or something (I strongly prefer the former). This will allow your test environment to give it a mock that tests that it works in all the edge cases, or is just generally benign (doesn't make real http request in tests), your dev environment to give it an EvalIn that looks so close to the real one you wouldn't even know, and your prod environment to give it the actual EvalIn that actually uses the service.

If this is still unclear, here is an example:

# == before: hard dependency prevents you from giving a mock ==
def get_output(code)
  EvalIn.call(code, language: 'ruby/mri-2.1').output
end

# == after: receive the thing you're talking to ==
def get_output(eval_in, code)
  eval_in.call(code, language: 'ruby/mri-2.1').output
end

# in test, you call like this
output = 'the output'
assert_equal output, get_output(EvalIn::Mock.new(result: EvalIn::Result.new(output: output)), 'some code')

# in prod you call like this:
get_output(EvalIn, params[:code_sample])

# in dev you call like this:
get_output(EvalIn::Mock.new(languages: {'ruby/mri-2.1' => {program: RbConfig.ruby, args: []}}),
           params[:code_sample])

# Now those last_two are probably in the same controller, right?
# How do you get it to do the right thing in the right env, then?
# well, you pass it to your controller, the same way you passed the `get_output`
# for example, you might do this in a rack middleware,
# then have it get the service from the `env` hash
# or set it in an environment initializer

The provided mock

For a test or dev env where you don't care about correctness, just that it does something that looks real, you can make a mock that has a Result, instantiated with any values you care about.

require 'eval_in/mock'
eval_in = EvalIn::Mock.new(result: EvalIn::Result.new(code: 'injected code', output: 'the output')) 

eval_in.call('overridden code', language: 'irrelevant')
# => #<EvalIn::Result:0x007fb503a7a5e8
#     @code="injected code",
#     @exitstatus=-1,
#     @language="",
#     @language_friendly="",
#     @output="the output",
#     @status="",
#     @url="">

If you want your environment to behave approximately like the real eval_in, you can instantiate a mock that knows how to evaluate code locally. This is necessary, because it doesn't know how to execute these languages (eval.in does that, it just knows how to talk to eval.in). So you must provide it with a list of languages and how to execute them

This is probably idea for a dev environment, the results will be the most realistic.

NOTE THAT THIS DOES NOT WORK ON JRUBY

require 'eval_in/mock'

# a mock that can execute Ruby code and C code
eval_in = EvalIn::Mock.new(languages: {
  'ruby/mri-2.1' => {program: RbConfig.ruby,
                     args: []
                    },
  'c/gcc-4.9.1'  => {program: RbConfig.ruby,
                     args: ['-e',
                            'system "gcc -x c -o /tmp/eval_in_c_example #{ARGV.first}"
                             exec   "/tmp/eval_in_c_example"']
                    },
})

eval_in.call 'puts "hello from ruby!"; exit 123', language: 'ruby/mri-2.1'
# => #<EvalIn::Result:0x007fb503a7d518
#     @code="puts \"hello from ruby!\"; exit 123",
#     @exitstatus=123,
#     @language="ruby/mri-2.1",
#     @language_friendly="ruby/mri-2.1",
#     @output="hello from ruby!\n",
#     @status="OK (0.072 sec real, 0.085 sec wall, 8 MB, 19 syscalls)",
#     @url="https://eval.in/207744.json">

eval_in.call '#include <stdio.h>
int main() {
  puts("hello from c!");
}', language: 'c/gcc-4.9.1'
# => #<EvalIn::Result:0x007fb503a850b0
#     @code="#include <stdio.h>\nint main() {\n  puts(\"hello from c!\");\n}",
#     @exitstatus=0,
#     @language="c/gcc-4.9.1",
#     @language_friendly="c/gcc-4.9.1",
#     @output="hello from c!\n",
#     @status="OK (0.072 sec real, 0.085 sec wall, 8 MB, 19 syscalls)",
#     @url="https://eval.in/207744.json">

You can also provide a callback that will be invoked to handle the request. This is probably ideal for testing more nuanced edge cases that the mock doesn't inherently provide the ability to do.

require 'eval_in/mock'
eval_in = EvalIn::Mock.new on_call: -> code, options { raise EvalIn::RequestError, 'does my code do the right thing in the event of an exception?' }

eval_in.call('code', language: 'any') rescue $! # => #<EvalIn::RequestError: does my code do the right thing in the event of an exception?>

Attribution

Thanks to Charlie Sommerville for making eval-in.

Thanks to Mon Oui, I partially stole the first version of the implementation from his gem cinch-eval-in

Contributing

Fork it, make your changes, send me a pull request. Make sure your code is tested and all tests pass.

Run tests with bundle exec rspec, run integration tests with bundle exec rspec -t integration.

WTFPL License

Copyright (C) 2014 Josh Cheek <josh.cheek@gmail.com>

This program is free software. It comes without any warranty,
to the extent permitted by applicable law.
You can redistribute it and/or modify it under the terms of the
Do What The Fuck You Want To Public License,
Version 2, as published by Sam Hocevar.
See http://www.wtfpl.net/ for more details.

FAQs

Package last updated on 21 Oct 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc