From 65151d6f0ce538b4fb25477784783b07ffaedc25 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Mon, 11 Jan 2021 13:24:17 -0600 Subject: [PATCH 01/73] send 400 when a bad language was supplied --- api/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api/main.go b/api/main.go index 51741d6..acd0f69 100644 --- a/api/main.go +++ b/api/main.go @@ -113,6 +113,7 @@ func Execute(res http.ResponseWriter, req *http.Request) { pres, _ := json.Marshal(problem) + res.WriteHeader(http.StatusBadRequest) res.Write(pres) } From 13a932d438e210e3905aee7e5588f3e0669f4878 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Tue, 12 Jan 2021 12:43:20 -0600 Subject: [PATCH 02/73] clean up other accessible tmp directories --- lxc/execute | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lxc/execute b/lxc/execute index 45a7f46..03cb6a9 100755 --- a/lxc/execute +++ b/lxc/execute @@ -147,6 +147,9 @@ lxc-attach --clear-env -n piston -- \ /bin/bash -l -c "\ for i in {1..100}; do pkill -u runner$newinc --signal SIGKILL; done ;\ find /tmp -user runner$newinc -exec /bin/rm -rf {} \;\ + find /var/tmp -user runner$newinc -exec /bin/rm -rf {} \;\ + find /dev/shm -user runner$newinc -exec /bin/rm -rf {} \;\ + find /run/lock -user runner$newinc -exec /bin/rm -rf {} \;\ " > /dev/null 2>&1 & rm -rf $basepath/tmp/$epoch From c3416b8628dd769e9e782d42a993e3a680350aea Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Tue, 12 Jan 2021 12:50:50 -0600 Subject: [PATCH 03/73] terminate each tmp cleanup --- lxc/execute | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lxc/execute b/lxc/execute index 03cb6a9..704202f 100755 --- a/lxc/execute +++ b/lxc/execute @@ -146,10 +146,10 @@ timeout -s KILL 10 \ lxc-attach --clear-env -n piston -- \ /bin/bash -l -c "\ for i in {1..100}; do pkill -u runner$newinc --signal SIGKILL; done ;\ - find /tmp -user runner$newinc -exec /bin/rm -rf {} \;\ - find /var/tmp -user runner$newinc -exec /bin/rm -rf {} \;\ - find /dev/shm -user runner$newinc -exec /bin/rm -rf {} \;\ - find /run/lock -user runner$newinc -exec /bin/rm -rf {} \;\ + find /tmp -user runner$newinc -exec /bin/rm -rf {} \; ;\ + find /var/tmp -user runner$newinc -exec /bin/rm -rf {} \; ;\ + find /dev/shm -user runner$newinc -exec /bin/rm -rf {} \; ;\ + find /run/lock -user runner$newinc -exec /bin/rm -rf {} \; ;\ " > /dev/null 2>&1 & rm -rf $basepath/tmp/$epoch From 1441b5ef6f953bcfc4f1c5e884990afcade5e8a9 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Tue, 12 Jan 2021 13:45:40 -0600 Subject: [PATCH 04/73] delete nim --- api/main.go | 1 - lxc/execute | 3 --- lxc/executors/nim | 4 ---- lxc/test_all_lxc | 2 -- lxc/versions | 4 ---- readme.md | 14 +------------- 6 files changed, 1 insertion(+), 27 deletions(-) delete mode 100755 lxc/executors/nim diff --git a/api/main.go b/api/main.go index acd0f69..d328363 100644 --- a/api/main.go +++ b/api/main.go @@ -83,7 +83,6 @@ func Execute(res http.ResponseWriter, req *http.Request) { "lua", "nasm", "asm", "nasm64", "asm64", - "nim", "node", "javascript", "js", "perl", "pl", "php", diff --git a/lxc/execute b/lxc/execute index 704202f..dd3b3c5 100755 --- a/lxc/execute +++ b/lxc/execute @@ -90,9 +90,6 @@ case "$lang" in "nasm64" | "asm64") bin=nasm64 ;; -"nim") - bin=nim - ;; "node" | "js" | "javascript") bin=node ;; diff --git a/lxc/executors/nim b/lxc/executors/nim deleted file mode 100755 index c6e6caf..0000000 --- a/lxc/executors/nim +++ /dev/null @@ -1,4 +0,0 @@ -cd /tmp/$2 -timeout -s KILL 10 nim --hints:off c code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./code" - diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 8e7130c..c7f0b28 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -31,8 +31,6 @@ echo 'testing asm 32 bit' ../execute asm test.nasm echo 'testing asm 64 bit' ../execute asm64 test64.nasm -echo 'testing nim' -../execute nim test.nim echo 'testing php' ../execute php test.php echo 'testing perl' diff --git a/lxc/versions b/lxc/versions index 12b5f76..cbfd824 100755 --- a/lxc/versions +++ b/lxc/versions @@ -69,10 +69,6 @@ echo 'nasm' lxc-attach --clear-env -n piston -- /bin/bash -l -c "nasm -version" echo '---' -echo 'nim' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "nim -v | head -n1" -echo '---' - echo 'node' lxc-attach --clear-env -n piston -- /bin/bash -l -c "node --version" echo '---' diff --git a/readme.md b/readme.md index a7ccaff..d66f8e3 100644 --- a/readme.md +++ b/readme.md @@ -88,7 +88,7 @@ source /opt/.profile # install paradoc # this is not a binary, it is a python module -# therefore it cannot be run directly as it requires python3 to be installed +# therefore it cannot be run directly as it requires python3 to be installed cd /opt && mkdir paradoc && cd paradoc git clone https://github.com/betaveros/paradoc.git echo 'export PYTHONPATH=$PYTHONPATH:/opt/paradoc/paradoc' >> /opt/.profile @@ -249,18 +249,6 @@ echo 'export DENO_INSTALL="/opt/.deno"' >> /opt/.profile echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /opt/.profile source /opt/.profile -# install nim -# final binary: /opt/nim/bin/nim -# get version: /opt/nim/bin/nim -v -cd /opt && mkdir nim && cd nim -wget https://nim-lang.org/download/nim-1.4.0-linux_x64.tar.xz -unxz nim-1.4.0-linux_x64.tar.xz -tar -xf nim-1.4.0-linux_x64.tar -cd nim-1.4.0 -./install.sh /opt -echo 'export PATH=$PATH:/opt/nim/bin' >> /opt/.profile -source /opt/.profile - # create runnable users and apply limits for i in {1..150}; do useradd -M runner$i From 9c985a1e5b83e321fb85e4d8f075d2b31aebcd97 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Tue, 12 Jan 2021 15:11:14 -0600 Subject: [PATCH 05/73] move docs to prepare for image distribution, clean up /var/lock --- lxc/execute | 1 + readme.md | 258 +---------------------------------------------- var/install.txt | 259 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 257 deletions(-) create mode 100644 var/install.txt diff --git a/lxc/execute b/lxc/execute index dd3b3c5..efc375d 100755 --- a/lxc/execute +++ b/lxc/execute @@ -145,6 +145,7 @@ lxc-attach --clear-env -n piston -- \ for i in {1..100}; do pkill -u runner$newinc --signal SIGKILL; done ;\ find /tmp -user runner$newinc -exec /bin/rm -rf {} \; ;\ find /var/tmp -user runner$newinc -exec /bin/rm -rf {} \; ;\ + find /var/lock -user runner$newinc -exec /bin/rm -rf {} \; ;\ find /dev/shm -user runner$newinc -exec /bin/rm -rf {} \; ;\ find /run/lock -user runner$newinc -exec /bin/rm -rf {} \; ;\ " > /dev/null 2>&1 & diff --git a/readme.md b/readme.md index d66f8e3..c3fcd5d 100644 --- a/readme.md +++ b/readme.md @@ -13,263 +13,7 @@ about the request format but rather than using the local URLs, use the following Important Note: The Piston API is rate limited to 5 requests per second #### Installation -``` -# clone and enter repo -git clone https://github.com/engineer-man/piston -cd piston/lxc - -# install dependencies - -# centos: -yum install -y epel-release -yum install -y lxc lxc-templates debootstrap libvirt -systemctl start libvirtd - -# ubuntu server 18.04: -apt install lxc lxc-templates debootstrap libvirt0 - -# arch: -sudo pacman -S lxc libvirt unzip - -# everything else: -# not documented, please open pull requests with commands for debian/arch/macos - -# create and start container -lxc-create -t download -n piston -- --dist ubuntu --release bionic --arch amd64 -./start - -# open a shell to the container -./shell - -# install all necessary piston dependencies -echo 'source /opt/.profile' >> /opt/.bashrc -echo 'export HOME=/opt' >> /opt/.profile -echo 'export TERM=linux' >> /opt/.profile -echo 'export PATH=$PATH:/opt/.local/bin' >> /opt/.profile -export HOME=/opt -export TERM=linux -sed -i 's/\/root/\/opt/' /etc/passwd -sed -i \ - 's/http:\/\/archive.ubuntu.com\/ubuntu/http:\/\/mirror.math.princeton.edu\/pub\/ubuntu/' \ - /etc/apt/sources.list -apt-get update -apt-get install -y \ - nano wget build-essential pkg-config libxml2-dev \ - libsqlite3-dev mono-complete curl cmake libpython2.7-dev \ - ruby libtinfo-dev unzip - -# install python2 -# final binary: /opt/python2/Python-2.7.17/python -# get version: /opt/python2/Python-2.7.17/python -V -cd /opt && mkdir python2 && cd python2 -wget https://www.python.org/ftp/python/2.7.17/Python-2.7.17.tar.xz -unxz Python-2.7.17.tar.xz -tar -xf Python-2.7.17.tar -cd Python-2.7.17 -./configure -# open Modules/Setup and uncomment zlib line -make -echo 'export PATH=$PATH:/opt/python2/Python-2.7.17' >> /opt/.profile -source /opt/.profile - -# install python3 -# final binary: /opt/python3/Python-3.8.2/python -# get version: /opt/python3/Python-3.8.2/python -V -cd /opt && mkdir python3 && cd python3 -wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz -unxz Python-3.8.2.tar.xz -tar -xf Python-3.8.2.tar -cd Python-3.8.2 -./configure -make -ln -s python python3.8 -echo 'export PATH=$PATH:/opt/python3/Python-3.8.2' >> /opt/.profile -source /opt/.profile - -# install paradoc -# this is not a binary, it is a python module -# therefore it cannot be run directly as it requires python3 to be installed -cd /opt && mkdir paradoc && cd paradoc -git clone https://github.com/betaveros/paradoc.git -echo 'export PYTHONPATH=$PYTHONPATH:/opt/paradoc/paradoc' >> /opt/.profile -source /opt/.profile - -# install node.js -# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/node -# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/node -v -cd /opt && mkdir nodejs && cd nodejs -wget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz -unxz node-v12.16.1-linux-x64.tar.xz -tar -xf node-v12.16.1-linux-x64.tar -echo 'export PATH=$PATH:/opt/nodejs/node-v12.16.1-linux-x64/bin' >> /opt/.profile -source /opt/.profile - -# install typescript -# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc -# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc -v -/opt/nodejs/node-v12.16.1-linux-x64/bin/npm i -g typescript - -# install golang -# final binary: /opt/go/go/bin/go -# get version: /opt/go/go/bin/go version -cd /opt && mkdir go && cd go -wget https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz -tar -xzf go1.14.1.linux-amd64.tar.gz -echo 'export PATH=$PATH:/opt/go/go/bin' >> /opt/.profile -echo 'export GOROOT=/opt/go/go' >> /opt/.profile -echo 'export GOCACHE=/tmp' >> /opt/.profile -source /opt/.profile - -# install php -# final binary: /usr/local/bin/php -# get version: /usr/local/bin/php -v -cd /opt && mkdir php && cd php -wget https://www.php.net/distributions/php-7.4.4.tar.gz -tar -xzf php-7.4.4.tar.gz -cd php-7.4.4 -./configure -make -make install - -# install rust -# final binary: /opt/.cargo/bin/rustc -# get version: /opt/.cargo/bin/rustc --version -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -echo 'export PATH=$PATH:/opt/.cargo/bin' >> /opt/.profile -source /opt/.profile - -# install swift -# final binary: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift -# get version: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift --version -cd /opt && mkdir swift && cd swift -wget https://swift.org/builds/swift-5.1.5-release/ubuntu1804/swift-5.1.5-RELEASE/swift-5.1.5-RELEASE-ubuntu18.04.tar.gz -tar -xzf swift-5.1.5-RELEASE-ubuntu18.04.tar.gz -echo 'export PATH=$PATH:/opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin' >> /opt/.profile -source /opt/.profile - -# install nasm -# final binary: /opt/nasm/nasm-2.14.02/nasm -# get version: /opt/nasm/nasm-2.14.02/nasm -v -cd /opt && mkdir nasm && cd nasm -wget https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz -tar -xzf nasm-2.14.02.tar.gz -cd nasm-2.14.02 -./configure -make -echo 'export PATH=$PATH:/opt/nasm/nasm-2.14.02' >> /opt/.profile -source /opt/.profile - -# install java -# final binary: /opt/java/jdk-14/bin/java -# get version: /opt/java/jdk-14/bin/java -version -cd /opt && mkdir java && cd java -wget https://download.java.net/java/GA/jdk14/076bab302c7b4508975440c56f6cc26a/36/GPL/openjdk-14_linux-x64_bin.tar.gz -tar -xzf openjdk-14_linux-x64_bin.tar.gz -echo 'export PATH=$PATH:/opt/java/jdk-14/bin' >> /opt/.profile -source /opt/.profile - -# install jelly -cd /opt && mkdir jelly && cd jelly -wget https://github.com/DennisMitchell/jellylanguage/archive/master.zip -unzip master.zip -cd jellylanguage-master -pip3.8 install . - -# install julia -# final binary: /opt/julia/julia-1.5.0/bin/julia -# get version: /opt/julia/julia-1.5.0/bin/julia --version -cd /opt && mkdir julia && cd julia -wget https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.0-linux-x86_64.tar.gz -tar -xzf julia-1.5.0-linux-x86_64.tar.gz -echo 'export PATH=$PATH:/opt/julia/julia-1.5.0/bin' >> /opt/.profile -source /opt/.profile - -# install kotlin -# final binary: /opt/kotlinc/bin/kotlinc -# get version: /opt/kotlinc/bin/kotlinc -version -cd /opt -wget https://github.com/JetBrains/kotlin/releases/download/v1.4.10/kotlin-compiler-1.4.10.zip -unzip kotlin-compiler-1.4.10.zip -rm kotlin-compiler-1.4.10.zip -echo 'export PATH=$PATH:/opt/kotlinc/bin' >> /opt/.profile -source /opt/.profile - -# install elixir and erlang -# final binary: /opt/elixir/bin/elixir -# get version: /opt/elixir/bin/elixir --version -# erlang -cd /opt && mkdir erlang && cd erlang -wget http://erlang.org/download/otp_src_23.0.tar.gz -gunzip -c otp_src_23.0.tar.gz | tar xf - -cd otp_src_23.0 && ./configure -make -echo 'export PATH=$PATH:/opt/erlang/otp_src_23.0/bin' >> /opt/.profile -source /opt/.profile -# elixir -cd /opt && mkdir elixir && cd elixir -wget https://github.com/elixir-lang/elixir/releases/download/v1.10.3/Precompiled.zip -mkdir elixir-1.10.3 && unzip Precompiled.zip -d elixir-1.10.3/ -echo 'export PATH=$PATH:/opt/elixir/elixir-1.10.3/bin' >> /opt/.profile -source /opt/.profile - -# install emacs -# final binary: /opt/emacs/emacs-26.3/src/emacs -# get version: /opt/emacs/emacs-26.3/src/emacs --version -cd /opt && mkdir emacs && cd emacs -wget https://mirrors.ocf.berkeley.edu/gnu/emacs/emacs-26.3.tar.xz -tar -xf emacs-26.3.tar.xz -cd emacs-26.3 -./configure --with-gnutls=no -make -echo 'export PATH=$PATH:/opt/emacs/emacs-26.3/src' >> /opt/.profile -source /opt/.profile - -# install lua -# final binary: /opt/lua/lua54/src/lua -# get version: /opt/lua/lua54/src/lua -v -cd /opt && mkdir lua && cd lua -wget https://sourceforge.net/projects/luabinaries/files/5.4.0/Docs%20and%20Sources/lua-5.4.0_Sources.tar.gz/download -tar -xzf download -cd lua54 -make -echo 'export PATH=$PATH:/opt/lua/lua54/src' >> /opt/.profile -source /opt/.profile - -# install haskell -# final binary: /usr/bin/ghc -# get version: /usr/bin/ghc --version -apt install -y ghc - -# install deno -# final binary: /opt/.deno/bin/deno -# get version: /opt/.deno/bin/deno --version -cd /opt && mkdir deno && cd deno -curl -fsSL https://deno.land/x/install/install.sh | sh -echo 'export DENO_INSTALL="/opt/.deno"' >> /opt/.profile -echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /opt/.profile -source /opt/.profile - -# create runnable users and apply limits -for i in {1..150}; do - useradd -M runner$i - usermod -d /tmp runner$i - echo "runner$i soft nproc 64" >> /etc/security/limits.conf - echo "runner$i hard nproc 64" >> /etc/security/limits.conf - echo "runner$i soft nofile 2048" >> /etc/security/limits.conf - echo "runner$i hard nofile 2048" >> /etc/security/limits.conf -done - -# cleanup -rm -rf /home/ubuntu -chmod 777 /tmp - -# leave container -exit - -# optionally run tests -cd ../tests -./test_all_lxc -``` +Updated installation instructions coming soon. See `var/install.txt` for how to do it from scratch. #### CLI Usage - `lxc/execute [language] [file path] [arg]...` diff --git a/var/install.txt b/var/install.txt new file mode 100644 index 0000000..4f44e22 --- /dev/null +++ b/var/install.txt @@ -0,0 +1,259 @@ +# clone and enter repo +git clone https://github.com/engineer-man/piston +cd piston/lxc + +# install dependencies + +# centos: +yum install -y epel-release +yum install -y lxc lxc-templates debootstrap libvirt +systemctl start libvirtd + +# ubuntu server 18.04: +apt install lxc lxc-templates debootstrap libvirt0 + +# arch: +sudo pacman -S lxc libvirt unzip + +# everything else: +# not documented, please open pull requests with commands for debian/arch/macos + +# create and start container +lxc-create -t download -n piston -- --dist ubuntu --release bionic --arch amd64 +./start + +# open a shell to the container +./shell + +# install all necessary piston dependencies +echo 'source /opt/.profile' >> /opt/.bashrc +echo 'export HOME=/opt' >> /opt/.profile +echo 'export TERM=linux' >> /opt/.profile +echo 'export PATH=$PATH:/opt/.local/bin' >> /opt/.profile +export HOME=/opt +export TERM=linux +sed -i 's/\/root/\/opt/' /etc/passwd +sed -i \ + 's/http:\/\/archive.ubuntu.com\/ubuntu/http:\/\/mirror.math.princeton.edu\/pub\/ubuntu/' \ + /etc/apt/sources.list +apt-get update +apt-get install -y \ + nano wget build-essential pkg-config libxml2-dev \ + libsqlite3-dev mono-complete curl cmake libpython2.7-dev \ + ruby libtinfo-dev unzip git + +# install python2 +# final binary: /opt/python2/Python-2.7.17/python +# get version: /opt/python2/Python-2.7.17/python -V +cd /opt && mkdir python2 && cd python2 +wget https://www.python.org/ftp/python/2.7.17/Python-2.7.17.tar.xz +unxz Python-2.7.17.tar.xz +tar -xf Python-2.7.17.tar +cd Python-2.7.17 +./configure +# open Modules/Setup and uncomment zlib line +make +echo 'export PATH=$PATH:/opt/python2/Python-2.7.17' >> /opt/.profile +source /opt/.profile + +# install python3 +# final binary: /opt/python3/Python-3.8.2/python +# get version: /opt/python3/Python-3.8.2/python -V +cd /opt && mkdir python3 && cd python3 +wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz +unxz Python-3.8.2.tar.xz +tar -xf Python-3.8.2.tar +cd Python-3.8.2 +./configure +make +ln -s python python3.8 +echo 'export PATH=$PATH:/opt/python3/Python-3.8.2' >> /opt/.profile +source /opt/.profile + +# install paradoc +# this is not a binary, it is a python module +# therefore it cannot be run directly as it requires python3 to be installed +cd /opt && mkdir paradoc && cd paradoc +git clone https://github.com/betaveros/paradoc.git +echo 'export PYTHONPATH=$PYTHONPATH:/opt/paradoc/paradoc' >> /opt/.profile +source /opt/.profile + +# install node.js +# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/node +# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/node -v +cd /opt && mkdir nodejs && cd nodejs +wget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz +unxz node-v12.16.1-linux-x64.tar.xz +tar -xf node-v12.16.1-linux-x64.tar +echo 'export PATH=$PATH:/opt/nodejs/node-v12.16.1-linux-x64/bin' >> /opt/.profile +source /opt/.profile + +# install typescript +# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc +# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc -v +/opt/nodejs/node-v12.16.1-linux-x64/bin/npm i -g typescript + +# install golang +# final binary: /opt/go/go/bin/go +# get version: /opt/go/go/bin/go version +cd /opt && mkdir go && cd go +wget https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz +tar -xzf go1.14.1.linux-amd64.tar.gz +echo 'export PATH=$PATH:/opt/go/go/bin' >> /opt/.profile +echo 'export GOROOT=/opt/go/go' >> /opt/.profile +echo 'export GOCACHE=/tmp' >> /opt/.profile +source /opt/.profile + +# install php +# final binary: /usr/local/bin/php +# get version: /usr/local/bin/php -v +cd /opt && mkdir php && cd php +wget https://www.php.net/distributions/php-7.4.4.tar.gz +tar -xzf php-7.4.4.tar.gz +cd php-7.4.4 +./configure +make +make install + +# install rust +# final binary: /opt/.cargo/bin/rustc +# get version: /opt/.cargo/bin/rustc --version +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +echo 'export PATH=$PATH:/opt/.cargo/bin' >> /opt/.profile +source /opt/.profile + +# install swift +# final binary: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift +# get version: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift --version +cd /opt && mkdir swift && cd swift +wget https://swift.org/builds/swift-5.1.5-release/ubuntu1804/swift-5.1.5-RELEASE/swift-5.1.5-RELEASE-ubuntu18.04.tar.gz +tar -xzf swift-5.1.5-RELEASE-ubuntu18.04.tar.gz +echo 'export PATH=$PATH:/opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin' >> /opt/.profile +source /opt/.profile + +# install nasm +# final binary: /opt/nasm/nasm-2.14.02/nasm +# get version: /opt/nasm/nasm-2.14.02/nasm -v +cd /opt && mkdir nasm && cd nasm +wget https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz +tar -xzf nasm-2.14.02.tar.gz +cd nasm-2.14.02 +./configure +make +echo 'export PATH=$PATH:/opt/nasm/nasm-2.14.02' >> /opt/.profile +source /opt/.profile + +# install java +# final binary: /opt/java/jdk-14/bin/java +# get version: /opt/java/jdk-14/bin/java -version +cd /opt && mkdir java && cd java +wget https://download.java.net/java/GA/jdk14/076bab302c7b4508975440c56f6cc26a/36/GPL/openjdk-14_linux-x64_bin.tar.gz +tar -xzf openjdk-14_linux-x64_bin.tar.gz +echo 'export PATH=$PATH:/opt/java/jdk-14/bin' >> /opt/.profile +source /opt/.profile + +# install jelly +cd /opt && mkdir jelly && cd jelly +wget https://github.com/DennisMitchell/jellylanguage/archive/master.zip +unzip master.zip +cd jellylanguage-master +pip3.8 install . + +# install julia +# final binary: /opt/julia/julia-1.5.0/bin/julia +# get version: /opt/julia/julia-1.5.0/bin/julia --version +cd /opt && mkdir julia && cd julia +wget https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.0-linux-x86_64.tar.gz +tar -xzf julia-1.5.0-linux-x86_64.tar.gz +echo 'export PATH=$PATH:/opt/julia/julia-1.5.0/bin' >> /opt/.profile +source /opt/.profile + +# install kotlin +# final binary: /opt/kotlinc/bin/kotlinc +# get version: /opt/kotlinc/bin/kotlinc -version +cd /opt +wget https://github.com/JetBrains/kotlin/releases/download/v1.4.10/kotlin-compiler-1.4.10.zip +unzip kotlin-compiler-1.4.10.zip +rm kotlin-compiler-1.4.10.zip +echo 'export PATH=$PATH:/opt/kotlinc/bin' >> /opt/.profile +source /opt/.profile + +# install elixir and erlang +# final binary: /opt/elixir/bin/elixir +# get version: /opt/elixir/bin/elixir --version +# erlang +cd /opt && mkdir erlang && cd erlang +wget http://erlang.org/download/otp_src_23.0.tar.gz +gunzip -c otp_src_23.0.tar.gz | tar xf - +cd otp_src_23.0 && ./configure +make +echo 'export PATH=$PATH:/opt/erlang/otp_src_23.0/bin' >> /opt/.profile +source /opt/.profile +# elixir +cd /opt && mkdir elixir && cd elixir +wget https://github.com/elixir-lang/elixir/releases/download/v1.10.3/Precompiled.zip +mkdir elixir-1.10.3 && unzip Precompiled.zip -d elixir-1.10.3/ +echo 'export PATH=$PATH:/opt/elixir/elixir-1.10.3/bin' >> /opt/.profile +source /opt/.profile + +# install emacs +# final binary: /opt/emacs/emacs-26.3/src/emacs +# get version: /opt/emacs/emacs-26.3/src/emacs --version +cd /opt && mkdir emacs && cd emacs +wget https://mirrors.ocf.berkeley.edu/gnu/emacs/emacs-26.3.tar.xz +tar -xf emacs-26.3.tar.xz +cd emacs-26.3 +./configure --with-gnutls=no +make +echo 'export PATH=$PATH:/opt/emacs/emacs-26.3/src' >> /opt/.profile +source /opt/.profile + +# install lua +# final binary: /opt/lua/lua54/src/lua +# get version: /opt/lua/lua54/src/lua -v +cd /opt && mkdir lua && cd lua +wget https://sourceforge.net/projects/luabinaries/files/5.4.0/Docs%20and%20Sources/lua-5.4.0_Sources.tar.gz/download +tar -xzf download +cd lua54 +make +echo 'export PATH=$PATH:/opt/lua/lua54/src' >> /opt/.profile +source /opt/.profile + +# install haskell +# final binary: /usr/bin/ghc +# get version: /usr/bin/ghc --version +apt install -y ghc + +# install deno +# final binary: /opt/.deno/bin/deno +# get version: /opt/.deno/bin/deno --version +cd /opt && mkdir deno && cd deno +curl -fsSL https://deno.land/x/install/install.sh | sh +echo 'export DENO_INSTALL="/opt/.deno"' >> /opt/.profile +echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /opt/.profile +source /opt/.profile + +# create runnable users and apply limits +for i in {1..150}; do + useradd -M runner$i + usermod -d /tmp runner$i + echo "runner$i soft nproc 64" >> /etc/security/limits.conf + echo "runner$i hard nproc 64" >> /etc/security/limits.conf + echo "runner$i soft nofile 2048" >> /etc/security/limits.conf + echo "runner$i hard nofile 2048" >> /etc/security/limits.conf +done + +# remove any lingering write access to others +cd /opt +chown -R root: * +chmod -R o-w * + +# cleanup +rm -rf /home/ubuntu +chmod 777 /tmp + +# leave container +exit + +# optionally run tests +./test_all_lxc From e6e1c093d69687bca001fefa7771077528ddf713 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Wed, 13 Jan 2021 01:36:10 -0600 Subject: [PATCH 06/73] update readme, set c to run everything under a runner --- lxc/executors/c | 7 ++++--- readme.md | 13 ++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lxc/executors/c b/lxc/executors/c index 5b3d84c..9800c05 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,3 +1,4 @@ -cd /tmp/$2 -timeout -s KILL 10 gcc -std=c11 -o binary -x c code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + timeout -s KILL 10 gcc -std=c11 -o binary -x c code.code \ + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/readme.md b/readme.md index c3fcd5d..fdf2f54 100644 --- a/readme.md +++ b/readme.md @@ -16,7 +16,7 @@ Important Note: The Piston API is rate limited to 5 requests per second Updated installation instructions coming soon. See `var/install.txt` for how to do it from scratch. #### CLI Usage -- `lxc/execute [language] [file path] [arg]...` +- `lxc/execute [language] [file path] [args]` #### API Usage To use the API, it must first be started. To start the API, run the following: @@ -41,6 +41,9 @@ This endpoint takes no input and returns a JSON array of the currently installed Truncated response sample: ```json +HTTP/1.1 200 OK +Content-Type: application/json + [ { "name": "awk", @@ -74,6 +77,9 @@ source is not provided, a blank file is passed as the source. ``` A typical response when everything succeeds will be similar to the following: ```json +HTTP/1.1 200 OK +Content-Type: application/json + { "ran": true, "language": "js", @@ -83,6 +89,9 @@ A typical response when everything succeeds will be similar to the following: ``` If an invalid language is supplied, a typical response will look like the following: ```json +HTTP/1.1 400 Bad Request +Content-Type: application/json + { "code": "unsupported_language", "message": "whatever is not supported by Piston" @@ -96,6 +105,7 @@ If an invalid language is supplied, a typical response will look like the follow - cpp - csharp - deno +- erlang - elixir - emacs - go @@ -130,6 +140,7 @@ various privilege escalation, denial-of-service, and resource saturation threats - Capping max processes at 64 (resists `:(){ :|: &}:;`, `while True: os.fork()`, etc.) - Capping max files at 2048 (resists various file based attacks) - Mounting all resources read-only (resists `sudo rm -rf --no-preserve-root /`) +- Cleaning up all temp space after each execution (resists out of drive space attacks) - Running as a variety of unprivileged users - Capping runtime execution at 3 seconds - Capping stdout to 65536 characters (resists yes/no bombs and runaway output) From 15b6f6e8d6467c78c5c6f0cbd6755b3e80f9f76c Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Wed, 13 Jan 2021 01:37:47 -0600 Subject: [PATCH 07/73] missing semicolon --- lxc/executors/c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/executors/c b/lxc/executors/c index 9800c05..b993915 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,4 +1,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ - timeout -s KILL 10 gcc -std=c11 -o binary -x c code.code \ + timeout -s KILL 10 gcc -std=c11 -o binary -x c code.code ; \ cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" From b81690a9de48dad02300de715cad5d40067be098 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Wed, 13 Jan 2021 23:45:48 -0600 Subject: [PATCH 08/73] fix jelly, move all executor code to runner permission, introduce stdout/stderr separate output to the api --- api/main.go | 48 ++++++++++++++++++++++++++++++++++++---- lxc/execute | 4 ++-- lxc/executors/c | 2 +- lxc/executors/cpp | 7 +++--- lxc/executors/csharp | 7 +++--- lxc/executors/emacs | 4 ++-- lxc/executors/go | 2 +- lxc/executors/haskell | 7 ++++-- lxc/executors/java | 7 ++++-- lxc/executors/kotlin | 6 +++-- lxc/executors/nasm | 9 ++++---- lxc/executors/nasm64 | 9 ++++---- lxc/executors/rust | 6 +++-- lxc/executors/typescript | 13 ++++++----- lxc/start | 2 +- lxc/test_all_lxc | 4 +++- lxc/tests/test.jelly | 1 + var/install.txt | 4 +++- 18 files changed, 101 insertions(+), 41 deletions(-) create mode 100644 lxc/tests/test.jelly diff --git a/api/main.go b/api/main.go index d328363..1fb17e5 100644 --- a/api/main.go +++ b/api/main.go @@ -28,6 +28,8 @@ type Outbound struct { Language string `json:"language"` Version string `json:"version"` Output string `json:"output"` + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` } type Language struct { @@ -124,6 +126,18 @@ func Versions(res http.ResponseWriter, req *http.Request) { res.Write(data) } +type StdWriter struct { + combined *string + separate *string +} + +func (writer *StdWriter) Write(data []byte) (int, error) { + *writer.combined += string(data) + *writer.separate += string(data) + + return len(data), nil +} + func launch(request Inbound, res http.ResponseWriter) { stamp := time.Now().UnixNano() @@ -136,9 +150,33 @@ func launch(request Inbound, res http.ResponseWriter) { cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) // capture out/err - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr + var stdout, stderr, combined string + + cmd.Stdout = &StdWriter{ + combined: &combined, + separate: &stdout, + } + + cmd.Stderr = &StdWriter{ + combined: &combined, + separate: &stderr, + } + + stdout = strings.TrimSpace(stdout) + stderr = strings.TrimSpace(stderr) + combined = strings.TrimSpace(combined) + + if len(stdout) > 65536 { + stdout = stdout[:65536] + } + + if len(stderr) > 65536 { + stderr = stdout[:65536] + } + + if len(combined) > 65536 { + combined = combined[:65536] + } err := cmd.Run() @@ -179,7 +217,9 @@ func launch(request Inbound, res http.ResponseWriter) { Ran: err == nil, Language: request.Language, Version: "", - Output: strings.TrimSpace(stdout.String()), + Output: combined, + Stdout: stdout, + Stderr: stderr, } // retrieve the language version diff --git a/lxc/execute b/lxc/execute index efc375d..ba81715 100755 --- a/lxc/execute +++ b/lxc/execute @@ -135,9 +135,9 @@ case "$lang" in esac # runner -timeout -s KILL 10 \ +timeout -s KILL 20 \ lxc-attach --clear-env -n piston -- \ - /bin/bash -l -c "bash /exec/$bin $newinc $epoch 2>&1 | head -c 65536" + /bin/bash -l -c "bash /exec/$bin $newinc $epoch" # process janitor lxc-attach --clear-env -n piston -- \ diff --git a/lxc/executors/c b/lxc/executors/c index b993915..3130257 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,4 +1,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ - timeout -s KILL 10 gcc -std=c11 -o binary -x c code.code ; \ + gcc -std=c11 -o binary -x c code.code ; \ cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/executors/cpp b/lxc/executors/cpp index c4f6471..4b8c6cf 100755 --- a/lxc/executors/cpp +++ b/lxc/executors/cpp @@ -1,3 +1,4 @@ -cd /tmp/$2 -timeout -s KILL 10 g++ -std=c++17 -o binary -x c++ code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + g++ -std=c++17 -o binary -x c++ code.code ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/executors/csharp b/lxc/executors/csharp index 76b3338..2c742c7 100755 --- a/lxc/executors/csharp +++ b/lxc/executors/csharp @@ -1,3 +1,4 @@ -cd /tmp/$2 -timeout -s KILL 10 mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 mono binary" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 mono binary" diff --git a/lxc/executors/emacs b/lxc/executors/emacs index 156723e..31f6186 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -1,7 +1,7 @@ cd /tmp/$2 if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser -l runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 emacs -Q --script code.code" + runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 emacs -Q --script code.code" else - runuser -l runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 emacs -Q --script code.code" + runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 emacs -Q --script code.code" fi diff --git a/lxc/executors/go b/lxc/executors/go index e7903d1..063af21 100755 --- a/lxc/executors/go +++ b/lxc/executors/go @@ -1,6 +1,6 @@ cd /tmp/$2 cp code.code interim.go file="interim.go" -timeout -s KILL 10 go build $file +go build $file file=${file%%.*} runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./$file" diff --git a/lxc/executors/haskell b/lxc/executors/haskell index edde524..7593b60 100755 --- a/lxc/executors/haskell +++ b/lxc/executors/haskell @@ -1,4 +1,7 @@ cd /tmp/$2 mv code.code code.hs -timeout -s KILL 10 ghc -dynamic -o binary code.hs > /dev/null 2>&1 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + ghc -dynamic -o binary code.hs > /dev/null 2>&1 ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/executors/java b/lxc/executors/java index 66261bb..0318a9f 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -2,5 +2,8 @@ cd /tmp/$2 cp code.code interim.java name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\n\s{]+)" interim.java) mv interim.java $name.java -timeout -s KILL 10 javac $name.java -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 java $name" + +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + javac $name.java ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 java $name" diff --git a/lxc/executors/kotlin b/lxc/executors/kotlin index dcd5eff..5d5070a 100755 --- a/lxc/executors/kotlin +++ b/lxc/executors/kotlin @@ -1,4 +1,6 @@ cd /tmp/$2 cp code.code code.kt -timeout -s KILL 10 kotlinc code.kt -include-runtime -d code.jar -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 java -jar code.jar" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + kotlinc code.kt -include-runtime -d code.jar ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 java -jar code.jar" diff --git a/lxc/executors/nasm b/lxc/executors/nasm index 60c4963..22026af 100755 --- a/lxc/executors/nasm +++ b/lxc/executors/nasm @@ -1,4 +1,5 @@ -cd /tmp/$2 -timeout -s KILL 10 nasm -f elf32 -o binary.o code.code -timeout -s KILL 10 ld -m elf_i386 binary.o -o binary -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + nasm -f elf32 -o binary.o code.code ; \ + ld -m elf_i386 binary.o -o binary ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/executors/nasm64 b/lxc/executors/nasm64 index 8723995..a6dc197 100755 --- a/lxc/executors/nasm64 +++ b/lxc/executors/nasm64 @@ -1,4 +1,5 @@ -cd /tmp/$2 -timeout -s KILL 10 nasm -f elf64 -o binary.o code.code -timeout -s KILL 10 ld -m elf_x86_64 binary.o -o binary -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + nasm -f elf64 -o binary.o code.code ; \ + ld -m elf_x86_64 binary.o -o binary ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/executors/rust b/lxc/executors/rust index aef4af3..c939259 100755 --- a/lxc/executors/rust +++ b/lxc/executors/rust @@ -1,3 +1,5 @@ cd /tmp/$2 -timeout -s KILL 10 rustc -o binary code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +rustc -o binary code.code +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/executors/typescript b/lxc/executors/typescript index 5ed50c5..863d8d0 100755 --- a/lxc/executors/typescript +++ b/lxc/executors/typescript @@ -1,6 +1,7 @@ -cd /tmp/$2 -mv code.code interim.ts -timeout -s KILL 10 tsc interim.ts -rm interim.ts -mv interim.js code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code" +runuser runner$1 -c "\ + cd /tmp/$2 ; \ + mv code.code interim.ts ; \ + tsc interim.ts ; \ + rm -f interim.ts ; \ + mv interim.js code.code ; \ + cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code" diff --git a/lxc/start b/lxc/start index 6c13c98..0c17ec8 100755 --- a/lxc/start +++ b/lxc/start @@ -6,4 +6,4 @@ cp -f executors/* /var/lib/lxc/piston/rootfs/exec chmod 700 /var/lib/lxc/piston/rootfs/exec/* chown -R root:root /var/lib/lxc/piston/rootfs/exec -lxc-start -n piston -d +#lxc-start -n piston -d diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index c7f0b28..873c840 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -9,7 +9,7 @@ echo 'testing cpp' ../execute cpp test.cpp echo 'testing cs' ../execute cs test.cs -echo 'testing deno ts' +echo 'testing deno' ../execute deno testdeno.ts echo 'testing elisp' ../execute elisp test.el @@ -21,6 +21,8 @@ echo 'testing haskell' ../execute haskell test.hs echo 'testing java' ../execute java test.java +echo 'testing jelly' +../execute jelly test.jelly echo 'testing jl' ../execute jl test.jl echo 'testing js' diff --git a/lxc/tests/test.jelly b/lxc/tests/test.jelly new file mode 100644 index 0000000..e688ff7 --- /dev/null +++ b/lxc/tests/test.jelly @@ -0,0 +1 @@ +“3ḅaė;œ» diff --git a/var/install.txt b/var/install.txt index 4f44e22..3dbeb44 100644 --- a/var/install.txt +++ b/var/install.txt @@ -157,7 +157,8 @@ cd /opt && mkdir jelly && cd jelly wget https://github.com/DennisMitchell/jellylanguage/archive/master.zip unzip master.zip cd jellylanguage-master -pip3.8 install . +python3.8 -m pip install . +sed -i 's/\/usr\/local\/bin\/python3.8/\/opt\/python3\/Python-3.8.2\/python3.8/' /usr/local/bin/jelly # install julia # final binary: /opt/julia/julia-1.5.0/bin/julia @@ -202,6 +203,7 @@ source /opt/.profile cd /opt && mkdir emacs && cd emacs wget https://mirrors.ocf.berkeley.edu/gnu/emacs/emacs-26.3.tar.xz tar -xf emacs-26.3.tar.xz +rm emacs-26.3.tar.xz cd emacs-26.3 ./configure --with-gnutls=no make From 843c6636c787d7785cc9949ace0663ceafde9297 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 00:01:22 -0600 Subject: [PATCH 09/73] updated readme --- readme.md | 67 +++++++++++++++++++++++++++++++++++++------------ var/install.txt | 20 --------------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/readme.md b/readme.md index fdf2f54..96702cd 100644 --- a/readme.md +++ b/readme.md @@ -1,19 +1,46 @@ ## Piston -Piston is the underlying engine for running untrusted and possibly malicious -code that originates from EMKC contests and challenges. It's also used in the -Engineer Man Discord server via [I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1000+ other servers. +Piston is the underlying engine for running untrusted and possibly malicious code that originates from +[EMKC Challenges](https://emkc.org/challenges) and +[EMKC Weekly Contests](https://emkc.org/contests). It's also used in the +[Engineer Man Discord Server](https://discord.gg/engineerman) via +[I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers. To get it in your own server, go here: https://emkc.org/run. #### Use Public API (new) -Requires no installation and you can use it immediately. Reference the API Usage section below to learn -about the request format but rather than using the local URLs, use the following URLs: +Requires no installation and you can use it immediately. Reference the Versions/Execute sections +below to learn about the request and response formats. - `GET` `https://emkc.org/api/v1/piston/versions` - `POST` `https://emkc.org/api/v1/piston/execute` Important Note: The Piston API is rate limited to 5 requests per second -#### Installation -Updated installation instructions coming soon. See `var/install.txt` for how to do it from scratch. +#### Cloning and System Dependencies +``` +# clone and enter repo +git clone https://github.com/engineer-man/piston +cd piston/lxc + +# centos/rhel dependencies: +yum install -y epel-release +yum install -y lxc lxc-templates debootstrap libvirt +systemctl start libvirtd + +# ubuntu server 18.04 dependencies: +apt install lxc lxc-templates debootstrap libvirt0 + +# arch dependencies: +sudo pacman -S lxc libvirt unzip + +# everything else: +# not documented, please open pull requests with commands for debian/arch/macos/etc +``` + +#### Installation (simple) +Coming soon + +#### Installation (advanced/manual) +See `var/install.txt` for how to create a new LXC container and install all of the required +software. #### CLI Usage - `lxc/execute [language] [file path] [args]` @@ -26,14 +53,14 @@ cd api ``` #### Base URLs -For your own local installation, use: -``` -http://127.0.0.1:2000 -``` When using the public Piston API, use: ``` https://emkc.org/api/v1/piston ``` +For your own local installation, use: +``` +http://127.0.0.1:2000 +``` #### Versions Endpoint `GET /versions` @@ -60,10 +87,11 @@ Content-Type: application/json ] ``` -#### Execution Endpoint +#### Execute Endpoint `POST /execute` This endpoint takes the following JSON payload and expects at least the language and source. If -source is not provided, a blank file is passed as the source. +source is not provided, a blank file is passed as the source. If no `args` are desired, it can either +be an empty array or left out entirely. ```json { "language": "js", @@ -75,7 +103,9 @@ source is not provided, a blank file is passed as the source. ] } ``` -A typical response when everything succeeds will be similar to the following: +A typical response upon successful execution will contain the `language`, `version`, `output` which +is a combination of both `stdout` and `stderr` but in chronological order according to program output, +as well as separate `stdout` and `stderr`. ```json HTTP/1.1 200 OK Content-Type: application/json @@ -84,7 +114,9 @@ Content-Type: application/json "ran": true, "language": "js", "version": "12.13.0", - "output": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]" + "output": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]", + "stdout": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]", + "stderr": "" } ``` If an invalid language is supplied, a typical response will look like the following: @@ -101,6 +133,7 @@ Content-Type: application/json #### Supported Languages - awk - bash +- brainfuck - c - cpp - csharp @@ -108,19 +141,21 @@ Content-Type: application/json - erlang - elixir - emacs +- elisp - go - haskell - java - jelly - julia - kotlin +- lua - nasm - node +- paradoc - perl - php - python2 - python3 -- paradoc - ruby - rust - swift diff --git a/var/install.txt b/var/install.txt index 3dbeb44..bf622af 100644 --- a/var/install.txt +++ b/var/install.txt @@ -1,23 +1,3 @@ -# clone and enter repo -git clone https://github.com/engineer-man/piston -cd piston/lxc - -# install dependencies - -# centos: -yum install -y epel-release -yum install -y lxc lxc-templates debootstrap libvirt -systemctl start libvirtd - -# ubuntu server 18.04: -apt install lxc lxc-templates debootstrap libvirt0 - -# arch: -sudo pacman -S lxc libvirt unzip - -# everything else: -# not documented, please open pull requests with commands for debian/arch/macos - # create and start container lxc-create -t download -n piston -- --dist ubuntu --release bionic --arch amd64 ./start From cdc52d280e3c9ef0fc32a9377f3c83e45ca4ef2d Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 00:02:03 -0600 Subject: [PATCH 10/73] re-enable lxc start --- lxc/start | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/start b/lxc/start index 0c17ec8..6c13c98 100755 --- a/lxc/start +++ b/lxc/start @@ -6,4 +6,4 @@ cp -f executors/* /var/lib/lxc/piston/rootfs/exec chmod 700 /var/lib/lxc/piston/rootfs/exec/* chown -R root:root /var/lib/lxc/piston/rootfs/exec -#lxc-start -n piston -d +lxc-start -n piston -d From b0084715b815e6227301628384ade050cb3a0f45 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 00:08:03 -0600 Subject: [PATCH 11/73] updated readme --- readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 96702cd..4f7f01c 100644 --- a/readme.md +++ b/readme.md @@ -36,7 +36,7 @@ sudo pacman -S lxc libvirt unzip ``` #### Installation (simple) -Coming soon +Coming soon. #### Installation (advanced/manual) See `var/install.txt` for how to create a new LXC container and install all of the required @@ -46,7 +46,8 @@ software. - `lxc/execute [language] [file path] [args]` #### API Usage -To use the API, it must first be started. To start the API, run the following: +To use the API, it must first be started. Please note that if root is required to access +LXC then the API must also be running as root. To start the API, run the following: ``` cd api ./start From 89be3703c6e1084ba094c043080ae3bb516e89dc Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 00:10:28 -0600 Subject: [PATCH 12/73] updated readme --- readme.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 4f7f01c..b8580a7 100644 --- a/readme.md +++ b/readme.md @@ -6,13 +6,15 @@ Piston is the underlying engine for running untrusted and possibly malicious cod [I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers. To get it in your own server, go here: https://emkc.org/run. -#### Use Public API (new) +#### Use Public API Requires no installation and you can use it immediately. Reference the Versions/Execute sections below to learn about the request and response formats. - `GET` `https://emkc.org/api/v1/piston/versions` - `POST` `https://emkc.org/api/v1/piston/execute` -Important Note: The Piston API is rate limited to 5 requests per second +Important Note: The Piston API is rate limited to 5 requests per second. If you have a need for more requests than that +and it's for a good cause, please reach out to me (EngineerMan#0001) on [Discord](https://discord.gg/engineerman) +so we can discuss potentially getting you an unlimited key. #### Cloning and System Dependencies ``` From 2bebceafb6d4c84bbb7974c78bd0959c5ede9b25 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 00:16:01 -0600 Subject: [PATCH 13/73] updated readme --- readme.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index b8580a7..4baecf8 100644 --- a/readme.md +++ b/readme.md @@ -1,10 +1,12 @@ ## Piston -Piston is the underlying engine for running untrusted and possibly malicious code that originates from -[EMKC Challenges](https://emkc.org/challenges) and -[EMKC Weekly Contests](https://emkc.org/contests). It's also used in the +Piston is a high performance general purpose code execution engine. It excels at running untrusted and +possibly malicious code without fear from any harmful effects. +It's used in numerous places including +[EMKC Challenges](https://emkc.org/challenges), +[EMKC Weekly Contests](https://emkc.org/contests), the [Engineer Man Discord Server](https://discord.gg/engineerman) via -[I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers. -To get it in your own server, go here: https://emkc.org/run. +[I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers +and 100+ direct integrations. To get it in your own server, go here: https://emkc.org/run. #### Use Public API Requires no installation and you can use it immediately. Reference the Versions/Execute sections From 20d659e5a6fc3f490e3d025d68aea7f23780b58c Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 00:28:26 -0600 Subject: [PATCH 14/73] add ssl to install dependencies, update python3 to python3.8 for versions --- lxc/versions | 4 ++-- var/install.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lxc/versions b/lxc/versions index cbfd824..d813719 100755 --- a/lxc/versions +++ b/lxc/versions @@ -86,11 +86,11 @@ lxc-attach --clear-env -n piston -- /bin/bash -l -c "python -V" echo '---' echo 'python3' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3 -V" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3.8 -V" echo '---' echo 'paradoc' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3 -m paradoc --version" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3.8 -m paradoc --version" echo '---' echo 'ruby' diff --git a/var/install.txt b/var/install.txt index bf622af..9be572e 100644 --- a/var/install.txt +++ b/var/install.txt @@ -20,7 +20,7 @@ apt-get update apt-get install -y \ nano wget build-essential pkg-config libxml2-dev \ libsqlite3-dev mono-complete curl cmake libpython2.7-dev \ - ruby libtinfo-dev unzip git + ruby libtinfo-dev unzip git openssl libssl-dev # install python2 # final binary: /opt/python2/Python-2.7.17/python From 77e645beb3b9995666c24de9d5775e2d2ae0b878 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Thu, 14 Jan 2021 20:14:26 +0100 Subject: [PATCH 15/73] Rip out go, add aliases to /versions --- api/.gitignore | 1 + api/main.go | 413 +++++++++---------- api/package-lock.json | 903 ++++++++++++++++++++++++++++++++++++++++++ api/package.json | 16 + api/src/index.js | 99 +++++ api/src/languages.js | 118 ++++++ api/start | 2 +- lxc/execute | 96 +---- 8 files changed, 1346 insertions(+), 302 deletions(-) create mode 100644 api/.gitignore create mode 100644 api/package-lock.json create mode 100644 api/package.json create mode 100644 api/src/index.js create mode 100644 api/src/languages.js diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/api/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/api/main.go b/api/main.go index 1fb17e5..2e7e378 100644 --- a/api/main.go +++ b/api/main.go @@ -1,302 +1,303 @@ package main import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os/exec" - "regexp" - "strings" - "time" + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os/exec" + "regexp" + "strings" + "time" ) type Inbound struct { - Language string `json:"language"` - Source string `json:"source"` - Args []string `json:"args"` + Language string `json:"language"` + Source string `json:"source"` + Args []string `json:"args"` } type Problem struct { - Code string `json:"code"` - Message string `json:"message"` + Code string `json:"code"` + Message string `json:"message"` } type Outbound struct { - Ran bool `json:"ran"` - Language string `json:"language"` - Version string `json:"version"` - Output string `json:"output"` - Stdout string `json:"stdout"` - Stderr string `json:"stderr"` + Ran bool `json:"ran"` + Language string `json:"language"` + Version string `json:"version"` + Output string `json:"output"` + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` } type Language struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` + Aliases []string `json:"aliases,omitempty"` } var instance int var languages []Language func main() { - port := "2000" + port := "2000" - var err error - languages, err = UpdateVersions() + var err error + languages, err = UpdateVersions() - if err != nil { - fmt.Println("could not get version info and therefore couldn't start") - fmt.Println(err) - return - } + if err != nil { + fmt.Println("could not get version info and therefore couldn't start") + fmt.Println(err) + return + } - fmt.Println("starting api on port", port) - http.HandleFunc("/execute", Execute) - http.HandleFunc("/versions", Versions) - http.ListenAndServe(":"+port, nil) + fmt.Println("starting api on port", port) + http.HandleFunc("/execute", Execute) + http.HandleFunc("/versions", Versions) + http.ListenAndServe(":"+port, nil) } func Execute(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") + res.Header().Set("Content-Type", "application/json") - // get json - inbound := Inbound{} - message := json.NewDecoder(req.Body) - message.Decode(&inbound) + // get json + inbound := Inbound{} + message := json.NewDecoder(req.Body) + message.Decode(&inbound) - whitelist := []string{ - "awk", - "bash", - "brainfuck", "bf", - "c", - "cpp", "c++", - "csharp", "cs", "c#", - "deno", "denojs", "denots", - "elixir", "exs", - "emacs", "elisp", "el", - "go", - "haskell", "hs", - "java", - "jelly", - "julia", "jl", - "kotlin", - "lua", - "nasm", "asm", - "nasm64", "asm64", - "node", "javascript", "js", - "perl", "pl", - "php", - "python2", - "python3", "python", - "paradoc", - "ruby", - "rust", - "swift", - "typescript", "ts", - } + whitelist := []string{ + "awk", + "bash", + "brainfuck", "bf", + "c", + "cpp", "c++", + "csharp", "cs", "c#", + "deno", "denojs", "denots", + "elixir", "exs", + "emacs", "elisp", "el", + "go", + "haskell", "hs", + "java", + "jelly", + "julia", "jl", + "kotlin", + "lua", + "nasm", "asm", + "nasm64", "asm64", + "node", "javascript", "js", + "perl", "pl", + "php", + "python2", + "python3", "python", + "paradoc", + "ruby", + "rust", + "swift", + "typescript", "ts", + } - // check if the supplied language is supported - // now calls function and returns - for _, lang := range whitelist { - if lang == inbound.Language { - launch(inbound, res) - return - } - } + // check if the supplied language is supported + // now calls function and returns + for _, lang := range whitelist { + if lang == inbound.Language { + launch(inbound, res) + return + } + } - // now only called when the language is not supported - problem := Problem{ - Code: "unsupported_language", - Message: inbound.Language + " is not supported by Piston", - } + // now only called when the language is not supported + problem := Problem{ + Code: "unsupported_language", + Message: inbound.Language + " is not supported by Piston", + } - pres, _ := json.Marshal(problem) + pres, _ := json.Marshal(problem) - res.WriteHeader(http.StatusBadRequest) - res.Write(pres) + res.WriteHeader(http.StatusBadRequest) + res.Write(pres) } func Versions(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") + res.Header().Set("Content-Type", "application/json") - data, _ := json.Marshal(languages) + data, _ := json.Marshal(languages) - res.Write(data) + res.Write(data) } type StdWriter struct { - combined *string - separate *string + combined *string + separate *string } func (writer *StdWriter) Write(data []byte) (int, error) { - *writer.combined += string(data) - *writer.separate += string(data) + *writer.combined += string(data) + *writer.separate += string(data) - return len(data), nil + return len(data), nil } func launch(request Inbound, res http.ResponseWriter) { - stamp := time.Now().UnixNano() + stamp := time.Now().UnixNano() - // write the code to temp dir - srcfile := fmt.Sprintf("/tmp/%d.code", stamp) + // write the code to temp dir + srcfile := fmt.Sprintf("/tmp/%d.code", stamp) - ioutil.WriteFile(srcfile, []byte(request.Source), 0644) + ioutil.WriteFile(srcfile, []byte(request.Source), 0644) - // set up the arguments to send to the execute command - cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) + // set up the arguments to send to the execute command + cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) - // capture out/err - var stdout, stderr, combined string + // capture out/err + var stdout, stderr, combined string - cmd.Stdout = &StdWriter{ - combined: &combined, - separate: &stdout, - } + cmd.Stdout = &StdWriter{ + combined: &combined, + separate: &stdout, + } - cmd.Stderr = &StdWriter{ - combined: &combined, - separate: &stderr, - } + cmd.Stderr = &StdWriter{ + combined: &combined, + separate: &stderr, + } - stdout = strings.TrimSpace(stdout) - stderr = strings.TrimSpace(stderr) - combined = strings.TrimSpace(combined) + stdout = strings.TrimSpace(stdout) + stderr = strings.TrimSpace(stderr) + combined = strings.TrimSpace(combined) - if len(stdout) > 65536 { - stdout = stdout[:65536] - } + if len(stdout) > 65536 { + stdout = stdout[:65536] + } - if len(stderr) > 65536 { - stderr = stdout[:65536] - } + if len(stderr) > 65536 { + stderr = stdout[:65536] + } - if len(combined) > 65536 { - combined = combined[:65536] - } + if len(combined) > 65536 { + combined = combined[:65536] + } - err := cmd.Run() + err := cmd.Run() - // get the executing version of the language - execlang := request.Language + // get the executing version of the language + execlang := request.Language - switch execlang { - case "bf": - execlang = "brainfuck" - case "c++": - execlang = "cpp" - case "cs", "c#": - execlang = "csharp" - case "denojs", "denots": - execlang = "deno" - case "el", "elisp": - execlang = "emacs" - case "exs": - execlang = "elixir" - case "hs": - execlang = "haskell" - case "asm": - execlang = "nasm" - case "asm64": - execlang = "nasm64" - case "js", "javascript": - execlang = "node" - case "jl": - execlang = "julia" - case "python": - execlang = "python3" - case "ts": - execlang = "typescript" - } + switch execlang { + case "bf": + execlang = "brainfuck" + case "c++": + execlang = "cpp" + case "cs", "c#": + execlang = "csharp" + case "denojs", "denots": + execlang = "deno" + case "el", "elisp": + execlang = "emacs" + case "exs": + execlang = "elixir" + case "hs": + execlang = "haskell" + case "asm": + execlang = "nasm" + case "asm64": + execlang = "nasm64" + case "js", "javascript": + execlang = "node" + case "jl": + execlang = "julia" + case "python": + execlang = "python3" + case "ts": + execlang = "typescript" + } - // prepare response - outbound := Outbound{ - Ran: err == nil, - Language: request.Language, - Version: "", - Output: combined, - Stdout: stdout, - Stderr: stderr, - } + // prepare response + outbound := Outbound{ + Ran: err == nil, + Language: request.Language, + Version: "", + Output: combined, + Stdout: stdout, + Stderr: stderr, + } - // retrieve the language version - for _, lang := range languages { - if lang.Name == execlang { - outbound.Version = lang.Version - break - } - } + // retrieve the language version + for _, lang := range languages { + if lang.Name == execlang { + outbound.Version = lang.Version + break + } + } - response, _ := json.Marshal(outbound) + response, _ := json.Marshal(outbound) - res.Write(response) + res.Write(response) } func UpdateVersions() ([]Language, error) { - langs, err := GetVersions() + langs, err := GetVersions() - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - return langs, nil + return langs, nil } // get all the language and their current version func GetVersions() ([]Language, error) { - var languages []Language + var languages []Language - res, err := ExecVersionScript() + res, err := ExecVersionScript() - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - info := strings.Split(res, "---") + info := strings.Split(res, "---") - for _, v := range info { - if len(v) < 2 { - continue - } - name, version := GetVersion(v) - languages = append(languages, Language{ - Name: name, - Version: version, - }) - } + for _, v := range info { + if len(v) < 2 { + continue + } + name, version := GetVersion(v) + languages = append(languages, Language{ + Name: name, + Version: version, + }) + } - return languages, nil + return languages, nil } // run the script that retrieves all the language versions func ExecVersionScript() (string, error) { - cmd := exec.Command("../lxc/versions") + cmd := exec.Command("../lxc/versions") - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout + var stdout bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stdout - err := cmd.Run() + err := cmd.Run() - return strings.ToLower(stdout.String()), err + return strings.ToLower(stdout.String()), err } // return the language and its version // most of the time it is easy to get the name and version // but for some languages helper functions are used func GetVersion(s string) (string, string) { - lines := strings.Split(s, "\n") + lines := strings.Split(s, "\n") - if lines[1] == "java" { - return "java", regexp.MustCompile("([0-9]+)").FindString(lines[2]) - } + if lines[1] == "java" { + return "java", regexp.MustCompile("([0-9]+)").FindString(lines[2]) + } - if lines[1] == "emacs" { - return "emacs", regexp.MustCompile("([0-9]+\\.[0-9]+)").FindString(lines[2]) - } + if lines[1] == "emacs" { + return "emacs", regexp.MustCompile("([0-9]+\\.[0-9]+)").FindString(lines[2]) + } - return lines[1], regexp.MustCompile("([0-9]+\\.[0-9]+\\.[0-9]+)").FindString(s) + return lines[1], regexp.MustCompile("([0-9]+\\.[0-9]+\\.[0-9]+)").FindString(s) } diff --git a/api/package-lock.json b/api/package-lock.json new file mode 100644 index 0000000..4757c95 --- /dev/null +++ b/api/package-lock.json @@ -0,0 +1,903 @@ +{ + "name": "api", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "express-validator": "^6.9.2" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-validator": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", + "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", + "dependencies": { + "lodash": "^4.17.20", + "validator": "^13.5.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "dependencies": { + "mime-db": "1.45.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + } + }, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "express-validator": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", + "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", + "requires": { + "lodash": "^4.17.20", + "validator": "^13.5.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + }, + "mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "requires": { + "mime-db": "1.45.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + } + } +} diff --git a/api/package.json b/api/package.json new file mode 100644 index 0000000..cf6bf15 --- /dev/null +++ b/api/package.json @@ -0,0 +1,16 @@ +{ + "name": "api", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "express-validator": "^6.9.2" + } +} diff --git a/api/src/index.js b/api/src/index.js new file mode 100644 index 0000000..1bb789f --- /dev/null +++ b/api/src/index.js @@ -0,0 +1,99 @@ +const { writeFile } = require('fs/promises'); +const express = require('express'); +const app = express(); +const languages = require('./languages'); +const { spawn, execFileSync } = require('child_process'); + +const versions = execFileSync(__dirname + '/../../lxc/versions') + .toString() + .toLowerCase() + .split('---') + .map(section => section.split('\n')) + .filter(section => section.length >= 2); + +function getVersion(language) { + return versions.find(section => section[0] === language?.name); +} + +for (const language of languages) { + // TODO: Add custom handlers for some languages + + language.version = getVersion(language); +} + +app.use(express.json()); + +app.post('/execute', (req, res) => { + const body = req.body; + + const language = languages.find(language => { + return language.aliases.includes(body.language?.toString()?.toLowerCase()); + }); + + if (!language) { + return res.status(400).json({ + code: 'unsupported_language', + message: `${body.language} is not supported by Piston`, + }); + } else if (!(body.source instanceof string)) { + return res.status(400).json({ + code: 'missing_source', + message: 'source field is invalid', + }); + } else if (body.args && !(body.args instanceof Array)) { + return res.status(400).json({ + code: 'invalid_args', + message: 'args field is not an array', + }); + } + + launch(res, language, body); +}); + +async function launch(res, language, body) { + const stamp = new Date().getTime(); + const sourceFile = `/tmp/${stamp}.code`; + + await writeFile(sourceFile, body.source); + + const process = spawn(__dirname + '/../../lxc/execute', [language.name, sourceFile, (body.args ?? []).join('\n')]); + + const result = { + ran: true, + language: language.name, + stderr: '', + stdout: '', + output: '', + }; + + if (language.version) + result.version = language.version; + + process.stderr.setEncoding('utf-8'); + process.stdout.setEncoding('utf-8'); + + process.stderr.addListener('data', chunk => { + result.stderr += chunk; + result.output += chunk; + }); + + process.stdout.addListener('data', chunk => { + result.stdout += chunk; + result.output += chunk; + }); + + result.stderr = result.stderr.substring(0, 65535); + result.stdout = result.stdout.substring(0, 65535); + result.output = result.output.substring(0, 65535); + + process.on('exit', () => { + res.json(result); + }); +} + +app.get('/versions', (req, res) => { + res.json(languages); +}); + +const PORT = 2000; +app.listen(PORT, () => console.log(`Listening on port ${PORT}`)); diff --git a/api/src/languages.js b/api/src/languages.js new file mode 100644 index 0000000..bee5db6 --- /dev/null +++ b/api/src/languages.js @@ -0,0 +1,118 @@ +module.exports = [ + { + name: 'nasm', + aliases: ['asm', 'nasm'], + }, + { + name: 'nasm64', + aliases: ['asm64', 'nasm64'], + }, + { + name: 'awk', + aliases: ['awk'], + }, + { + name: 'bash', + aliases: ['bash'], + }, + { + name: 'brainfuck', + aliases: ['bf', 'brainfuck'], + }, + { + name: 'c', + aliases: ['c'], + }, + { + name: 'csharp', + aliases: ['c#', 'cs', 'csharp'], + }, + { + name: 'cpp', + aliases: ['c++', 'cpp'], + }, + { + name: 'deno', + aliases: ['deno', 'denojs', 'denots'], + }, + { + name: 'ruby', + aliases: ['duby', 'rb', 'ruby'], + }, + { + name: 'emacs', + aliases: ['el', 'elisp', 'emacs'], + }, + { + name: 'elixir', + aliases: ['elixir'], + }, + { + name: 'haskell', + aliases: ['haskell', 'hs'], + }, + { + name: 'go', + aliases: ['go'], + }, + { + name: 'java', + aliases: ['java'], + }, + { + name: 'javascript', + aliases: ['javascript', 'js', 'node'], + }, + { + name: 'jelly', + aliases: ['jelly'], + }, + { + name: 'julia', + aliases: ['jl', 'julia'], + }, + { + name: 'kotlin', + aliases: ['kotlin'], + }, + { + name: 'lua', + aliases: ['lua'], + }, + { + name: 'paradoc', + aliases: ['paradoc'], + }, + { + name: 'perl', + aliases: ['perl'], + }, + { + name: 'php', + aliases: ['php', 'php3', 'php4', 'php5'], + }, + { + name: 'python3', + aliases: ['py', 'py3', 'python', 'python3'], + }, + { + name: 'python2', + aliases: ['python2'], + }, + { + name: 'r', + aliases: ['r'], + }, + { + name: 'rust', + aliases: ['rs', 'rust'], + }, + { + name: 'swift', + aliases: ['swift'], + }, + { + name: 'typescript', + aliases: ['ts', 'typescript'], + }, +]; diff --git a/api/start b/api/start index 9cf6e69..fe2024e 100755 --- a/api/start +++ b/api/start @@ -1,3 +1,3 @@ #!/usr/bin/env bash -go run main.go $* +node src diff --git a/lxc/execute b/lxc/execute index ba81715..c33d7f2 100755 --- a/lxc/execute +++ b/lxc/execute @@ -40,104 +40,10 @@ else fi exec 200>&- -bin= -case "$lang" in -"awk") - bin=awk - ;; -"bash") - bin=bash - ;; -"brainfuck" | "bf") - bin=brainfuck - ;; -"c") - bin=c - ;; -"cpp" | "c++") - bin=cpp - ;; -"csharp" | "cs" | "c#") - bin=csharp - ;; -"elixir" | "exs") - bin=elixir - ;; -"go") - bin=go - ;; -"haskell" | "hs") - bin=haskell - ;; -"java") - bin=java - ;; -"jelly") - bin=jelly - ;; -"julia" | "jl") - bin=julia - ;; -"kotlin") - bin=kotlin - ;; -"lua") - bin=lua - ;; -"nasm" | "asm") - bin=nasm - ;; -"nasm64" | "asm64") - bin=nasm64 - ;; -"node" | "js" | "javascript") - bin=node - ;; -"deno" | "denojs" | "denots") - bin=deno - ;; -"paradoc") - bin=paradoc - ;; -"perl") - bin=perl - ;; -"php") - bin=php - ;; -"python2") - bin=python2 - ;; -"python3" | "python") - bin=python3 - ;; -"ruby") - bin=ruby - ;; -"rust") - bin=rust - ;; -"swift") - bin=swift - ;; -"emacs" | "elisp" | "el") - bin=emacs - ;; -"bash") - bin=bash - ;; -"typescript" | "ts") - bin=typescript - ;; -*) - echo "invalid language" - exit -esac - # runner timeout -s KILL 20 \ lxc-attach --clear-env -n piston -- \ - /bin/bash -l -c "bash /exec/$bin $newinc $epoch" + /bin/bash -l -c "bash /exec/$lang $newinc $epoch" # process janitor lxc-attach --clear-env -n piston -- \ From 2bcd133edf3cf3be15934a19052074e5dee04fcb Mon Sep 17 00:00:00 2001 From: Vrganj Date: Thu, 14 Jan 2021 20:25:45 +0100 Subject: [PATCH 16/73] Fix validation, versions --- api/src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index 1bb789f..76c4e50 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -12,7 +12,7 @@ const versions = execFileSync(__dirname + '/../../lxc/versions') .filter(section => section.length >= 2); function getVersion(language) { - return versions.find(section => section[0] === language?.name); + return versions.find(section => section[0] === language?.name)?.slice(1).join('\n'); } for (const language of languages) { @@ -35,12 +35,12 @@ app.post('/execute', (req, res) => { code: 'unsupported_language', message: `${body.language} is not supported by Piston`, }); - } else if (!(body.source instanceof string)) { + } else if (typeof body.source !== 'string') { return res.status(400).json({ code: 'missing_source', message: 'source field is invalid', }); - } else if (body.args && !(body.args instanceof Array)) { + } else if (body.args && Array.isArray(body.args)) { return res.status(400).json({ code: 'invalid_args', message: 'args field is not an array', From 11b2520189dd936058a85c6b25b0f12bcc4789f7 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Thu, 14 Jan 2021 20:26:41 +0100 Subject: [PATCH 17/73] Fix validation yet again --- api/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/index.js b/api/src/index.js index 76c4e50..fb6ac06 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -40,7 +40,7 @@ app.post('/execute', (req, res) => { code: 'missing_source', message: 'source field is invalid', }); - } else if (body.args && Array.isArray(body.args)) { + } else if (body.args && !Array.isArray(body.args)) { return res.status(400).json({ code: 'invalid_args', message: 'args field is not an array', From 218fe8f0237bea24c6b326995b2804331006001d Mon Sep 17 00:00:00 2001 From: Vrganj Date: Thu, 14 Jan 2021 20:32:06 +0100 Subject: [PATCH 18/73] Fix versions --- api/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/index.js b/api/src/index.js index fb6ac06..9210e16 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -8,7 +8,7 @@ const versions = execFileSync(__dirname + '/../../lxc/versions') .toString() .toLowerCase() .split('---') - .map(section => section.split('\n')) + .map(section => section.trim().split('\n')) .filter(section => section.length >= 2); function getVersion(language) { From c15f9a9942ee759c0e91ddc3c10ff328aa5367b8 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Thu, 14 Jan 2021 21:06:26 +0100 Subject: [PATCH 19/73] Capture stderr when setting versions --- api/src/index.js | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index 9210e16..d510eb9 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -2,24 +2,43 @@ const { writeFile } = require('fs/promises'); const express = require('express'); const app = express(); const languages = require('./languages'); -const { spawn, execFileSync } = require('child_process'); +const { spawn } = require('child_process'); -const versions = execFileSync(__dirname + '/../../lxc/versions') - .toString() - .toLowerCase() - .split('---') - .map(section => section.trim().split('\n')) - .filter(section => section.length >= 2); +(function setVersions() { + let output = ''; -function getVersion(language) { - return versions.find(section => section[0] === language?.name)?.slice(1).join('\n'); -} + const process = spawn(__dirname + '/../../lxc/versions'); -for (const language of languages) { - // TODO: Add custom handlers for some languages + process.stdout.setEncoding('utf-8'); + process.stderr.setEncoding('utf-8'); - language.version = getVersion(language); -} + process.stdout.addListener('data', chunk => { + output += chunk; + }); + + process.stderr.addListener('data', chunk => { + output += chunk; + }); + + process.on('exit', () => { + const sections = output.toLowerCase().split('---'); + const versions = {}; + + for (let section of sections) { + section = section.trim().split('\n'); + + if (section.length >= 2) { + const language = section[0]; + + versions[language] = /\d.\d.\d/.exec(section.slice(1).join('\n'))?.[0]; + } + } + + for (const language of languages) { + language.version = versions[language.name]; + } + }); +})(); app.use(express.json()); From 3f301b8c1fe823de707282367f170d0ba777fc1a Mon Sep 17 00:00:00 2001 From: Vrganj Date: Thu, 14 Jan 2021 21:21:10 +0100 Subject: [PATCH 20/73] Fix version regex --- api/src/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/src/index.js b/api/src/index.js index d510eb9..e22b8cb 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -30,7 +30,13 @@ const { spawn } = require('child_process'); if (section.length >= 2) { const language = section[0]; - versions[language] = /\d.\d.\d/.exec(section.slice(1).join('\n'))?.[0]; + if (language === 'java') { + versions[language] = /\d+/.exec(section[2]); + } else if (language === 'emacs') { + versions[language] = /\d+\.\d+/.exec(section[2]); + } else { + versions[language] = /\d\.\d\.\d/.exec(section.slice(1).join('\n'))?.[0]; + } } } From d3361049f3b9f129f39630bf634ad4493b5f3cf1 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 14 Jan 2021 18:46:21 -0600 Subject: [PATCH 21/73] move run up --- api/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/main.go b/api/main.go index 1fb17e5..29aaa0c 100644 --- a/api/main.go +++ b/api/main.go @@ -162,6 +162,8 @@ func launch(request Inbound, res http.ResponseWriter) { separate: &stderr, } + err := cmd.Run() + stdout = strings.TrimSpace(stdout) stderr = strings.TrimSpace(stderr) combined = strings.TrimSpace(combined) @@ -178,8 +180,6 @@ func launch(request Inbound, res http.ResponseWriter) { combined = combined[:65536] } - err := cmd.Run() - // get the executing version of the language execlang := request.Language From b2b69db27dbf60efaa69d947b710ea9caad92207 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 15 Jan 2021 11:29:57 -0600 Subject: [PATCH 22/73] remove path separators for java executor --- lxc/executors/java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/executors/java b/lxc/executors/java index 0318a9f..6fc09e0 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -1,6 +1,6 @@ cd /tmp/$2 cp code.code interim.java -name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\n\s{]+)" interim.java) +name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\n\s{]+)" interim.java) mv interim.java $name.java runuser runner$1 -c "\ From 6fdf2d6061e0f5bc8effb667184b81c5b80786af Mon Sep 17 00:00:00 2001 From: Vrganj Date: Fri, 15 Jan 2021 20:40:18 +0100 Subject: [PATCH 23/73] Fixes --- api/src/index.js | 39 +++++++++++++++------------------------ api/src/languages.js | 6 +----- lxc/versions | 4 ++++ 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index e22b8cb..825a472 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -4,47 +4,41 @@ const app = express(); const languages = require('./languages'); const { spawn } = require('child_process'); -(function setVersions() { - let output = ''; - +{ const process = spawn(__dirname + '/../../lxc/versions'); - process.stdout.setEncoding('utf-8'); - process.stderr.setEncoding('utf-8'); + let output = ''; + process.stderr.on('data', chunk => output += chunk); + process.stdout.on('data', chunk => output += chunk); - process.stdout.addListener('data', chunk => { - output += chunk; - }); - - process.stderr.addListener('data', chunk => { - output += chunk; - }); - process.on('exit', () => { const sections = output.toLowerCase().split('---'); const versions = {}; - for (let section of sections) { - section = section.trim().split('\n'); + for (const section of sections) { + const lines = section.trim().split('\n'); - if (section.length >= 2) { - const language = section[0]; + if (lines.length >= 2) { + const language = lines[0]; + + console.log(language); if (language === 'java') { - versions[language] = /\d+/.exec(section[2]); + versions[language] = /\d+/.exec(lines[1])?.[0]; } else if (language === 'emacs') { - versions[language] = /\d+\.\d+/.exec(section[2]); + versions[language] = /\d+\.\d+/.exec(lines[1])?.[0]; } else { - versions[language] = /\d\.\d\.\d/.exec(section.slice(1).join('\n'))?.[0]; + versions[language] = /\d+\.\d+\.\d+/.exec(section)?.[0]; } } } for (const language of languages) { + console.log(language.name, versions[language.name]) language.version = versions[language.name]; } }); -})(); +} app.use(express.json()); @@ -94,9 +88,6 @@ async function launch(res, language, body) { if (language.version) result.version = language.version; - process.stderr.setEncoding('utf-8'); - process.stdout.setEncoding('utf-8'); - process.stderr.addListener('data', chunk => { result.stderr += chunk; result.output += chunk; diff --git a/api/src/languages.js b/api/src/languages.js index bee5db6..34409cb 100644 --- a/api/src/languages.js +++ b/api/src/languages.js @@ -60,7 +60,7 @@ module.exports = [ aliases: ['java'], }, { - name: 'javascript', + name: 'node', aliases: ['javascript', 'js', 'node'], }, { @@ -99,10 +99,6 @@ module.exports = [ name: 'python2', aliases: ['python2'], }, - { - name: 'r', - aliases: ['r'], - }, { name: 'rust', aliases: ['rs', 'rust'], diff --git a/lxc/versions b/lxc/versions index d813719..583feb7 100755 --- a/lxc/versions +++ b/lxc/versions @@ -69,6 +69,10 @@ echo 'nasm' lxc-attach --clear-env -n piston -- /bin/bash -l -c "nasm -version" echo '---' +echo 'nasm64' +lxc-attach --clear-env -n piston -- /bin/bash -l -c "nasm -version" +echo '---' + echo 'node' lxc-attach --clear-env -n piston -- /bin/bash -l -c "node --version" echo '---' From bbbea5045acf2b42e46aa6ad30616a2ac7fbf3dd Mon Sep 17 00:00:00 2001 From: Vrganj Date: Fri, 15 Jan 2021 20:43:01 +0100 Subject: [PATCH 24/73] Remove debug --- api/src/index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index 825a472..fcbe547 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -21,8 +21,6 @@ const { spawn } = require('child_process'); if (lines.length >= 2) { const language = lines[0]; - console.log(language); - if (language === 'java') { versions[language] = /\d+/.exec(lines[1])?.[0]; } else if (language === 'emacs') { @@ -34,7 +32,6 @@ const { spawn } = require('child_process'); } for (const language of languages) { - console.log(language.name, versions[language.name]) language.version = versions[language.name]; } }); From a2457edc6fa689fdde099c1722d8cf9551d87c1d Mon Sep 17 00:00:00 2001 From: Vrganj Date: Fri, 15 Jan 2021 22:13:29 +0100 Subject: [PATCH 25/73] Trim output --- api/src/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index fcbe547..a7c769f 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -95,13 +95,11 @@ async function launch(res, language, body) { result.output += chunk; }); - result.stderr = result.stderr.substring(0, 65535); - result.stdout = result.stdout.substring(0, 65535); - result.output = result.output.substring(0, 65535); + result.stderr = result.stderr.trim().substring(0, 65535); + result.stdout = result.stdout.trim().substring(0, 65535); + result.output = result.output.trim().substring(0, 65535); - process.on('exit', () => { - res.json(result); - }); + process.on('exit', () => res.json(result)); } app.get('/versions', (req, res) => { From c88abc3ac93de62466cbdc11daef87d36bd690eb Mon Sep 17 00:00:00 2001 From: Vrganj Date: Fri, 15 Jan 2021 22:47:04 +0100 Subject: [PATCH 26/73] Remove main.go, remove useless dependency --- api/main.go | 303 ----------------------------------------------- api/package.json | 3 +- 2 files changed, 1 insertion(+), 305 deletions(-) delete mode 100644 api/main.go diff --git a/api/main.go b/api/main.go deleted file mode 100644 index 2e7e378..0000000 --- a/api/main.go +++ /dev/null @@ -1,303 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os/exec" - "regexp" - "strings" - "time" -) - -type Inbound struct { - Language string `json:"language"` - Source string `json:"source"` - Args []string `json:"args"` -} - -type Problem struct { - Code string `json:"code"` - Message string `json:"message"` -} - -type Outbound struct { - Ran bool `json:"ran"` - Language string `json:"language"` - Version string `json:"version"` - Output string `json:"output"` - Stdout string `json:"stdout"` - Stderr string `json:"stderr"` -} - -type Language struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` - Aliases []string `json:"aliases,omitempty"` -} - -var instance int -var languages []Language - -func main() { - port := "2000" - - var err error - languages, err = UpdateVersions() - - if err != nil { - fmt.Println("could not get version info and therefore couldn't start") - fmt.Println(err) - return - } - - fmt.Println("starting api on port", port) - http.HandleFunc("/execute", Execute) - http.HandleFunc("/versions", Versions) - http.ListenAndServe(":"+port, nil) -} - -func Execute(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") - - // get json - inbound := Inbound{} - message := json.NewDecoder(req.Body) - message.Decode(&inbound) - - whitelist := []string{ - "awk", - "bash", - "brainfuck", "bf", - "c", - "cpp", "c++", - "csharp", "cs", "c#", - "deno", "denojs", "denots", - "elixir", "exs", - "emacs", "elisp", "el", - "go", - "haskell", "hs", - "java", - "jelly", - "julia", "jl", - "kotlin", - "lua", - "nasm", "asm", - "nasm64", "asm64", - "node", "javascript", "js", - "perl", "pl", - "php", - "python2", - "python3", "python", - "paradoc", - "ruby", - "rust", - "swift", - "typescript", "ts", - } - - // check if the supplied language is supported - // now calls function and returns - for _, lang := range whitelist { - if lang == inbound.Language { - launch(inbound, res) - return - } - } - - // now only called when the language is not supported - problem := Problem{ - Code: "unsupported_language", - Message: inbound.Language + " is not supported by Piston", - } - - pres, _ := json.Marshal(problem) - - res.WriteHeader(http.StatusBadRequest) - res.Write(pres) -} - -func Versions(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") - - data, _ := json.Marshal(languages) - - res.Write(data) -} - -type StdWriter struct { - combined *string - separate *string -} - -func (writer *StdWriter) Write(data []byte) (int, error) { - *writer.combined += string(data) - *writer.separate += string(data) - - return len(data), nil -} - -func launch(request Inbound, res http.ResponseWriter) { - stamp := time.Now().UnixNano() - - // write the code to temp dir - srcfile := fmt.Sprintf("/tmp/%d.code", stamp) - - ioutil.WriteFile(srcfile, []byte(request.Source), 0644) - - // set up the arguments to send to the execute command - cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) - - // capture out/err - var stdout, stderr, combined string - - cmd.Stdout = &StdWriter{ - combined: &combined, - separate: &stdout, - } - - cmd.Stderr = &StdWriter{ - combined: &combined, - separate: &stderr, - } - - stdout = strings.TrimSpace(stdout) - stderr = strings.TrimSpace(stderr) - combined = strings.TrimSpace(combined) - - if len(stdout) > 65536 { - stdout = stdout[:65536] - } - - if len(stderr) > 65536 { - stderr = stdout[:65536] - } - - if len(combined) > 65536 { - combined = combined[:65536] - } - - err := cmd.Run() - - // get the executing version of the language - execlang := request.Language - - switch execlang { - case "bf": - execlang = "brainfuck" - case "c++": - execlang = "cpp" - case "cs", "c#": - execlang = "csharp" - case "denojs", "denots": - execlang = "deno" - case "el", "elisp": - execlang = "emacs" - case "exs": - execlang = "elixir" - case "hs": - execlang = "haskell" - case "asm": - execlang = "nasm" - case "asm64": - execlang = "nasm64" - case "js", "javascript": - execlang = "node" - case "jl": - execlang = "julia" - case "python": - execlang = "python3" - case "ts": - execlang = "typescript" - } - - // prepare response - outbound := Outbound{ - Ran: err == nil, - Language: request.Language, - Version: "", - Output: combined, - Stdout: stdout, - Stderr: stderr, - } - - // retrieve the language version - for _, lang := range languages { - if lang.Name == execlang { - outbound.Version = lang.Version - break - } - } - - response, _ := json.Marshal(outbound) - - res.Write(response) -} - -func UpdateVersions() ([]Language, error) { - langs, err := GetVersions() - - if err != nil { - return nil, err - } - - return langs, nil -} - -// get all the language and their current version -func GetVersions() ([]Language, error) { - var languages []Language - - res, err := ExecVersionScript() - - if err != nil { - return nil, err - } - - info := strings.Split(res, "---") - - for _, v := range info { - if len(v) < 2 { - continue - } - name, version := GetVersion(v) - languages = append(languages, Language{ - Name: name, - Version: version, - }) - } - - return languages, nil -} - -// run the script that retrieves all the language versions -func ExecVersionScript() (string, error) { - cmd := exec.Command("../lxc/versions") - - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout - - err := cmd.Run() - - return strings.ToLower(stdout.String()), err -} - -// return the language and its version -// most of the time it is easy to get the name and version -// but for some languages helper functions are used -func GetVersion(s string) (string, string) { - lines := strings.Split(s, "\n") - - if lines[1] == "java" { - return "java", regexp.MustCompile("([0-9]+)").FindString(lines[2]) - } - - if lines[1] == "emacs" { - return "emacs", regexp.MustCompile("([0-9]+\\.[0-9]+)").FindString(lines[2]) - } - - return lines[1], regexp.MustCompile("([0-9]+\\.[0-9]+\\.[0-9]+)").FindString(s) -} diff --git a/api/package.json b/api/package.json index cf6bf15..b55f17c 100644 --- a/api/package.json +++ b/api/package.json @@ -10,7 +10,6 @@ "author": "", "license": "ISC", "dependencies": { - "express": "^4.17.1", - "express-validator": "^6.9.2" + "express": "^4.17.1" } } From e80bb0372b5486bdb4276367ec97990e3dd7cd82 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 00:53:51 +0100 Subject: [PATCH 27/73] Use express-validator, refactor --- api/package.json | 3 +- api/src/execute.js | 46 ++++++++ api/src/index.js | 165 ++++++++++----------------- api/src/languages.js | 265 +++++++++++++++++++++++++------------------ lxc/execute | 6 +- readme.md | 2 +- 6 files changed, 261 insertions(+), 226 deletions(-) create mode 100644 api/src/execute.js diff --git a/api/package.json b/api/package.json index b55f17c..cf6bf15 100644 --- a/api/package.json +++ b/api/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { - "express": "^4.17.1" + "express": "^4.17.1", + "express-validator": "^6.9.2" } } diff --git a/api/src/execute.js b/api/src/execute.js new file mode 100644 index 0000000..3642671 --- /dev/null +++ b/api/src/execute.js @@ -0,0 +1,46 @@ +const { writeFile } = require('fs/promises'); +const { spawn } = require('child_process'); + +async function execute(res, language, body) { + const stamp = new Date().getTime(); + const sourceFile = `/tmp/${stamp}.code`; + + await writeFile(sourceFile, body.source); + + const process = spawn(__dirname + '/../../lxc/execute', [ + language.name, + sourceFile, + body.args?.join('\n') ?? '', + ]); + + const result = { + ran: true, + language: language.name, + stderr: '', + stdout: '', + output: '', + }; + + if (language.version) + result.version = language.version; + + process.stderr.on('data', chunk => { + result.stderr += chunk; + result.output += chunk; + }); + + process.stdout.on('data', chunk => { + result.stdout += chunk; + result.output += chunk; + }); + + result.stderr = result.stderr.trim().substring(0, 65535); + result.stdout = result.stdout.trim().substring(0, 65535); + result.output = result.output.trim().substring(0, 65535); + + process.on('exit', () => res.json(result)); +} + +module.exports = { + execute, +}; diff --git a/api/src/index.js b/api/src/index.js index a7c769f..d0efee4 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -1,110 +1,63 @@ -const { writeFile } = require('fs/promises'); const express = require('express'); -const app = express(); -const languages = require('./languages'); -const { spawn } = require('child_process'); - -{ - const process = spawn(__dirname + '/../../lxc/versions'); - - let output = ''; - process.stderr.on('data', chunk => output += chunk); - process.stdout.on('data', chunk => output += chunk); - - process.on('exit', () => { - const sections = output.toLowerCase().split('---'); - const versions = {}; - - for (const section of sections) { - const lines = section.trim().split('\n'); - - if (lines.length >= 2) { - const language = lines[0]; - - if (language === 'java') { - versions[language] = /\d+/.exec(lines[1])?.[0]; - } else if (language === 'emacs') { - versions[language] = /\d+\.\d+/.exec(lines[1])?.[0]; - } else { - versions[language] = /\d+\.\d+\.\d+/.exec(section)?.[0]; - } - } - } - - for (const language of languages) { - language.version = versions[language.name]; - } - }); -} - -app.use(express.json()); - -app.post('/execute', (req, res) => { - const body = req.body; - - const language = languages.find(language => { - return language.aliases.includes(body.language?.toString()?.toLowerCase()); - }); - - if (!language) { - return res.status(400).json({ - code: 'unsupported_language', - message: `${body.language} is not supported by Piston`, - }); - } else if (typeof body.source !== 'string') { - return res.status(400).json({ - code: 'missing_source', - message: 'source field is invalid', - }); - } else if (body.args && !Array.isArray(body.args)) { - return res.status(400).json({ - code: 'invalid_args', - message: 'args field is not an array', - }); - } - - launch(res, language, body); -}); - -async function launch(res, language, body) { - const stamp = new Date().getTime(); - const sourceFile = `/tmp/${stamp}.code`; - - await writeFile(sourceFile, body.source); - - const process = spawn(__dirname + '/../../lxc/execute', [language.name, sourceFile, (body.args ?? []).join('\n')]); - - const result = { - ran: true, - language: language.name, - stderr: '', - stdout: '', - output: '', - }; - - if (language.version) - result.version = language.version; - - process.stderr.addListener('data', chunk => { - result.stderr += chunk; - result.output += chunk; - }); - - process.stdout.addListener('data', chunk => { - result.stdout += chunk; - result.output += chunk; - }); - - result.stderr = result.stderr.trim().substring(0, 65535); - result.stdout = result.stdout.trim().substring(0, 65535); - result.output = result.output.trim().substring(0, 65535); - - process.on('exit', () => res.json(result)); -} - -app.get('/versions', (req, res) => { - res.json(languages); -}); +const { execute } = require('./execute'); +const { languages } = require('./languages'); +const { checkSchema, validationResult } = require('express-validator'); const PORT = 2000; + +const app = express(); +app.use(express.json()); + +app.post( + '/execute', + checkSchema({ + language: { + in: 'body', + notEmpty: { + errorMessage: 'Supply a language field', + }, + isString: { + errorMessage: 'Supplied language is not a string', + }, + custom: { + options: value => languages.find(language => language.name === value?.toLowerCase()), + errorMessage: 'Supplied language is not supported by Piston', + }, + }, + source: { + in: 'body', + notEmpty: { + errorMessage: 'Supply a source field', + }, + isString: { + errorMessage: 'Supplied source is not a string', + }, + }, + args: { + in: 'body', + optional: true, + isArray: { + errorMessage: 'Supplied args is not an array', + }, + } + }), + (req, res) => { + const errors = validationResult(req).array(); + + if (errors.length === 0) { + const language = languages.find(language => + language.aliases.includes(req.body.language.toLowerCase()) + ); + + execute(res, language, req.body); + } else { + res.status(400).json({ + message: errors[0].msg, + }); + } + }, +); + +app.get('/versions', (_, res) => res.json(languages)); + app.listen(PORT, () => console.log(`Listening on port ${PORT}`)); diff --git a/api/src/languages.js b/api/src/languages.js index 34409cb..9fda547 100644 --- a/api/src/languages.js +++ b/api/src/languages.js @@ -1,114 +1,153 @@ -module.exports = [ - { - name: 'nasm', - aliases: ['asm', 'nasm'], - }, - { - name: 'nasm64', - aliases: ['asm64', 'nasm64'], - }, - { - name: 'awk', - aliases: ['awk'], - }, - { - name: 'bash', - aliases: ['bash'], - }, - { - name: 'brainfuck', - aliases: ['bf', 'brainfuck'], - }, - { - name: 'c', - aliases: ['c'], - }, - { - name: 'csharp', - aliases: ['c#', 'cs', 'csharp'], - }, - { - name: 'cpp', - aliases: ['c++', 'cpp'], - }, - { - name: 'deno', - aliases: ['deno', 'denojs', 'denots'], - }, - { - name: 'ruby', - aliases: ['duby', 'rb', 'ruby'], - }, - { - name: 'emacs', - aliases: ['el', 'elisp', 'emacs'], - }, - { - name: 'elixir', - aliases: ['elixir'], - }, - { - name: 'haskell', - aliases: ['haskell', 'hs'], - }, - { - name: 'go', - aliases: ['go'], - }, - { - name: 'java', - aliases: ['java'], - }, - { - name: 'node', - aliases: ['javascript', 'js', 'node'], - }, - { - name: 'jelly', - aliases: ['jelly'], - }, - { - name: 'julia', - aliases: ['jl', 'julia'], - }, - { - name: 'kotlin', - aliases: ['kotlin'], - }, - { - name: 'lua', - aliases: ['lua'], - }, - { - name: 'paradoc', - aliases: ['paradoc'], - }, - { - name: 'perl', - aliases: ['perl'], - }, - { - name: 'php', - aliases: ['php', 'php3', 'php4', 'php5'], - }, - { - name: 'python3', - aliases: ['py', 'py3', 'python', 'python3'], - }, - { - name: 'python2', - aliases: ['python2'], - }, - { - name: 'rust', - aliases: ['rs', 'rust'], - }, - { - name: 'swift', - aliases: ['swift'], - }, - { - name: 'typescript', - aliases: ['ts', 'typescript'], - }, +const { spawn } = require('child_process'); + +const languages = [ + { + name: 'nasm', + aliases: ['asm', 'nasm'], + }, + { + name: 'nasm64', + aliases: ['asm64', 'nasm64'], + }, + { + name: 'awk', + aliases: ['awk'], + }, + { + name: 'bash', + aliases: ['bash'], + }, + { + name: 'brainfuck', + aliases: ['bf', 'brainfuck'], + }, + { + name: 'c', + aliases: ['c'], + }, + { + name: 'csharp', + aliases: ['c#', 'cs', 'csharp'], + }, + { + name: 'cpp', + aliases: ['c++', 'cpp'], + }, + { + name: 'deno', + aliases: ['deno', 'denojs', 'denots'], + }, + { + name: 'ruby', + aliases: ['duby', 'rb', 'ruby'], + }, + { + name: 'emacs', + aliases: ['el', 'elisp', 'emacs'], + }, + { + name: 'elixir', + aliases: ['elixir'], + }, + { + name: 'haskell', + aliases: ['haskell', 'hs'], + }, + { + name: 'go', + aliases: ['go'], + }, + { + name: 'java', + aliases: ['java'], + }, + { + name: 'node', + aliases: ['javascript', 'js', 'node'], + }, + { + name: 'jelly', + aliases: ['jelly'], + }, + { + name: 'julia', + aliases: ['jl', 'julia'], + }, + { + name: 'kotlin', + aliases: ['kotlin'], + }, + { + name: 'lua', + aliases: ['lua'], + }, + { + name: 'paradoc', + aliases: ['paradoc'], + }, + { + name: 'perl', + aliases: ['perl'], + }, + { + name: 'php', + aliases: ['php', 'php3', 'php4', 'php5'], + }, + { + name: 'python3', + aliases: ['py', 'py3', 'python', 'python3'], + }, + { + name: 'python2', + aliases: ['python2'], + }, + { + name: 'rust', + aliases: ['rs', 'rust'], + }, + { + name: 'swift', + aliases: ['swift'], + }, + { + name: 'typescript', + aliases: ['ts', 'typescript'], + }, ]; + +{ + const process = spawn(__dirname + '/../../lxc/versions'); + + let output = ''; + process.stderr.on('data', chunk => output += chunk); + process.stdout.on('data', chunk => output += chunk); + + process.on('exit', () => { + const sections = output.toLowerCase().split('---'); + const versions = {}; + + for (const section of sections) { + const lines = section.trim().split('\n'); + + if (lines.length >= 2) { + const language = lines[0]; + + if (language === 'java') { + versions[language] = /\d+/.exec(lines[1])?.[0]; + } else if (language === 'emacs') { + versions[language] = /\d+\.\d+/.exec(lines[1])?.[0]; + } else { + versions[language] = /\d+\.\d+\.\d+/.exec(section)?.[0]; + } + } + } + + for (const language of languages) { + language.version = versions[language.name]; + } + }); +} + +module.exports = { + languages, +}; diff --git a/lxc/execute b/lxc/execute index c33d7f2..42d5b52 100755 --- a/lxc/execute +++ b/lxc/execute @@ -4,11 +4,7 @@ dir="$( cd "$( dirname "$0" )" && pwd )" touch $dir/lockfile -if [ -z "$1" ]; then - echo "invalid args" - exit -fi -if [ -z "$2" ]; then +if [ -z "$1" ] || [ -z "$2" ]; then echo "invalid args" exit fi diff --git a/readme.md b/readme.md index 4baecf8..5b2cb85 100644 --- a/readme.md +++ b/readme.md @@ -167,7 +167,7 @@ Content-Type: application/json - typescript #### Principle of Operation -Piston utilizes LXC as the primary mechanism for sandboxing. There is a small API written in Go which takes +Piston utilizes LXC as the primary mechanism for sandboxing. There is a small API written in Node which takes in execution requests and executes them in the container. High level, the API writes a temporary source and args file to `/tmp` and that gets mounted read-only along with the execution scripts into the container. The source file is either ran or compiled and ran (in the case of languages like c, c++, c#, go, etc.). From 420a104f5c228f2988f0b8d8908851fa30739d1b Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 00:59:25 +0100 Subject: [PATCH 28/73] Check aliases instead of name directly --- api/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/index.js b/api/src/index.js index d0efee4..c29a461 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -20,7 +20,7 @@ app.post( errorMessage: 'Supplied language is not a string', }, custom: { - options: value => languages.find(language => language.name === value?.toLowerCase()), + options: value => languages.find(language => language.aliases.includes(value?.toLowerCase())), errorMessage: 'Supplied language is not supported by Piston', }, }, From def096fbeabdbd490df05db10011fff189664402 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 01:03:49 +0100 Subject: [PATCH 29/73] Trim and subtring only after executing --- api/src/execute.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api/src/execute.js b/api/src/execute.js index 3642671..1409a7b 100644 --- a/api/src/execute.js +++ b/api/src/execute.js @@ -34,11 +34,13 @@ async function execute(res, language, body) { result.output += chunk; }); - result.stderr = result.stderr.trim().substring(0, 65535); - result.stdout = result.stdout.trim().substring(0, 65535); - result.output = result.output.trim().substring(0, 65535); + process.on('exit', () => { + result.stderr = result.stderr.trim().substring(0, 65535); + result.stdout = result.stdout.trim().substring(0, 65535); + result.output = result.output.trim().substring(0, 65535); - process.on('exit', () => res.json(result)); + res.json(result); + }); } module.exports = { From d666e5c19d70511ed11a5a375bf8e89d219bfa42 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 01:07:34 +0100 Subject: [PATCH 30/73] Fix C/C++ versions --- lxc/versions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxc/versions b/lxc/versions index 583feb7..098cb92 100755 --- a/lxc/versions +++ b/lxc/versions @@ -14,11 +14,11 @@ echo '1.0.0' echo '---' echo 'c' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "gcc -v" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "gcc --version" echo '---' echo 'cpp' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "g++ -v" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "g++ --version" echo '---' echo 'csharp' From d8b6379b9a4c4a4c40269da362e7349136528fcb Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 13:14:17 +0100 Subject: [PATCH 31/73] Add CLI written in Node --- api/src/execute.js | 48 ----------- api/src/index.js | 15 +++- api/src/languages.js | 116 +------------------------ cli/execute | 3 + cli/package.json | 12 +++ cli/src/index.js | 30 +++++++ lxc/test_all_lxc | 52 +++++------ shared/execute.js | 43 ++++++++++ shared/languages.json | 194 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 321 insertions(+), 192 deletions(-) delete mode 100644 api/src/execute.js create mode 100755 cli/execute create mode 100644 cli/package.json create mode 100644 cli/src/index.js create mode 100644 shared/execute.js create mode 100644 shared/languages.json diff --git a/api/src/execute.js b/api/src/execute.js deleted file mode 100644 index 1409a7b..0000000 --- a/api/src/execute.js +++ /dev/null @@ -1,48 +0,0 @@ -const { writeFile } = require('fs/promises'); -const { spawn } = require('child_process'); - -async function execute(res, language, body) { - const stamp = new Date().getTime(); - const sourceFile = `/tmp/${stamp}.code`; - - await writeFile(sourceFile, body.source); - - const process = spawn(__dirname + '/../../lxc/execute', [ - language.name, - sourceFile, - body.args?.join('\n') ?? '', - ]); - - const result = { - ran: true, - language: language.name, - stderr: '', - stdout: '', - output: '', - }; - - if (language.version) - result.version = language.version; - - process.stderr.on('data', chunk => { - result.stderr += chunk; - result.output += chunk; - }); - - process.stdout.on('data', chunk => { - result.stdout += chunk; - result.output += chunk; - }); - - process.on('exit', () => { - result.stderr = result.stderr.trim().substring(0, 65535); - result.stdout = result.stdout.trim().substring(0, 65535); - result.output = result.output.trim().substring(0, 65535); - - res.json(result); - }); -} - -module.exports = { - execute, -}; diff --git a/api/src/index.js b/api/src/index.js index c29a461..cd658c5 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -1,5 +1,5 @@ const express = require('express'); -const { execute } = require('./execute'); +const { execute } = require('../../shared/execute'); const { languages } = require('./languages'); const { checkSchema, validationResult } = require('express-validator'); @@ -41,7 +41,7 @@ app.post( }, } }), - (req, res) => { + async (req, res) => { const errors = validationResult(req).array(); if (errors.length === 0) { @@ -49,7 +49,16 @@ app.post( language.aliases.includes(req.body.language.toLowerCase()) ); - execute(res, language, req.body); + const { stdout, stderr, output } = await execute(language, req.body.source, req.body.args); + + res.status(200).json({ + ran: true, + language: language.name, + version: language.version, + stdout, + stderr, + output, + }); } else { res.status(400).json({ message: errors[0].msg, diff --git a/api/src/languages.js b/api/src/languages.js index 9fda547..23e352a 100644 --- a/api/src/languages.js +++ b/api/src/languages.js @@ -1,119 +1,5 @@ const { spawn } = require('child_process'); - -const languages = [ - { - name: 'nasm', - aliases: ['asm', 'nasm'], - }, - { - name: 'nasm64', - aliases: ['asm64', 'nasm64'], - }, - { - name: 'awk', - aliases: ['awk'], - }, - { - name: 'bash', - aliases: ['bash'], - }, - { - name: 'brainfuck', - aliases: ['bf', 'brainfuck'], - }, - { - name: 'c', - aliases: ['c'], - }, - { - name: 'csharp', - aliases: ['c#', 'cs', 'csharp'], - }, - { - name: 'cpp', - aliases: ['c++', 'cpp'], - }, - { - name: 'deno', - aliases: ['deno', 'denojs', 'denots'], - }, - { - name: 'ruby', - aliases: ['duby', 'rb', 'ruby'], - }, - { - name: 'emacs', - aliases: ['el', 'elisp', 'emacs'], - }, - { - name: 'elixir', - aliases: ['elixir'], - }, - { - name: 'haskell', - aliases: ['haskell', 'hs'], - }, - { - name: 'go', - aliases: ['go'], - }, - { - name: 'java', - aliases: ['java'], - }, - { - name: 'node', - aliases: ['javascript', 'js', 'node'], - }, - { - name: 'jelly', - aliases: ['jelly'], - }, - { - name: 'julia', - aliases: ['jl', 'julia'], - }, - { - name: 'kotlin', - aliases: ['kotlin'], - }, - { - name: 'lua', - aliases: ['lua'], - }, - { - name: 'paradoc', - aliases: ['paradoc'], - }, - { - name: 'perl', - aliases: ['perl'], - }, - { - name: 'php', - aliases: ['php', 'php3', 'php4', 'php5'], - }, - { - name: 'python3', - aliases: ['py', 'py3', 'python', 'python3'], - }, - { - name: 'python2', - aliases: ['python2'], - }, - { - name: 'rust', - aliases: ['rs', 'rust'], - }, - { - name: 'swift', - aliases: ['swift'], - }, - { - name: 'typescript', - aliases: ['ts', 'typescript'], - }, -]; +const languages = require('../../shared/languages.json'); { const process = spawn(__dirname + '/../../lxc/versions'); diff --git a/cli/execute b/cli/execute new file mode 100755 index 0000000..37a6b35 --- /dev/null +++ b/cli/execute @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +node src $* diff --git a/cli/package.json b/cli/package.json new file mode 100644 index 0000000..0166712 --- /dev/null +++ b/cli/package.json @@ -0,0 +1,12 @@ +{ + "name": "cli", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/cli/src/index.js b/cli/src/index.js new file mode 100644 index 0000000..c53d132 --- /dev/null +++ b/cli/src/index.js @@ -0,0 +1,30 @@ +const { execute } = require('../../shared/execute'); +const { readFileSync } = require('fs'); +const languages = require('../../shared/languages.json'); + +const [languageName, sourceFile, ...args] = process.argv.slice(2); + +(async () => { + if (!languageName) { + console.error('Provide a language name'); + return; + } + + if (!sourceFile) { + console.error('Provide a source file'); + return; + } + + const source = readFileSync(sourceFile); + + const language = languages.find(language => language.name === languageName); + + if (!language) { + console.error(`${languageName} is not supported by Piston`); + return; + } + + const { output } = await execute(language, source, args); + + console.log(output); +})(); diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 873c840..493c4b5 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -2,54 +2,54 @@ cd tests echo 'testing awk' -../execute awk test.awk +../../cli/execute awk test.awk echo 'testing c' -../execute c test.c +../../cli/execute c test.c echo 'testing cpp' -../execute cpp test.cpp +../../cli/execute cpp test.cpp echo 'testing cs' -../execute cs test.cs +../../cli/execute cs test.cs echo 'testing deno' -../execute deno testdeno.ts +../../cli/execute deno testdeno.ts echo 'testing elisp' -../execute elisp test.el +../../cli/execute elisp test.el echo 'testing elixir' -../execute exs test.exs +../../cli/execute exs test.exs echo 'testing go' -../execute go test.go +../../cli/execute go test.go echo 'testing haskell' -../execute haskell test.hs +../../cli/execute haskell test.hs echo 'testing java' -../execute java test.java +../../cli/execute java test.java echo 'testing jelly' -../execute jelly test.jelly +../../cli/execute jelly test.jelly echo 'testing jl' -../execute jl test.jl +../../cli/execute jl test.jl echo 'testing js' -../execute js test.js +../../cli/execute js test.js echo 'testing kotlin' -../execute kotlin test.kt +../../cli/execute kotlin test.kt echo 'testing asm 32 bit' -../execute asm test.nasm +../../cli/execute asm test.nasm echo 'testing asm 64 bit' -../execute asm64 test64.nasm +../../cli/execute asm64 test64.nasm echo 'testing php' -../execute php test.php +../../cli/execute php test.php echo 'testing perl' -../execute perl test.pl +../../cli/execute perl test.pl echo 'testing ruby' -../execute ruby test.rb +../../cli/execute ruby test.rb echo 'testing rust' -../execute rust test.rs +../../cli/execute rust test.rs echo 'testing bash' -../execute bash test.sh +../../cli/execute bash test.sh echo 'testing swift' -../execute swift test.swift +../../cli/execute swift test.swift echo 'testing typescript' -../execute typescript test.ts +../../cli/execute typescript test.ts echo 'testing python2' -../execute python2 test2.py +../../cli/execute python2 test2.py echo 'testing python3' -../execute python3 test3.py +../../cli/execute python3 test3.py echo 'testing paradoc' -../execute python3 test_paradoc.py +../../cli/execute python3 test_paradoc.py diff --git a/shared/execute.js b/shared/execute.js new file mode 100644 index 0000000..22c6dad --- /dev/null +++ b/shared/execute.js @@ -0,0 +1,43 @@ +const { writeFile } = require('fs/promises'); +const { spawn } = require('child_process'); + +function execute(language, source, args) { + return new Promise(async resolve => { + const stamp = new Date().getTime(); + const sourceFile = `/tmp/${stamp}.code`; + + await writeFile(sourceFile, source); + + const process = spawn(__dirname + '/../lxc/execute', [ + language.name, + sourceFile, + args?.join('\n') ?? '', + ]); + + let stdout = ''; + let stderr = ''; + let output = ''; + + process.stderr.on('data', chunk => { + stderr += chunk; + output += chunk; + }); + + process.stdout.on('data', chunk => { + stdout += chunk; + output += chunk; + }); + + process.on('exit', () => { + stderr = stderr.trim().substring(0, 65535); + stdout = stdout.trim().substring(0, 65535); + output = output.trim().substring(0, 65535); + + resolve({ stdout, stderr, output }); + }); + }); +} + +module.exports = { + execute, +}; diff --git a/shared/languages.json b/shared/languages.json new file mode 100644 index 0000000..ba04153 --- /dev/null +++ b/shared/languages.json @@ -0,0 +1,194 @@ +[ + { + "name": "nasm", + "aliases": [ + "asm", + "nasm" + ] + }, + { + "name": "nasm64", + "aliases": [ + "asm64", + "nasm64" + ] + }, + { + "name": "awk", + "aliases": [ + "awk" + ] + }, + { + "name": "bash", + "aliases": [ + "bash" + ] + }, + { + "name": "brainfuck", + "aliases": [ + "bf", + "brainfuck" + ] + }, + { + "name": "c", + "aliases": [ + "c" + ] + }, + { + "name": "csharp", + "aliases": [ + "c#", + "cs", + "csharp" + ] + }, + { + "name": "cpp", + "aliases": [ + "c++", + "cpp" + ] + }, + { + "name": "deno", + "aliases": [ + "deno", + "denojs", + "denots" + ] + }, + { + "name": "ruby", + "aliases": [ + "duby", + "rb", + "ruby" + ] + }, + { + "name": "emacs", + "aliases": [ + "el", + "elisp", + "emacs" + ] + }, + { + "name": "elixir", + "aliases": [ + "elixir" + ] + }, + { + "name": "haskell", + "aliases": [ + "haskell", + "hs" + ] + }, + { + "name": "go", + "aliases": [ + "go" + ] + }, + { + "name": "java", + "aliases": [ + "java" + ] + }, + { + "name": "node", + "aliases": [ + "javascript", + "js", + "node" + ] + }, + { + "name": "jelly", + "aliases": [ + "jelly" + ] + }, + { + "name": "julia", + "aliases": [ + "jl", + "julia" + ] + }, + { + "name": "kotlin", + "aliases": [ + "kotlin" + ] + }, + { + "name": "lua", + "aliases": [ + "lua" + ] + }, + { + "name": "paradoc", + "aliases": [ + "paradoc" + ] + }, + { + "name": "perl", + "aliases": [ + "perl" + ] + }, + { + "name": "php", + "aliases": [ + "php", + "php3", + "php4", + "php5" + ] + }, + { + "name": "python3", + "aliases": [ + "py", + "py3", + "python", + "python3" + ] + }, + { + "name": "python2", + "aliases": [ + "python2" + ] + }, + { + "name": "rust", + "aliases": [ + "rs", + "rust" + ] + }, + { + "name": "swift", + "aliases": [ + "swift" + ] + }, + { + "name": "typescript", + "aliases": [ + "ts", + "typescript" + ] + } +] From f78aa34c10875e1091b5fecebb224e4297991507 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 13:14:46 +0100 Subject: [PATCH 32/73] Read file as string in CLI --- cli/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/index.js b/cli/src/index.js index c53d132..02fdd56 100644 --- a/cli/src/index.js +++ b/cli/src/index.js @@ -15,7 +15,7 @@ const [languageName, sourceFile, ...args] = process.argv.slice(2); return; } - const source = readFileSync(sourceFile); + const source = readFileSync(sourceFile).toString(); const language = languages.find(language => language.name === languageName); From f685bdc7516fc9810e4848ecd799c80e17233c2a Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 13:27:14 +0100 Subject: [PATCH 33/73] Fix aliases, update readme --- cli/execute | 33 +++++++++++++++++++++++++++++++-- cli/package.json | 12 ------------ cli/src/index.js | 30 ------------------------------ readme.md | 8 +++++--- 4 files changed, 36 insertions(+), 47 deletions(-) delete mode 100644 cli/package.json delete mode 100644 cli/src/index.js diff --git a/cli/execute b/cli/execute index 37a6b35..a62d120 100755 --- a/cli/execute +++ b/cli/execute @@ -1,3 +1,32 @@ -#!/usr/bin/env bash +#!/usr/bin/env node -node src $* +const { execute } = require('../shared/execute'); +const { readFileSync } = require('fs'); +const languages = require('../shared/languages.json'); + +const [languageName, sourceFile, ...args] = process.argv.slice(2); + +(async () => { + if (!languageName) { + console.error('Provide a language name'); + return; + } + + if (!sourceFile) { + console.error('Provide a source file'); + return; + } + + const source = readFileSync(sourceFile).toString(); + + const language = languages.find(language => language.aliases.includes(languageName.toLowerCase())); + + if (!language) { + console.error(`${languageName} is not supported by Piston`); + return; + } + + const { output } = await execute(language, source, args); + + console.log(output); +})(); diff --git a/cli/package.json b/cli/package.json deleted file mode 100644 index 0166712..0000000 --- a/cli/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "cli", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC" -} diff --git a/cli/src/index.js b/cli/src/index.js deleted file mode 100644 index 02fdd56..0000000 --- a/cli/src/index.js +++ /dev/null @@ -1,30 +0,0 @@ -const { execute } = require('../../shared/execute'); -const { readFileSync } = require('fs'); -const languages = require('../../shared/languages.json'); - -const [languageName, sourceFile, ...args] = process.argv.slice(2); - -(async () => { - if (!languageName) { - console.error('Provide a language name'); - return; - } - - if (!sourceFile) { - console.error('Provide a source file'); - return; - } - - const source = readFileSync(sourceFile).toString(); - - const language = languages.find(language => language.name === languageName); - - if (!language) { - console.error(`${languageName} is not supported by Piston`); - return; - } - - const { output } = await execute(language, source, args); - - console.log(output); -})(); diff --git a/readme.md b/readme.md index 5b2cb85..05f8d93 100644 --- a/readme.md +++ b/readme.md @@ -47,7 +47,7 @@ See `var/install.txt` for how to create a new LXC container and install all of t software. #### CLI Usage -- `lxc/execute [language] [file path] [args]` +- `cli/execute [language] [file path] [args]` #### API Usage To use the API, it must first be started. Please note that if root is required to access @@ -79,14 +79,17 @@ Content-Type: application/json [ { "name": "awk", + "aliases": ["awk"], "version": "1.3.3" }, { "name": "bash", + "aliases": ["bash"], "version": "4.4.20" }, { "name": "c", + "aliases": ["c"], "version": "7.5.0" } ] @@ -130,8 +133,7 @@ HTTP/1.1 400 Bad Request Content-Type: application/json { - "code": "unsupported_language", - "message": "whatever is not supported by Piston" + "message": "Provided language is not supported by Piston" } ``` From 8fd831982eb3589333203fe3dffc5357528193f2 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 14:19:29 +0100 Subject: [PATCH 34/73] Make ran field do something --- api/src/index.js | 4 ++-- shared/execute.js | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index cd658c5..ba234fe 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -49,10 +49,10 @@ app.post( language.aliases.includes(req.body.language.toLowerCase()) ); - const { stdout, stderr, output } = await execute(language, req.body.source, req.body.args); + const { stdout, stderr, output, ran } = await execute(language, req.body.source, req.body.args); res.status(200).json({ - ran: true, + ran, language: language.name, version: language.version, stdout, diff --git a/shared/execute.js b/shared/execute.js index 22c6dad..ed612bf 100644 --- a/shared/execute.js +++ b/shared/execute.js @@ -28,12 +28,17 @@ function execute(language, source, args) { output += chunk; }); - process.on('exit', () => { + process.on('exit', code => { stderr = stderr.trim().substring(0, 65535); stdout = stdout.trim().substring(0, 65535); output = output.trim().substring(0, 65535); - resolve({ stdout, stderr, output }); + resolve({ + stdout, + stderr, + output, + ran: code === 0, + }); }); }); } From e9a14e8a47a784b63eac979210d8d99783c71b76 Mon Sep 17 00:00:00 2001 From: Josh Uy Date: Sat, 16 Jan 2021 10:01:35 -0700 Subject: [PATCH 35/73] README rewrite --- readme.md | 241 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 172 insertions(+), 69 deletions(-) diff --git a/readme.md b/readme.md index 5b2cb85..ca541ed 100644 --- a/readme.md +++ b/readme.md @@ -1,68 +1,175 @@ -## Piston +

Piston

+

+
+ engineer-man piston +

+ +

A high performance general purpose code execution engine.

+
+ +

+ + GitHub last commit + + GitHub issues + + GitHub pull requests +

+ +--- + +

+ About • + Public API • + Getting Started • + Usage • + Supported Languages • + Principles • + Security • + License +

+ +--- +
+ +# About + +

Piston is a high performance general purpose code execution engine. It excels at running untrusted and possibly malicious code without fear from any harmful effects. -It's used in numerous places including -[EMKC Challenges](https://emkc.org/challenges), -[EMKC Weekly Contests](https://emkc.org/contests), the -[Engineer Man Discord Server](https://discord.gg/engineerman) via -[I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers -and 100+ direct integrations. To get it in your own server, go here: https://emkc.org/run. +

+
-#### Use Public API -Requires no installation and you can use it immediately. Reference the Versions/Execute sections -below to learn about the request and response formats. -- `GET` `https://emkc.org/api/v1/piston/versions` -- `POST` `https://emkc.org/api/v1/piston/execute` +It's used in numerous places including: +* [EMKC Challenges](https://emkc.org/challenges), +* [EMKC Weekly Contests](https://emkc.org/contests), +* [Engineer Man Discord Server](https://discord.gg/engineerman), +* [I Run Code (Discord Bot)](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers +and 100+ direct integrations. -Important Note: The Piston API is rate limited to 5 requests per second. If you have a need for more requests than that +To get it in your own server, go here: https://emkc.org/run. + +
+ +# Public API + +- Requires no installation and you can use it immediately. +- Reference the Versions/Execute sections below to learn about the request and response formats. + +
+ +When using the public Piston API, use the base URL: + +``` +https://emkc.org/api/v1/piston +``` + +#### GET +``` +https://emkc.org/api/v1/piston/versions +``` +#### POST +``` +https://emkc.org/api/v1/piston/execute +``` + +> Important Note: The Piston API is rate limited to 5 requests per second. If you have a need for more requests than that and it's for a good cause, please reach out to me (EngineerMan#0001) on [Discord](https://discord.gg/engineerman) so we can discuss potentially getting you an unlimited key. -#### Cloning and System Dependencies -``` -# clone and enter repo -git clone https://github.com/engineer-man/piston -cd piston/lxc +
+ +# Getting Started + +### Host System Package Dependencies + +* NodeJS +* lxc +* libvirt + +
+ +If your OS is not documented below, please open pull requests with the correct commands for your OS. + +
+CentOS / RHEL + +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +nvm install --lts +nvm use --lts -# centos/rhel dependencies: yum install -y epel-release yum install -y lxc lxc-templates debootstrap libvirt systemctl start libvirtd +``` +
-# ubuntu server 18.04 dependencies: -apt install lxc lxc-templates debootstrap libvirt0 +
+Ubuntu (18.04) + +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +nvm install --lts +nvm use --lts + +apt install -y lxc lxc-templates debootstrap libvirt0 +``` +
+ +
+Arch Linux + +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +nvm install --lts +nvm use --lts -# arch dependencies: sudo pacman -S lxc libvirt unzip +``` +
-# everything else: -# not documented, please open pull requests with commands for debian/arch/macos/etc +#### After system dependencies are installed, clone this repository: + +```sh +# clone and enter repo +git clone https://github.com/engineer-man/piston +cd piston/lxc ``` #### Installation (simple) -Coming soon. -#### Installation (advanced/manual) -See `var/install.txt` for how to create a new LXC container and install all of the required +- Coming soon. + +#### Installation (advanced) + +- See `var/install.txt` for how to create a new LXC container and install all of the required software. -#### CLI Usage -- `lxc/execute [language] [file path] [args]` +
-#### API Usage +# Usage + +### CLI + +```sh +lxc/execute [language] [file path] [args] +``` + +### API To use the API, it must first be started. Please note that if root is required to access LXC then the API must also be running as root. To start the API, run the following: + ``` cd api ./start ``` -#### Base URLs -When using the public Piston API, use: -``` -https://emkc.org/api/v1/piston -``` -For your own local installation, use: +For your own local installation, the API is available at + ``` http://127.0.0.1:2000 ``` @@ -135,44 +242,38 @@ Content-Type: application/json } ``` -#### Supported Languages -- awk -- bash -- brainfuck -- c -- cpp -- csharp -- deno -- erlang -- elixir -- emacs -- elisp -- go -- haskell -- java -- jelly -- julia -- kotlin -- lua -- nasm -- node -- paradoc -- perl -- php -- python2 -- python3 -- ruby -- rust -- swift -- typescript +
-#### Principle of Operation +# Supported Languages +| | | +|:---------:|------------| +| awk | julia | +| bash | kotlin | +| brainfuck | lua | +| c | nasm | +| cpp | node | +| csharp | paradoc | +| deno | perl | +| erlang | php | +| elixir | python2 | +| emacs | python3 | +| elisp | ruby | +| go | rust | +| haskell | swift | +| java | typescript | +| jelly | | + +
+ +# Principle of Operation Piston utilizes LXC as the primary mechanism for sandboxing. There is a small API written in Node which takes in execution requests and executes them in the container. High level, the API writes a temporary source and args file to `/tmp` and that gets mounted read-only along with the execution scripts into the container. The source file is either ran or compiled and ran (in the case of languages like c, c++, c#, go, etc.). -#### Security +
+ +# Security LXC provides a great deal of security out of the box in that it's separate from the system. Piston takes additional steps to make it resistant to various privilege escalation, denial-of-service, and resource saturation threats. These steps include: @@ -186,5 +287,7 @@ various privilege escalation, denial-of-service, and resource saturation threats - Capping stdout to 65536 characters (resists yes/no bombs and runaway output) - SIGKILLing misbehaving code -#### License +
+ +# License Piston is licensed under the MIT license. From c537cab2da435ed31e080c198b82d745d7068efd Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 18:41:41 +0100 Subject: [PATCH 36/73] Add stdin --- api/src/index.js | 9 ++++++++- cli/execute | 2 +- lxc/execute | 4 +++- lxc/executors/bash | 2 +- lxc/executors/brainfuck | 2 +- lxc/executors/c | 2 +- lxc/executors/cpp | 2 +- lxc/executors/csharp | 2 +- lxc/executors/deno | 4 ++-- lxc/executors/elixir | 2 +- lxc/executors/emacs | 2 +- lxc/executors/go | 2 +- lxc/executors/haskell | 2 +- lxc/executors/java | 2 +- lxc/executors/jelly | 2 +- lxc/executors/julia | 2 +- lxc/executors/kotlin | 2 +- lxc/executors/lua | 2 +- lxc/executors/nasm | 2 +- lxc/executors/nasm64 | 2 +- lxc/executors/node | 4 ++-- lxc/executors/perl | 2 +- lxc/executors/php | 2 +- lxc/executors/python2 | 2 +- lxc/executors/python3 | 2 +- lxc/executors/ruby | 2 +- lxc/executors/rust | 2 +- lxc/executors/swift | 2 +- lxc/executors/typescript | 2 +- shared/execute.js | 3 ++- 30 files changed, 42 insertions(+), 32 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index ba234fe..70878ea 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -39,6 +39,13 @@ app.post( isArray: { errorMessage: 'Supplied args is not an array', }, + }, + stdin: { + in: 'body', + optional: true, + isString: { + errorMessage: 'Supplied stdin is not a string', + }, } }), async (req, res) => { @@ -49,7 +56,7 @@ app.post( language.aliases.includes(req.body.language.toLowerCase()) ); - const { stdout, stderr, output, ran } = await execute(language, req.body.source, req.body.args); + const { stdout, stderr, output, ran } = await execute(language, req.body.source, req.body.args, req.body.stdin); res.status(200).json({ ran, diff --git a/cli/execute b/cli/execute index a62d120..a8dc72c 100755 --- a/cli/execute +++ b/cli/execute @@ -26,7 +26,7 @@ const [languageName, sourceFile, ...args] = process.argv.slice(2); return; } - const { output } = await execute(language, source, args); + const { output } = await execute(language, source, '', args); console.log(output); })(); diff --git a/lxc/execute b/lxc/execute index 42d5b52..14db573 100755 --- a/lxc/execute +++ b/lxc/execute @@ -14,13 +14,15 @@ epoch=$(date +%s%N) basepath="/var/lib/lxc/piston/rootfs" filepath="/tmp/$epoch/code.code" argpath="/tmp/$epoch/args.args" +stdinpath="/tmp/$epoch/stdin.stdin" arg=$(basename $argpath) # write arg file mkdir -p $basepath/tmp/$epoch chmod 777 $basepath/tmp/$epoch cat $2 > $basepath$filepath -echo "${@:3}" > $basepath$argpath +cat $3 > $basepath$argpath +echo "${@:4}" > $basepath$argpath # process incrementor exec 200>$dir/lockfile diff --git a/lxc/executors/bash b/lxc/executors/bash index c13ad07..410e383 100755 --- a/lxc/executors/bash +++ b/lxc/executors/bash @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 bash code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 bash code.code < stdin.stdin" diff --git a/lxc/executors/brainfuck b/lxc/executors/brainfuck index b4458a0..94fc7d9 100755 --- a/lxc/executors/brainfuck +++ b/lxc/executors/brainfuck @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 brainfuck code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 brainfuck code.code < stdin.stdin" diff --git a/lxc/executors/c b/lxc/executors/c index 3130257..79ba5b0 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,4 +1,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ gcc -std=c11 -o binary -x c code.code ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" diff --git a/lxc/executors/cpp b/lxc/executors/cpp index 4b8c6cf..cfb02dd 100755 --- a/lxc/executors/cpp +++ b/lxc/executors/cpp @@ -1,4 +1,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ g++ -std=c++17 -o binary -x c++ code.code ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" diff --git a/lxc/executors/csharp b/lxc/executors/csharp index 2c742c7..f2ee2ea 100755 --- a/lxc/executors/csharp +++ b/lxc/executors/csharp @@ -1,4 +1,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 mono binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 mono binary < stdin.stdin" diff --git a/lxc/executors/deno b/lxc/executors/deno index b466288..1a92dc8 100755 --- a/lxc/executors/deno +++ b/lxc/executors/deno @@ -1,7 +1,7 @@ cd /tmp/$2 if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 deno run code.code" + runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 deno run code.code < stdin.stdin" else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 deno run code.code" + runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 deno run code.code < stdin.stdin" fi diff --git a/lxc/executors/elixir b/lxc/executors/elixir index 49f9679..664501f 100755 --- a/lxc/executors/elixir +++ b/lxc/executors/elixir @@ -3,5 +3,5 @@ cd /tmp/$2 if [[ -z $(grep '[^[:space:]]' args.args) ]]; then runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 elixir code.code" else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args ; xargs -d '\n' timeout -s KILL 3 elixir code.code" + runuser runner$1 -c "cd /tmp/$2 ; cat args.args ; xargs -d '\n' timeout -s KILL 3 elixir code.code < stdin.stdin" fi diff --git a/lxc/executors/emacs b/lxc/executors/emacs index 31f6186..6fb0553 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -3,5 +3,5 @@ cd /tmp/$2 if [[ -z $(grep '[^[:space:]]' args.args) ]]; then runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 emacs -Q --script code.code" else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 emacs -Q --script code.code" + runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 emacs -Q --script code.code < stdin.stdin" fi diff --git a/lxc/executors/go b/lxc/executors/go index 063af21..b713027 100755 --- a/lxc/executors/go +++ b/lxc/executors/go @@ -3,4 +3,4 @@ cp code.code interim.go file="interim.go" go build $file file=${file%%.*} -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./$file" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./$file < stdin.stdin" diff --git a/lxc/executors/haskell b/lxc/executors/haskell index 7593b60..becc27f 100755 --- a/lxc/executors/haskell +++ b/lxc/executors/haskell @@ -4,4 +4,4 @@ mv code.code code.hs runuser runner$1 -c "\ cd /tmp/$2 ; \ ghc -dynamic -o binary code.hs > /dev/null 2>&1 ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" diff --git a/lxc/executors/java b/lxc/executors/java index 6fc09e0..7f84d81 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -6,4 +6,4 @@ mv interim.java $name.java runuser runner$1 -c "\ cd /tmp/$2 ; \ javac $name.java ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 java $name" + cat args.args | xargs -d '\n' timeout -s KILL 3 java $name < stdin.stdin" diff --git a/lxc/executors/jelly b/lxc/executors/jelly index 4107b6b..32b79d9 100755 --- a/lxc/executors/jelly +++ b/lxc/executors/jelly @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 jelly fu code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 jelly fu code.code < stdin.stdin" diff --git a/lxc/executors/julia b/lxc/executors/julia index 7dddb24..3eeb323 100755 --- a/lxc/executors/julia +++ b/lxc/executors/julia @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 julia code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 julia code.code < stdin.stdin" diff --git a/lxc/executors/kotlin b/lxc/executors/kotlin index 5d5070a..6c034e6 100755 --- a/lxc/executors/kotlin +++ b/lxc/executors/kotlin @@ -3,4 +3,4 @@ cp code.code code.kt runuser runner$1 -c "\ cd /tmp/$2 ; \ kotlinc code.kt -include-runtime -d code.jar ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 java -jar code.jar" + cat args.args | xargs -d '\n' timeout -s KILL 3 java -jar code.jar < stdin.stdin" diff --git a/lxc/executors/lua b/lxc/executors/lua index b412013..a5ab76f 100755 --- a/lxc/executors/lua +++ b/lxc/executors/lua @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 lua code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 lua code.code < stdin.stdin" diff --git a/lxc/executors/nasm b/lxc/executors/nasm index 22026af..45e1d1c 100755 --- a/lxc/executors/nasm +++ b/lxc/executors/nasm @@ -2,4 +2,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ nasm -f elf32 -o binary.o code.code ; \ ld -m elf_i386 binary.o -o binary ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" diff --git a/lxc/executors/nasm64 b/lxc/executors/nasm64 index a6dc197..d498a54 100755 --- a/lxc/executors/nasm64 +++ b/lxc/executors/nasm64 @@ -2,4 +2,4 @@ runuser runner$1 -c "\ cd /tmp/$2 ; \ nasm -f elf64 -o binary.o code.code ; \ ld -m elf_x86_64 binary.o -o binary ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" diff --git a/lxc/executors/node b/lxc/executors/node index 5fd7d26..04113d2 100755 --- a/lxc/executors/node +++ b/lxc/executors/node @@ -1,7 +1,7 @@ cd /tmp/$2 if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 node code.code" + runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 node code.code < stdin.stdin" else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code" + runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code < stdin.stdin" fi diff --git a/lxc/executors/perl b/lxc/executors/perl index afb8ad5..9951e18 100755 --- a/lxc/executors/perl +++ b/lxc/executors/perl @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 perl code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 perl code.code < stdin.stdin" diff --git a/lxc/executors/php b/lxc/executors/php index d88a8d2..470f494 100755 --- a/lxc/executors/php +++ b/lxc/executors/php @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 php code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 php code.code < stdin.stdin" diff --git a/lxc/executors/python2 b/lxc/executors/python2 index d172f18..15b65de 100755 --- a/lxc/executors/python2 +++ b/lxc/executors/python2 @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python code.code < stdin.stdin" diff --git a/lxc/executors/python3 b/lxc/executors/python3 index 0749d88..a2bc47f 100755 --- a/lxc/executors/python3 +++ b/lxc/executors/python3 @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python3.8 code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python3.8 code.code < stdin.stdin" diff --git a/lxc/executors/ruby b/lxc/executors/ruby index 9de7477..5c5b181 100755 --- a/lxc/executors/ruby +++ b/lxc/executors/ruby @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ruby code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ruby code.code < stdin.stdin" diff --git a/lxc/executors/rust b/lxc/executors/rust index c939259..ad7d8e2 100755 --- a/lxc/executors/rust +++ b/lxc/executors/rust @@ -2,4 +2,4 @@ cd /tmp/$2 rustc -o binary code.code runuser runner$1 -c "\ cd /tmp/$2 ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" + cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" diff --git a/lxc/executors/swift b/lxc/executors/swift index 4b5d8a1..fd8eb9f 100755 --- a/lxc/executors/swift +++ b/lxc/executors/swift @@ -1,2 +1,2 @@ cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 swift code.code" +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 swift code.code < stdin.stdin" diff --git a/lxc/executors/typescript b/lxc/executors/typescript index 863d8d0..26adfba 100755 --- a/lxc/executors/typescript +++ b/lxc/executors/typescript @@ -4,4 +4,4 @@ runuser runner$1 -c "\ tsc interim.ts ; \ rm -f interim.ts ; \ mv interim.js code.code ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code" + cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code < stdin.stdin" diff --git a/shared/execute.js b/shared/execute.js index ed612bf..fbfd5de 100644 --- a/shared/execute.js +++ b/shared/execute.js @@ -1,7 +1,7 @@ const { writeFile } = require('fs/promises'); const { spawn } = require('child_process'); -function execute(language, source, args) { +function execute(language, source, args, stdin) { return new Promise(async resolve => { const stamp = new Date().getTime(); const sourceFile = `/tmp/${stamp}.code`; @@ -11,6 +11,7 @@ function execute(language, source, args) { const process = spawn(__dirname + '/../lxc/execute', [ language.name, sourceFile, + stdin ?? '', args?.join('\n') ?? '', ]); From ea547167748a1ec99fe98fa83ab053844db7f831 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 18:52:18 +0100 Subject: [PATCH 37/73] Fix order of args and stdin --- api/src/index.js | 2 +- shared/execute.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index 70878ea..d628ba1 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -56,7 +56,7 @@ app.post( language.aliases.includes(req.body.language.toLowerCase()) ); - const { stdout, stderr, output, ran } = await execute(language, req.body.source, req.body.args, req.body.stdin); + const { stdout, stderr, output, ran } = await execute(language, req.body.source, req.body.stdin, req.body.args); res.status(200).json({ ran, diff --git a/shared/execute.js b/shared/execute.js index fbfd5de..4124928 100644 --- a/shared/execute.js +++ b/shared/execute.js @@ -1,7 +1,7 @@ const { writeFile } = require('fs/promises'); const { spawn } = require('child_process'); -function execute(language, source, args, stdin) { +function execute(language, source, stdin, args) { return new Promise(async resolve => { const stamp = new Date().getTime(); const sourceFile = `/tmp/${stamp}.code`; From b7ba08ccdfb8570de10bd8b4e1d668815e7e25c8 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 16 Jan 2021 20:02:36 +0100 Subject: [PATCH 38/73] Fix stdin --- lxc/execute | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/execute b/lxc/execute index 14db573..3438547 100755 --- a/lxc/execute +++ b/lxc/execute @@ -21,7 +21,7 @@ arg=$(basename $argpath) mkdir -p $basepath/tmp/$epoch chmod 777 $basepath/tmp/$epoch cat $2 > $basepath$filepath -cat $3 > $basepath$argpath +echo $3 > $basepath$stdinpath echo "${@:4}" > $basepath$argpath # process incrementor From 008d55643b31b2cf516495ba87babd901e290e89 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 00:54:57 +0000 Subject: [PATCH 39/73] Fix stdin for most languages --- lxc/executors/bash | 8 ++++++-- lxc/executors/brainfuck | 8 ++++++-- lxc/executors/c | 11 +++++++---- lxc/executors/cpp | 11 +++++++---- lxc/executors/csharp | 11 +++++++---- lxc/executors/deno | 11 +++++------ lxc/executors/elixir | 11 +++++------ lxc/executors/emacs | 11 +++++------ lxc/executors/go | 14 ++++++++------ lxc/executors/haskell | 11 ++++++----- lxc/executors/java | 18 ++++++++++-------- lxc/executors/jelly | 8 ++++++-- lxc/executors/julia | 8 ++++++-- lxc/executors/kotlin | 14 ++++++++------ lxc/executors/lua | 8 ++++++-- lxc/executors/nasm | 13 ++++++++----- lxc/executors/nasm64 | 13 ++++++++----- lxc/executors/node | 11 +++++------ lxc/executors/perl | 8 ++++++-- lxc/executors/php | 8 ++++++-- lxc/executors/python2 | 8 ++++++-- lxc/executors/python3 | 8 ++++++-- lxc/executors/ruby | 8 ++++++-- lxc/executors/rust | 10 +++++++--- lxc/executors/swift | 8 ++++++-- lxc/executors/typescript | 17 ++++++++++------- 26 files changed, 172 insertions(+), 103 deletions(-) diff --git a/lxc/executors/bash b/lxc/executors/bash index 410e383..04ebb1c 100755 --- a/lxc/executors/bash +++ b/lxc/executors/bash @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 bash code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + xargs -a args.args -d '\n' timeout -s KILL 3 bash code.code < stdin.stdin +" diff --git a/lxc/executors/brainfuck b/lxc/executors/brainfuck index 94fc7d9..0503bcf 100755 --- a/lxc/executors/brainfuck +++ b/lxc/executors/brainfuck @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 brainfuck code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' brainfuck code.code < stdin.stdin +" diff --git a/lxc/executors/c b/lxc/executors/c index 79ba5b0..8d60422 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,4 +1,7 @@ -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - gcc -std=c11 -o binary -x c code.code ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" +#!/usr/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + gcc -std=c11 -o binary -x c code.code + timeout -s KILL 3 xargs -a args.args ./binary < stdin.stdin +" diff --git a/lxc/executors/cpp b/lxc/executors/cpp index cfb02dd..8602962 100755 --- a/lxc/executors/cpp +++ b/lxc/executors/cpp @@ -1,4 +1,7 @@ -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - g++ -std=c++17 -o binary -x c++ code.code ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + g++ -std=c++17 -o binary -x c++ code.code + timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin +" diff --git a/lxc/executors/csharp b/lxc/executors/csharp index f2ee2ea..4946e27 100755 --- a/lxc/executors/csharp +++ b/lxc/executors/csharp @@ -1,4 +1,7 @@ -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 mono binary < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary + timeout -s KILL 3 xargs -a args.args -d '\n' mono binary < stdin.stdin +" diff --git a/lxc/executors/deno b/lxc/executors/deno index 1a92dc8..a18c647 100755 --- a/lxc/executors/deno +++ b/lxc/executors/deno @@ -1,7 +1,6 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 deno run code.code < stdin.stdin" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 deno run code.code < stdin.stdin" -fi +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' deno run code.code < stdin.stdin +" diff --git a/lxc/executors/elixir b/lxc/executors/elixir index 664501f..0343cf1 100755 --- a/lxc/executors/elixir +++ b/lxc/executors/elixir @@ -1,7 +1,6 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 elixir code.code" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args ; xargs -d '\n' timeout -s KILL 3 elixir code.code < stdin.stdin" -fi +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' elixir code.code < stdin.stdin +" diff --git a/lxc/executors/emacs b/lxc/executors/emacs index 6fb0553..3a64ecc 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -1,7 +1,6 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 emacs -Q --script code.code" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 emacs -Q --script code.code < stdin.stdin" -fi +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin +" diff --git a/lxc/executors/go b/lxc/executors/go index b713027..a9aa4fd 100755 --- a/lxc/executors/go +++ b/lxc/executors/go @@ -1,6 +1,8 @@ -cd /tmp/$2 -cp code.code interim.go -file="interim.go" -go build $file -file=${file%%.*} -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./$file < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + cp code.code interim.go + go build interim.go + timeout -s KILL 3 xargs -a args.args -d '\n' ./interim < stdin.stdin +" diff --git a/lxc/executors/haskell b/lxc/executors/haskell index becc27f..bc13034 100755 --- a/lxc/executors/haskell +++ b/lxc/executors/haskell @@ -1,7 +1,8 @@ -cd /tmp/$2 -mv code.code code.hs +#!/bin/bash runuser runner$1 -c "\ - cd /tmp/$2 ; \ - ghc -dynamic -o binary code.hs > /dev/null 2>&1 ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" + cd /tmp/$2 + cp code.code code.hs + ghc -dynamic -o binary code.hs > /dev/null 2>&1 + timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin +" diff --git a/lxc/executors/java b/lxc/executors/java index 7f84d81..12ac347 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -1,9 +1,11 @@ -cd /tmp/$2 -cp code.code interim.java -name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\n\s{]+)" interim.java) -mv interim.java $name.java +#!/bin/bash -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - javac $name.java ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 java $name < stdin.stdin" +cd /tmp/$2 +name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\n\s{]+)" code.code) + +runuser runner$1 -c " + cd /tmp/$2 + cp code.code $name.java + javac $name.java + timeout -s KILL 3 xargs -a args.args -d '\n' java $name < stdin.stdin +" diff --git a/lxc/executors/jelly b/lxc/executors/jelly index 32b79d9..0c1b343 100755 --- a/lxc/executors/jelly +++ b/lxc/executors/jelly @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 jelly fu code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' jelly fu code.code < stdin.stdin +" diff --git a/lxc/executors/julia b/lxc/executors/julia index 3eeb323..4350335 100755 --- a/lxc/executors/julia +++ b/lxc/executors/julia @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 julia code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' julia code.code < stdin.stdin +" diff --git a/lxc/executors/kotlin b/lxc/executors/kotlin index 6c034e6..efd00e0 100755 --- a/lxc/executors/kotlin +++ b/lxc/executors/kotlin @@ -1,6 +1,8 @@ -cd /tmp/$2 -cp code.code code.kt -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - kotlinc code.kt -include-runtime -d code.jar ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 java -jar code.jar < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + cp code.code code.kt + kotlinc code.kt -include-runtime -d code.jar + timeout -s KILL 3 xargs -a args.args -d '\n' java -jar code.jar < stdin.stdin +" diff --git a/lxc/executors/lua b/lxc/executors/lua index a5ab76f..c318a87 100755 --- a/lxc/executors/lua +++ b/lxc/executors/lua @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 lua code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' lua code.code < stdin.stdin +" diff --git a/lxc/executors/nasm b/lxc/executors/nasm index 45e1d1c..f48e5bc 100755 --- a/lxc/executors/nasm +++ b/lxc/executors/nasm @@ -1,5 +1,8 @@ -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - nasm -f elf32 -o binary.o code.code ; \ - ld -m elf_i386 binary.o -o binary ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + nasm -f elf32 -o binary.o code.code + ld -m elf_i386 binary.o -o binary + timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin +" diff --git a/lxc/executors/nasm64 b/lxc/executors/nasm64 index d498a54..23ad450 100755 --- a/lxc/executors/nasm64 +++ b/lxc/executors/nasm64 @@ -1,5 +1,8 @@ -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - nasm -f elf64 -o binary.o code.code ; \ - ld -m elf_x86_64 binary.o -o binary ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + nasm -f elf64 -o binary.o code.code + ld -m elf_x86_64 binary.o -o binary + timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin +" diff --git a/lxc/executors/node b/lxc/executors/node index 04113d2..b43fff0 100755 --- a/lxc/executors/node +++ b/lxc/executors/node @@ -1,7 +1,6 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 node code.code < stdin.stdin" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code < stdin.stdin" -fi +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' node code.code < stdin.stdin +" diff --git a/lxc/executors/perl b/lxc/executors/perl index 9951e18..8657564 100755 --- a/lxc/executors/perl +++ b/lxc/executors/perl @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 perl code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' perl code.code < stdin.stdin +" diff --git a/lxc/executors/php b/lxc/executors/php index 470f494..2acacb9 100755 --- a/lxc/executors/php +++ b/lxc/executors/php @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 php code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' php code.code < stdin.stdin +" diff --git a/lxc/executors/python2 b/lxc/executors/python2 index 15b65de..ab90f29 100755 --- a/lxc/executors/python2 +++ b/lxc/executors/python2 @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' python code.code < stdin.stdin +" diff --git a/lxc/executors/python3 b/lxc/executors/python3 index a2bc47f..a944242 100755 --- a/lxc/executors/python3 +++ b/lxc/executors/python3 @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python3.8 code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' python3.8 code.code < stdin.stdin +" diff --git a/lxc/executors/ruby b/lxc/executors/ruby index 5c5b181..9407d75 100755 --- a/lxc/executors/ruby +++ b/lxc/executors/ruby @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ruby code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' ruby code.code < stdin.stdin +" diff --git a/lxc/executors/rust b/lxc/executors/rust index ad7d8e2..2a70609 100755 --- a/lxc/executors/rust +++ b/lxc/executors/rust @@ -1,5 +1,9 @@ +#!/bin/bash + cd /tmp/$2 rustc -o binary code.code -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary < stdin.stdin" + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin +" diff --git a/lxc/executors/swift b/lxc/executors/swift index fd8eb9f..6e0565d 100755 --- a/lxc/executors/swift +++ b/lxc/executors/swift @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 swift code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 xargs -a args.args -d '\n' swift code.code < stdin.stdin +" diff --git a/lxc/executors/typescript b/lxc/executors/typescript index 26adfba..20a382f 100755 --- a/lxc/executors/typescript +++ b/lxc/executors/typescript @@ -1,7 +1,10 @@ -runuser runner$1 -c "\ - cd /tmp/$2 ; \ - mv code.code interim.ts ; \ - tsc interim.ts ; \ - rm -f interim.ts ; \ - mv interim.js code.code ; \ - cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code < stdin.stdin" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + mv code.code interim.ts + tsc interim.ts + rm -f interim.ts + mv interim.js code.code + xargs -a args.args -d '\n' timeout -s KILL 3 node code.code < stdin.stdin +" From e637a95b335a361cb754c8e0932accca64d34dd4 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 01:12:13 +0000 Subject: [PATCH 40/73] Make execute.js support older Node versions --- shared/execute.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/execute.js b/shared/execute.js index 4124928..188a123 100644 --- a/shared/execute.js +++ b/shared/execute.js @@ -1,18 +1,18 @@ -const { writeFile } = require('fs/promises'); +const { writeFileSync } = require('fs'); const { spawn } = require('child_process'); -function execute(language, source, stdin, args) { - return new Promise(async resolve => { +function execute(language, source, stdin = '', args = []) { + return new Promise(resolve => { const stamp = new Date().getTime(); const sourceFile = `/tmp/${stamp}.code`; - await writeFile(sourceFile, source); + writeFileSync(sourceFile, source); const process = spawn(__dirname + '/../lxc/execute', [ language.name, sourceFile, - stdin ?? '', - args?.join('\n') ?? '', + stdin, + args.join('\n'), ]); let stdout = ''; From e462a7d41eb328dd0e0753335e090586cf087715 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 01:23:49 +0000 Subject: [PATCH 41/73] Add additional aliases for languages --- shared/languages.json | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/shared/languages.json b/shared/languages.json index ba04153..b158de2 100644 --- a/shared/languages.json +++ b/shared/languages.json @@ -50,7 +50,9 @@ "name": "cpp", "aliases": [ "c++", - "cpp" + "cpp", + "cc", + "cxx" ] }, { @@ -80,7 +82,8 @@ { "name": "elixir", "aliases": [ - "elixir" + "elixir", + "exs" ] }, { @@ -93,7 +96,8 @@ { "name": "go", "aliases": [ - "go" + "go", + "golang" ] }, { @@ -107,7 +111,8 @@ "aliases": [ "javascript", "js", - "node" + "node", + "node.js" ] }, { @@ -126,7 +131,8 @@ { "name": "kotlin", "aliases": [ - "kotlin" + "kotlin", + "kt" ] }, { @@ -144,7 +150,8 @@ { "name": "perl", "aliases": [ - "perl" + "perl", + "pl" ] }, { @@ -168,7 +175,8 @@ { "name": "python2", "aliases": [ - "python2" + "python2", + "py2" ] }, { From 14565b16e424e8fccf9833e667e0b5f0ad55d38b Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 13:50:40 +0000 Subject: [PATCH 42/73] Compile rust as runner --- api/src/index.js | 2 +- lxc/execute | 20 ++++++++++++-------- lxc/executors/paradoc | 8 ++++++-- lxc/executors/rust | 4 +--- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index d628ba1..d9a5cae 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -20,7 +20,7 @@ app.post( errorMessage: 'Supplied language is not a string', }, custom: { - options: value => languages.find(language => language.aliases.includes(value?.toLowerCase())), + options: value => value && languages.find(language => language.aliases.includes(value.toLowerCase())), errorMessage: 'Supplied language is not supported by Piston', }, }, diff --git a/lxc/execute b/lxc/execute index 3438547..29c445b 100755 --- a/lxc/execute +++ b/lxc/execute @@ -45,13 +45,17 @@ timeout -s KILL 20 \ # process janitor lxc-attach --clear-env -n piston -- \ - /bin/bash -l -c "\ - for i in {1..100}; do pkill -u runner$newinc --signal SIGKILL; done ;\ - find /tmp -user runner$newinc -exec /bin/rm -rf {} \; ;\ - find /var/tmp -user runner$newinc -exec /bin/rm -rf {} \; ;\ - find /var/lock -user runner$newinc -exec /bin/rm -rf {} \; ;\ - find /dev/shm -user runner$newinc -exec /bin/rm -rf {} \; ;\ - find /run/lock -user runner$newinc -exec /bin/rm -rf {} \; ;\ - " > /dev/null 2>&1 & + /bin/bash -l -c " + for i in {1..100} + do + pkill -u runner$newinc --signal SIGKILL + done + + find /tmp -user runner$newinc -delete + find /var/tmp -user runner$newinc -delete + find /var/lock -user runner$newinc -delete + find /dev/shm -user runner$newinc -delete + find /run/lock -user runner$newinc -delete + " > /dev/null 2>&1 & rm -rf $basepath/tmp/$epoch diff --git a/lxc/executors/paradoc b/lxc/executors/paradoc index 33fe880..08e6e2c 100755 --- a/lxc/executors/paradoc +++ b/lxc/executors/paradoc @@ -1,2 +1,6 @@ -cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 python3 -m paradoc code.code <<< args.args" +#!/bin/bash + +runuser runner$1 -c " + cd /tmp/$2 + timeout -s KILL 3 python3 -m paradoc code.code < args.args +" diff --git a/lxc/executors/rust b/lxc/executors/rust index 2a70609..9dc32ea 100755 --- a/lxc/executors/rust +++ b/lxc/executors/rust @@ -1,9 +1,7 @@ #!/bin/bash -cd /tmp/$2 -rustc -o binary code.code - runuser runner$1 -c " cd /tmp/$2 + rustc -o binary code.code timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin " From 9851352f87a7dbbc9b4e032c86420f93b407e6a9 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 15:44:40 +0000 Subject: [PATCH 43/73] Move runuser to execute --- lxc/execute | 2 +- lxc/executors/awk | 2 +- lxc/executors/bash | 6 ++---- lxc/executors/brainfuck | 6 ++---- lxc/executors/c | 8 +++----- lxc/executors/cpp | 8 +++----- lxc/executors/csharp | 8 +++----- lxc/executors/deno | 6 ++---- lxc/executors/elixir | 6 ++---- lxc/executors/emacs | 6 ++---- lxc/executors/go | 10 ++++------ lxc/executors/haskell | 10 ++++------ lxc/executors/java | 10 +++------- lxc/executors/jelly | 6 ++---- lxc/executors/julia | 6 ++---- lxc/executors/kotlin | 10 ++++------ lxc/executors/lua | 6 ++---- lxc/executors/nasm | 10 ++++------ lxc/executors/nasm64 | 10 ++++------ lxc/executors/node | 6 ++---- lxc/executors/paradoc | 6 ++---- lxc/executors/perl | 6 ++---- lxc/executors/php | 6 ++---- lxc/executors/python2 | 6 ++---- lxc/executors/python3 | 6 ++---- lxc/executors/ruby | 6 ++---- lxc/executors/rust | 8 +++----- lxc/executors/swift | 6 ++---- lxc/executors/typescript | 14 ++++++-------- lxc/start | 2 +- 30 files changed, 76 insertions(+), 132 deletions(-) diff --git a/lxc/execute b/lxc/execute index 29c445b..d7e5b22 100755 --- a/lxc/execute +++ b/lxc/execute @@ -41,7 +41,7 @@ exec 200>&- # runner timeout -s KILL 20 \ lxc-attach --clear-env -n piston -- \ - /bin/bash -l -c "bash /exec/$lang $newinc $epoch" + /bin/bash -l -c "runuser runner$newinc /exec/$lang $newinc $epoch" # process janitor lxc-attach --clear-env -n piston -- \ diff --git a/lxc/executors/awk b/lxc/executors/awk index 26723b3..67cdee8 100755 --- a/lxc/executors/awk +++ b/lxc/executors/awk @@ -1,4 +1,4 @@ cd /tmp/$2 timeout -s KILL 2 sed "/___code___/Q" code.code > code.stdin timeout -s KILL 2 sed "1,/___code___/d" code.code > code.awk -runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 awk -f code.awk < code.stdin" +timeout -s KILL 3 awk -f code.awk < code.stdin diff --git a/lxc/executors/bash b/lxc/executors/bash index 04ebb1c..6aeb899 100755 --- a/lxc/executors/bash +++ b/lxc/executors/bash @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - xargs -a args.args -d '\n' timeout -s KILL 3 bash code.code < stdin.stdin -" +cd /tmp/$2 +xargs -a args.args -d '\n' timeout -s KILL 3 bash code.code < stdin.stdin diff --git a/lxc/executors/brainfuck b/lxc/executors/brainfuck index 0503bcf..7ec1bfe 100755 --- a/lxc/executors/brainfuck +++ b/lxc/executors/brainfuck @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' brainfuck code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' brainfuck code.code < stdin.stdin diff --git a/lxc/executors/c b/lxc/executors/c index 8d60422..096b1d9 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,7 +1,5 @@ #!/usr/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - gcc -std=c11 -o binary -x c code.code - timeout -s KILL 3 xargs -a args.args ./binary < stdin.stdin -" +cd /tmp/$2 +gcc -std=c11 -o binary -x c code.code +timeout -s KILL 3 xargs -a args.args ./binary < stdin.stdin diff --git a/lxc/executors/cpp b/lxc/executors/cpp index 8602962..5f7008b 100755 --- a/lxc/executors/cpp +++ b/lxc/executors/cpp @@ -1,7 +1,5 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - g++ -std=c++17 -o binary -x c++ code.code - timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin -" +cd /tmp/$2 +g++ -std=c++17 -o binary -x c++ code.code +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/csharp b/lxc/executors/csharp index 4946e27..f35c876 100755 --- a/lxc/executors/csharp +++ b/lxc/executors/csharp @@ -1,7 +1,5 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary - timeout -s KILL 3 xargs -a args.args -d '\n' mono binary < stdin.stdin -" +cd /tmp/$2 +mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary +timeout -s KILL 3 xargs -a args.args -d '\n' mono binary < stdin.stdin diff --git a/lxc/executors/deno b/lxc/executors/deno index a18c647..31132fa 100755 --- a/lxc/executors/deno +++ b/lxc/executors/deno @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' deno run code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' deno run code.code < stdin.stdin diff --git a/lxc/executors/elixir b/lxc/executors/elixir index 0343cf1..49bfb78 100755 --- a/lxc/executors/elixir +++ b/lxc/executors/elixir @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' elixir code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' elixir code.code < stdin.stdin diff --git a/lxc/executors/emacs b/lxc/executors/emacs index 3a64ecc..ab41624 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin diff --git a/lxc/executors/go b/lxc/executors/go index a9aa4fd..09c1e68 100755 --- a/lxc/executors/go +++ b/lxc/executors/go @@ -1,8 +1,6 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - cp code.code interim.go - go build interim.go - timeout -s KILL 3 xargs -a args.args -d '\n' ./interim < stdin.stdin -" +cd /tmp/$2 +cp code.code interim.go +go build interim.go +timeout -s KILL 3 xargs -a args.args -d '\n' ./interim < stdin.stdin diff --git a/lxc/executors/haskell b/lxc/executors/haskell index bc13034..df517d9 100755 --- a/lxc/executors/haskell +++ b/lxc/executors/haskell @@ -1,8 +1,6 @@ #!/bin/bash -runuser runner$1 -c "\ - cd /tmp/$2 - cp code.code code.hs - ghc -dynamic -o binary code.hs > /dev/null 2>&1 - timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin -" +cd /tmp/$2 +cp code.code code.hs +ghc -dynamic -o binary code.hs > /dev/null 2>&1 +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/java b/lxc/executors/java index 12ac347..52f4cf0 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -2,10 +2,6 @@ cd /tmp/$2 name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\n\s{]+)" code.code) - -runuser runner$1 -c " - cd /tmp/$2 - cp code.code $name.java - javac $name.java - timeout -s KILL 3 xargs -a args.args -d '\n' java $name < stdin.stdin -" +cp code.code $name.java +javac $name.java +timeout -s KILL 3 xargs -a args.args -d '\n' java $name < stdin.stdin diff --git a/lxc/executors/jelly b/lxc/executors/jelly index 0c1b343..945444e 100755 --- a/lxc/executors/jelly +++ b/lxc/executors/jelly @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' jelly fu code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' jelly fu code.code < stdin.stdin diff --git a/lxc/executors/julia b/lxc/executors/julia index 4350335..e8b4ea5 100755 --- a/lxc/executors/julia +++ b/lxc/executors/julia @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' julia code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' julia code.code < stdin.stdin diff --git a/lxc/executors/kotlin b/lxc/executors/kotlin index efd00e0..c304575 100755 --- a/lxc/executors/kotlin +++ b/lxc/executors/kotlin @@ -1,8 +1,6 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - cp code.code code.kt - kotlinc code.kt -include-runtime -d code.jar - timeout -s KILL 3 xargs -a args.args -d '\n' java -jar code.jar < stdin.stdin -" +cd /tmp/$2 +cp code.code code.kt +kotlinc code.kt -include-runtime -d code.jar +timeout -s KILL 3 xargs -a args.args -d '\n' java -jar code.jar < stdin.stdin diff --git a/lxc/executors/lua b/lxc/executors/lua index c318a87..4caa4b6 100755 --- a/lxc/executors/lua +++ b/lxc/executors/lua @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' lua code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' lua code.code < stdin.stdin diff --git a/lxc/executors/nasm b/lxc/executors/nasm index f48e5bc..ffe8fd0 100755 --- a/lxc/executors/nasm +++ b/lxc/executors/nasm @@ -1,8 +1,6 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - nasm -f elf32 -o binary.o code.code - ld -m elf_i386 binary.o -o binary - timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin -" +cd /tmp/$2 +nasm -f elf32 -o binary.o code.code +ld -m elf_i386 binary.o -o binary +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/nasm64 b/lxc/executors/nasm64 index 23ad450..98c2aab 100755 --- a/lxc/executors/nasm64 +++ b/lxc/executors/nasm64 @@ -1,8 +1,6 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - nasm -f elf64 -o binary.o code.code - ld -m elf_x86_64 binary.o -o binary - timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin -" +cd /tmp/$2 +nasm -f elf64 -o binary.o code.code +ld -m elf_x86_64 binary.o -o binary +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/node b/lxc/executors/node index b43fff0..3262b53 100755 --- a/lxc/executors/node +++ b/lxc/executors/node @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' node code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' node code.code < stdin.stdin diff --git a/lxc/executors/paradoc b/lxc/executors/paradoc index 08e6e2c..be58dad 100755 --- a/lxc/executors/paradoc +++ b/lxc/executors/paradoc @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 python3 -m paradoc code.code < args.args -" +cd /tmp/$2 +timeout -s KILL 3 python3 -m paradoc code.code < args.args diff --git a/lxc/executors/perl b/lxc/executors/perl index 8657564..8b65855 100755 --- a/lxc/executors/perl +++ b/lxc/executors/perl @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' perl code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' perl code.code < stdin.stdin diff --git a/lxc/executors/php b/lxc/executors/php index 2acacb9..9f21f7b 100755 --- a/lxc/executors/php +++ b/lxc/executors/php @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' php code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' php code.code < stdin.stdin diff --git a/lxc/executors/python2 b/lxc/executors/python2 index ab90f29..5fa1c3e 100755 --- a/lxc/executors/python2 +++ b/lxc/executors/python2 @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' python code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' python code.code < stdin.stdin diff --git a/lxc/executors/python3 b/lxc/executors/python3 index a944242..6cb93f8 100755 --- a/lxc/executors/python3 +++ b/lxc/executors/python3 @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' python3.8 code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' python3.8 code.code < stdin.stdin diff --git a/lxc/executors/ruby b/lxc/executors/ruby index 9407d75..ebb9b06 100755 --- a/lxc/executors/ruby +++ b/lxc/executors/ruby @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' ruby code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' ruby code.code < stdin.stdin diff --git a/lxc/executors/rust b/lxc/executors/rust index 9dc32ea..137dffa 100755 --- a/lxc/executors/rust +++ b/lxc/executors/rust @@ -1,7 +1,5 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - rustc -o binary code.code - timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin -" +cd /tmp/$2 +rustc -o binary code.code +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/swift b/lxc/executors/swift index 6e0565d..a8327f7 100755 --- a/lxc/executors/swift +++ b/lxc/executors/swift @@ -1,6 +1,4 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - timeout -s KILL 3 xargs -a args.args -d '\n' swift code.code < stdin.stdin -" +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' swift code.code < stdin.stdin diff --git a/lxc/executors/typescript b/lxc/executors/typescript index 20a382f..8c1873d 100755 --- a/lxc/executors/typescript +++ b/lxc/executors/typescript @@ -1,10 +1,8 @@ #!/bin/bash -runuser runner$1 -c " - cd /tmp/$2 - mv code.code interim.ts - tsc interim.ts - rm -f interim.ts - mv interim.js code.code - xargs -a args.args -d '\n' timeout -s KILL 3 node code.code < stdin.stdin -" +cd /tmp/$2 +mv code.code interim.ts +tsc interim.ts +rm -f interim.ts +mv interim.js code.code +timeout -s KILL 3 xargs -a args.args -d '\n' node code.code < stdin.stdin diff --git a/lxc/start b/lxc/start index 6c13c98..fec7aef 100755 --- a/lxc/start +++ b/lxc/start @@ -3,7 +3,7 @@ mkdir -p /var/lib/lxc/piston/rootfs/exec rm -f /var/lib/lxc/piston/rootfs/exec/* cp -f executors/* /var/lib/lxc/piston/rootfs/exec -chmod 700 /var/lib/lxc/piston/rootfs/exec/* +chmod 555 /var/lib/lxc/piston/rootfs/exec/* chown -R root:root /var/lib/lxc/piston/rootfs/exec lxc-start -n piston -d From 7f03de9f71707145751266405c613b054b44f98b Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 15:53:46 +0000 Subject: [PATCH 44/73] Add shebang to awk --- lxc/executors/awk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lxc/executors/awk b/lxc/executors/awk index 67cdee8..dafa525 100755 --- a/lxc/executors/awk +++ b/lxc/executors/awk @@ -1,3 +1,5 @@ +#!/bin/bash + cd /tmp/$2 timeout -s KILL 2 sed "/___code___/Q" code.code > code.stdin timeout -s KILL 2 sed "1,/___code___/d" code.code > code.awk From 4c04ebdee0a531acdefdd9460b9fba81d954b29e Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Sun, 17 Jan 2021 14:45:58 -0600 Subject: [PATCH 45/73] Update readme.md --- readme.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index ca541ed..625537d 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,9 @@ -

Piston

-
- engineer-man piston + engineer-man piston + Piston +

+

+

A high performance general purpose code execution engine.

From f041385f34b0d0777129c1fc0bd57e103d4b257b Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Sun, 17 Jan 2021 14:46:17 -0600 Subject: [PATCH 46/73] Update readme.md --- readme.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/readme.md b/readme.md index 625537d..0702805 100644 --- a/readme.md +++ b/readme.md @@ -2,9 +2,6 @@ engineer-man piston Piston -

- -

A high performance general purpose code execution engine.


From 1c99570e671f10fac04473d2e43f2be0c28bafa8 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 22:29:45 +0000 Subject: [PATCH 47/73] Change awk executor --- lxc/executors/awk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lxc/executors/awk b/lxc/executors/awk index dafa525..8590654 100755 --- a/lxc/executors/awk +++ b/lxc/executors/awk @@ -1,6 +1,4 @@ #!/bin/bash cd /tmp/$2 -timeout -s KILL 2 sed "/___code___/Q" code.code > code.stdin -timeout -s KILL 2 sed "1,/___code___/d" code.code > code.awk -timeout -s KILL 3 awk -f code.awk < code.stdin +timeout -s KILL 3 awk -f code.code < stdin.stdin From 2b1f213beab77d24bf201dacfc1af6c798bf9ee6 Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 22:30:02 +0000 Subject: [PATCH 48/73] Change rust install instructions --- var/install.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/var/install.txt b/var/install.txt index 9be572e..ae81b05 100644 --- a/var/install.txt +++ b/var/install.txt @@ -96,11 +96,13 @@ make make install # install rust -# final binary: /opt/.cargo/bin/rustc -# get version: /opt/.cargo/bin/rustc --version -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -echo 'export PATH=$PATH:/opt/.cargo/bin' >> /opt/.profile -source /opt/.profile +# final binary: /usr/local/bin/rustc +# get version: /usr/local/bin/rustc --version +cd /opt && mkdir rust && cd rust +wget https://static.rust-lang.org/dist/rust-1.49.0-x86_64-unknown-linux-gnu.tar.gz +tar -xzf rust-1.49.0-x86_64-unknown-linux-gnu.tar.gz +cd rust-1.49.0-x86_64-unknown-linux-gnu +./install.sh # install swift # final binary: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift From a2eeff85b5ae4a363adc75581cbb76cb1d48a02d Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sun, 17 Jan 2021 22:36:52 +0000 Subject: [PATCH 49/73] Revert back to the mess the awk executor was --- lxc/executors/awk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lxc/executors/awk b/lxc/executors/awk index 8590654..dafa525 100755 --- a/lxc/executors/awk +++ b/lxc/executors/awk @@ -1,4 +1,6 @@ #!/bin/bash cd /tmp/$2 -timeout -s KILL 3 awk -f code.code < stdin.stdin +timeout -s KILL 2 sed "/___code___/Q" code.code > code.stdin +timeout -s KILL 2 sed "1,/___code___/d" code.code > code.awk +timeout -s KILL 3 awk -f code.awk < code.stdin From 8de614ee9435e9792872ad317e9684f31c3d63f3 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 13:47:25 -0600 Subject: [PATCH 50/73] escape backslash --- lxc/executors/java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/executors/java b/lxc/executors/java index 6fc09e0..1ad5cad 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -1,6 +1,6 @@ cd /tmp/$2 cp code.code interim.java -name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\n\s{]+)" interim.java) +name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\\\n\s{]+)" interim.java) mv interim.java $name.java runuser runner$1 -c "\ From 80e0304424b7763ef3c136ed1ce98e71430aa60e Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 13:43:47 -0600 Subject: [PATCH 51/73] readme updates --- readme.md | 2 +- var/archive.txt | 24 ++++++++++++++++++++++++ var/install.txt | 4 ++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 var/archive.txt diff --git a/readme.md b/readme.md index 0702805..acd5078 100644 --- a/readme.md +++ b/readme.md @@ -127,7 +127,7 @@ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash nvm install --lts nvm use --lts -sudo pacman -S lxc libvirt unzip +pacman -S lxc libvirt unzip ``` diff --git a/var/archive.txt b/var/archive.txt new file mode 100644 index 0000000..7767b8b --- /dev/null +++ b/var/archive.txt @@ -0,0 +1,24 @@ +# make piston image +lxc-clone -KMP /mnt/piston_image piston piston +sed -i 's/\/mnt\/piston_image/\/var\/lib\/lxc/' piston/config +tar -czf piston.tar.gz piston/ + +# restore piston image +cd /var/lib/lxc +tar -xzf piston.tar.gz + + + + + +``` +# get piston image +cd /var/lib/lxc +wget whatever url +tar -xzf piston.tar.gz +sed -i "s/virtbr0/$(ip a | grep br0: | cut -d' ' -f2 | sed 's/://gi')/" piston/config + +# start piston +cd /path/to/piston/lxc +./start +``` diff --git a/var/install.txt b/var/install.txt index 9be572e..282403e 100644 --- a/var/install.txt +++ b/var/install.txt @@ -234,6 +234,10 @@ chmod -R o-w * rm -rf /home/ubuntu chmod 777 /tmp +# disable cron +systemctl stop cron +systemctl disable cron + # leave container exit From 95adaf574442be1a9ad64ea9bded3df87e7d54ea Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 14:11:31 -0600 Subject: [PATCH 52/73] add new rust instructions --- var/install.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/var/install.txt b/var/install.txt index 9be572e..ae81b05 100644 --- a/var/install.txt +++ b/var/install.txt @@ -96,11 +96,13 @@ make make install # install rust -# final binary: /opt/.cargo/bin/rustc -# get version: /opt/.cargo/bin/rustc --version -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -echo 'export PATH=$PATH:/opt/.cargo/bin' >> /opt/.profile -source /opt/.profile +# final binary: /usr/local/bin/rustc +# get version: /usr/local/bin/rustc --version +cd /opt && mkdir rust && cd rust +wget https://static.rust-lang.org/dist/rust-1.49.0-x86_64-unknown-linux-gnu.tar.gz +tar -xzf rust-1.49.0-x86_64-unknown-linux-gnu.tar.gz +cd rust-1.49.0-x86_64-unknown-linux-gnu +./install.sh # install swift # final binary: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift From 402ec32f8b85dd7eb17d0e9918c77cd90566d446 Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Thu, 21 Jan 2021 21:48:06 +0000 Subject: [PATCH 53/73] Updated python3 commands to use 3.8 --- lxc/test_all_lxc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 493c4b5..cff05a1 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -50,6 +50,6 @@ echo 'testing typescript' echo 'testing python2' ../../cli/execute python2 test2.py echo 'testing python3' -../../cli/execute python3 test3.py +../../cli/execute python3.8 test3.py echo 'testing paradoc' -../../cli/execute python3 test_paradoc.py +../../cli/execute python3.8 test_paradoc.py From 6c1e4082e0a32c14ed2bd95bf24edb3bb7281f3a Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Thu, 21 Jan 2021 21:49:17 +0000 Subject: [PATCH 54/73] Updated paradoc executor to use python3.8 --- lxc/executors/paradoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/executors/paradoc b/lxc/executors/paradoc index be58dad..50aab63 100755 --- a/lxc/executors/paradoc +++ b/lxc/executors/paradoc @@ -1,4 +1,4 @@ #!/bin/bash cd /tmp/$2 -timeout -s KILL 3 python3 -m paradoc code.code < args.args +timeout -s KILL 3 python3.8 -m paradoc code.code < args.args From 3fc860788be10060bd2d1dc5f1858ce7d4301513 Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Thu, 21 Jan 2021 21:51:26 +0000 Subject: [PATCH 55/73] Moved paradoc path to executor --- lxc/executors/paradoc | 1 + 1 file changed, 1 insertion(+) diff --git a/lxc/executors/paradoc b/lxc/executors/paradoc index 50aab63..f82630a 100755 --- a/lxc/executors/paradoc +++ b/lxc/executors/paradoc @@ -1,4 +1,5 @@ #!/bin/bash cd /tmp/$2 +export PYTHONPATH=$PYTHONPATH:/opt/paradoc timeout -s KILL 3 python3.8 -m paradoc code.code < args.args From 4a160ac5abd75e6fbce0df155e42f9e897ff08f6 Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Thu, 21 Jan 2021 21:53:17 +0000 Subject: [PATCH 56/73] Convert paradoc test execution to call bash script --- lxc/test_all_lxc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index cff05a1..c9de1b7 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -52,4 +52,4 @@ echo 'testing python2' echo 'testing python3' ../../cli/execute python3.8 test3.py echo 'testing paradoc' -../../cli/execute python3.8 test_paradoc.py +../../cli/execute bash test_paradoc.sh From 7ab437399276327ddb0babd8375177d98828c28b Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Thu, 21 Jan 2021 22:05:28 +0000 Subject: [PATCH 57/73] Convert paradoc test to bash script Now loads the paradoc correctly and gets paradoc to print the result --- lxc/tests/test_paradoc.py | 5 ----- lxc/tests/test_paradoc.sh | 11 +++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 lxc/tests/test_paradoc.py create mode 100644 lxc/tests/test_paradoc.sh diff --git a/lxc/tests/test_paradoc.py b/lxc/tests/test_paradoc.py deleted file mode 100644 index 3acba15..0000000 --- a/lxc/tests/test_paradoc.py +++ /dev/null @@ -1,5 +0,0 @@ -try: - import paradoc - print('good') -except: - pass diff --git a/lxc/tests/test_paradoc.sh b/lxc/tests/test_paradoc.sh new file mode 100644 index 0000000..5f70e1c --- /dev/null +++ b/lxc/tests/test_paradoc.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# add paradoc module to python python +export PYTHONPATH=$PYTHONPATH:/opt/paradoc +# file for test code +test_code=/tmp/paradoc.test +# save test code to file +echo -n iP>$test_code +# pass param to paradoc module and have it print it +echo good | python3.8 -m paradoc $test_code +# clean test code +rm -f $test_code From ef549ff0c235923ae39d341c411087d76523b427 Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Thu, 21 Jan 2021 22:12:23 +0000 Subject: [PATCH 58/73] Removed paradoc from pythonpath This supposedly conflicts with other executors so I have moved it to the individual executor and test in previous commits --- var/install.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/var/install.txt b/var/install.txt index ae81b05..c9b151c 100644 --- a/var/install.txt +++ b/var/install.txt @@ -55,8 +55,6 @@ source /opt/.profile # therefore it cannot be run directly as it requires python3 to be installed cd /opt && mkdir paradoc && cd paradoc git clone https://github.com/betaveros/paradoc.git -echo 'export PYTHONPATH=$PYTHONPATH:/opt/paradoc/paradoc' >> /opt/.profile -source /opt/.profile # install node.js # final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/node From 36ff6c8282e09c0631fe605f1cad2cca56b35454 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 18:32:30 -0600 Subject: [PATCH 59/73] fix awk maybe --- lxc/executors/awk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lxc/executors/awk b/lxc/executors/awk index dafa525..395424f 100755 --- a/lxc/executors/awk +++ b/lxc/executors/awk @@ -1,6 +1,4 @@ #!/bin/bash cd /tmp/$2 -timeout -s KILL 2 sed "/___code___/Q" code.code > code.stdin -timeout -s KILL 2 sed "1,/___code___/d" code.code > code.awk -timeout -s KILL 3 awk -f code.awk < code.stdin +timeout -s KILL 3 xargs -a args.args -d '\n' awk -f code.code < stdin.stdin From 92f6f15a47764c26bf2036101a60b4e5935924c7 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 18:50:05 -0600 Subject: [PATCH 60/73] update error messages --- api/src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index d9a5cae..a2b5265 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -14,7 +14,7 @@ app.post( language: { in: 'body', notEmpty: { - errorMessage: 'Supply a language field', + errorMessage: 'No language supplied', }, isString: { errorMessage: 'Supplied language is not a string', @@ -27,7 +27,7 @@ app.post( source: { in: 'body', notEmpty: { - errorMessage: 'Supply a source field', + errorMessage: 'No source supplied', }, isString: { errorMessage: 'Supplied source is not a string', From df246707f2a5b1c3bf1c07c38918e331e999d028 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 19:03:09 -0600 Subject: [PATCH 61/73] clean up lingering .code file on host --- lxc/execute | 1 + 1 file changed, 1 insertion(+) diff --git a/lxc/execute b/lxc/execute index d7e5b22..eb36b54 100755 --- a/lxc/execute +++ b/lxc/execute @@ -59,3 +59,4 @@ lxc-attach --clear-env -n piston -- \ " > /dev/null 2>&1 & rm -rf $basepath/tmp/$epoch +rm /tmp/$2 From b85605a34058aad5d13b23ad6015327e43bd8007 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 19:05:04 -0600 Subject: [PATCH 62/73] revert --- lxc/execute | 1 - 1 file changed, 1 deletion(-) diff --git a/lxc/execute b/lxc/execute index eb36b54..d7e5b22 100755 --- a/lxc/execute +++ b/lxc/execute @@ -59,4 +59,3 @@ lxc-attach --clear-env -n piston -- \ " > /dev/null 2>&1 & rm -rf $basepath/tmp/$epoch -rm /tmp/$2 From 037dedd1626c62c59c1531b2ce86f70418cd543f Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 19:07:23 -0600 Subject: [PATCH 63/73] remove temp file after running --- shared/execute.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shared/execute.js b/shared/execute.js index 188a123..6547ca8 100644 --- a/shared/execute.js +++ b/shared/execute.js @@ -1,4 +1,4 @@ -const { writeFileSync } = require('fs'); +const { writeFileSync, unlinkSync } = require('fs'); const { spawn } = require('child_process'); function execute(language, source, stdin = '', args = []) { @@ -28,8 +28,10 @@ function execute(language, source, stdin = '', args = []) { stdout += chunk; output += chunk; }); - + process.on('exit', code => { + unlinkSync(sourceFile); + stderr = stderr.trim().substring(0, 65535); stdout = stdout.trim().substring(0, 65535); output = output.trim().substring(0, 65535); From b72c429c42520949d8d7ea724ef0bd55ee17d440 Mon Sep 17 00:00:00 2001 From: Pyroseza Date: Fri, 22 Jan 2021 01:19:21 +0000 Subject: [PATCH 64/73] =?UTF-8?q?=E2=94=AC=E2=94=80=E2=94=AC=20=E3=83=8E(?= =?UTF-8?q?=20=E3=82=9C-=E3=82=9C=E3=83=8E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lxc/test_all_lxc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index c9de1b7..122ccc4 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -50,6 +50,6 @@ echo 'testing typescript' echo 'testing python2' ../../cli/execute python2 test2.py echo 'testing python3' -../../cli/execute python3.8 test3.py +../../cli/execute python3 test3.py echo 'testing paradoc' ../../cli/execute bash test_paradoc.sh From 8db0dc0b6d8cb7f6c8ad7a44224a83ecf60760f7 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 19:32:43 -0600 Subject: [PATCH 65/73] dont use xargs for elisp if no args were passed --- lxc/executors/emacs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lxc/executors/emacs b/lxc/executors/emacs index ab41624..bf586e4 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -1,4 +1,8 @@ #!/bin/bash cd /tmp/$2 -timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin +if [[ -z $(grep '[^[:space:]]' args.args) ]]; then + timeout -s KILL 3 emacs -Q --script code.code < stdin.stdin +else + timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin +fi From 6d69a1b189291a7c871c2d70f24b5610b8b0fd0e Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Thu, 21 Jan 2021 19:38:00 -0600 Subject: [PATCH 66/73] revert emacs code, omit newline in args file so languages stop seeing a blank arg --- lxc/execute | 2 +- lxc/executors/emacs | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lxc/execute b/lxc/execute index d7e5b22..824b578 100755 --- a/lxc/execute +++ b/lxc/execute @@ -22,7 +22,7 @@ mkdir -p $basepath/tmp/$epoch chmod 777 $basepath/tmp/$epoch cat $2 > $basepath$filepath echo $3 > $basepath$stdinpath -echo "${@:4}" > $basepath$argpath +echo -n "${@:4}" > $basepath$argpath # process incrementor exec 200>$dir/lockfile diff --git a/lxc/executors/emacs b/lxc/executors/emacs index bf586e4..ab41624 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -1,8 +1,4 @@ #!/bin/bash cd /tmp/$2 -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - timeout -s KILL 3 emacs -Q --script code.code < stdin.stdin -else - timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin -fi +timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin From 0a414f2d3fef3e3bed48e0c6bd47da111aca2388 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 22 Jan 2021 02:17:28 -0600 Subject: [PATCH 67/73] add locale for elixir, fix test for kotlin, add instructions for bf installation --- lxc/executors/elixir | 2 ++ lxc/tests/test.kt | 2 +- var/install.txt | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lxc/executors/elixir b/lxc/executors/elixir index 49bfb78..1a8e23f 100755 --- a/lxc/executors/elixir +++ b/lxc/executors/elixir @@ -1,4 +1,6 @@ #!/bin/bash +export LC_ALL="en_US.UTF-8" + cd /tmp/$2 timeout -s KILL 3 xargs -a args.args -d '\n' elixir code.code < stdin.stdin diff --git a/lxc/tests/test.kt b/lxc/tests/test.kt index a6f9758..1e0df2c 100644 --- a/lxc/tests/test.kt +++ b/lxc/tests/test.kt @@ -1,3 +1,3 @@ -fun main(args: Array) { +fun main() { println("good") } diff --git a/var/install.txt b/var/install.txt index c9b151c..988e465 100644 --- a/var/install.txt +++ b/var/install.txt @@ -215,6 +215,14 @@ echo 'export DENO_INSTALL="/opt/.deno"' >> /opt/.profile echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /opt/.profile source /opt/.profile +# install brainfuck +cd /opt && mkdir bf && cd bf +git clone https://github.com/texus/Brainfuck-interpreter +cd Brainfuck-interpreter +echo 'export PATH=$PATH:/opt/bf/Brainfuck-interpreter' >> /opt/.profile +source /opt/.profile + + # create runnable users and apply limits for i in {1..150}; do useradd -M runner$i From ca59f7e882560e7b800b30a9789a891618c82d99 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 22 Jan 2021 02:19:02 -0600 Subject: [PATCH 68/73] update awk test --- lxc/tests/test.awk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lxc/tests/test.awk b/lxc/tests/test.awk index de48d9a..c5ba5ad 100644 --- a/lxc/tests/test.awk +++ b/lxc/tests/test.awk @@ -1,3 +1 @@ -good -___code___ -{ print } +{ print "good" } From e3473f99df7bd18acd33e4dea7f981cace90648a Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 22 Jan 2021 02:31:48 -0600 Subject: [PATCH 69/73] rename tests so they make more sense --- lxc/test_all_lxc | 98 +++++++++++------------ lxc/tests/{test.awk => awk.awk} | 0 lxc/tests/{test.sh => bash.sh} | 0 lxc/tests/{test.c => c.c} | 0 lxc/tests/{test.cpp => cpp.cpp} | 0 lxc/tests/{test.cs => csharp.cs} | 0 lxc/tests/{testdeno.ts => deno.ts} | 0 lxc/tests/{test.exs => elixir.exs} | 0 lxc/tests/{test.el => emacs.el} | 0 lxc/tests/{test.go => go.go} | 0 lxc/tests/{test.hs => haskell.hs} | 0 lxc/tests/{test.java => java.java} | 0 lxc/tests/jelly.jelly | 1 + lxc/tests/{test.jl => julia.jl} | 0 lxc/tests/{test.kt => kotlin.kt} | 0 lxc/tests/{test.nasm => nasm.nasm} | 0 lxc/tests/{test64.nasm => nasm64.nasm} | 0 lxc/tests/{test.nim => nim.nim} | 0 lxc/tests/{test.js => node.js} | 0 lxc/tests/{test_paradoc.sh => paradoc.sh} | 0 lxc/tests/{test.pl => perl.pl} | 0 lxc/tests/{test.php => php.php} | 0 lxc/tests/{test2.py => python2.py} | 0 lxc/tests/{test3.py => python3.py} | 0 lxc/tests/{test.rb => ruby.rb} | 0 lxc/tests/{test.rs => rust.rs} | 0 lxc/tests/{test.swift => swift.swift} | 0 lxc/tests/test.jelly | 1 - lxc/tests/{test.ts => typescript.ts} | 0 29 files changed, 50 insertions(+), 50 deletions(-) rename lxc/tests/{test.awk => awk.awk} (100%) rename lxc/tests/{test.sh => bash.sh} (100%) rename lxc/tests/{test.c => c.c} (100%) rename lxc/tests/{test.cpp => cpp.cpp} (100%) rename lxc/tests/{test.cs => csharp.cs} (100%) rename lxc/tests/{testdeno.ts => deno.ts} (100%) rename lxc/tests/{test.exs => elixir.exs} (100%) rename lxc/tests/{test.el => emacs.el} (100%) rename lxc/tests/{test.go => go.go} (100%) rename lxc/tests/{test.hs => haskell.hs} (100%) rename lxc/tests/{test.java => java.java} (100%) create mode 100644 lxc/tests/jelly.jelly rename lxc/tests/{test.jl => julia.jl} (100%) rename lxc/tests/{test.kt => kotlin.kt} (100%) rename lxc/tests/{test.nasm => nasm.nasm} (100%) rename lxc/tests/{test64.nasm => nasm64.nasm} (100%) rename lxc/tests/{test.nim => nim.nim} (100%) rename lxc/tests/{test.js => node.js} (100%) rename lxc/tests/{test_paradoc.sh => paradoc.sh} (100%) rename lxc/tests/{test.pl => perl.pl} (100%) rename lxc/tests/{test.php => php.php} (100%) rename lxc/tests/{test2.py => python2.py} (100%) rename lxc/tests/{test3.py => python3.py} (100%) rename lxc/tests/{test.rb => ruby.rb} (100%) rename lxc/tests/{test.rs => rust.rs} (100%) rename lxc/tests/{test.swift => swift.swift} (100%) delete mode 100644 lxc/tests/test.jelly rename lxc/tests/{test.ts => typescript.ts} (100%) diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 122ccc4..473e888 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -2,54 +2,54 @@ cd tests echo 'testing awk' -../../cli/execute awk test.awk -echo 'testing c' -../../cli/execute c test.c -echo 'testing cpp' -../../cli/execute cpp test.cpp -echo 'testing cs' -../../cli/execute cs test.cs -echo 'testing deno' -../../cli/execute deno testdeno.ts -echo 'testing elisp' -../../cli/execute elisp test.el -echo 'testing elixir' -../../cli/execute exs test.exs -echo 'testing go' -../../cli/execute go test.go -echo 'testing haskell' -../../cli/execute haskell test.hs -echo 'testing java' -../../cli/execute java test.java -echo 'testing jelly' -../../cli/execute jelly test.jelly -echo 'testing jl' -../../cli/execute jl test.jl -echo 'testing js' -../../cli/execute js test.js -echo 'testing kotlin' -../../cli/execute kotlin test.kt -echo 'testing asm 32 bit' -../../cli/execute asm test.nasm -echo 'testing asm 64 bit' -../../cli/execute asm64 test64.nasm -echo 'testing php' -../../cli/execute php test.php -echo 'testing perl' -../../cli/execute perl test.pl -echo 'testing ruby' -../../cli/execute ruby test.rb -echo 'testing rust' -../../cli/execute rust test.rs +../../cli/execute awk awk.awk echo 'testing bash' -../../cli/execute bash test.sh -echo 'testing swift' -../../cli/execute swift test.swift -echo 'testing typescript' -../../cli/execute typescript test.ts -echo 'testing python2' -../../cli/execute python2 test2.py -echo 'testing python3' -../../cli/execute python3 test3.py +../../cli/execute bash bash.sh +echo 'testing c' +../../cli/execute c c.c +echo 'testing cpp' +../../cli/execute cpp cpp.cpp +echo 'testing csharp' +../../cli/execute csharp csharp.cs +echo 'testing deno' +../../cli/execute deno deno.ts +echo 'testing elixir' +../../cli/execute elixir elixir.exs +echo 'testing emacs' +../../cli/execute emacs emacs.el +echo 'testing go' +../../cli/execute go go.go +echo 'testing haskell' +../../cli/execute haskell haskell.hs +echo 'testing java' +../../cli/execute java java.java +echo 'testing jelly' +../../cli/execute jelly jelly.jelly good +echo 'testing julia' +../../cli/execute julia julia.jl +echo 'testing kotlin' +../../cli/execute kotlin kotlin.kt +echo 'testing nasm 32 bit' +../../cli/execute nasm nasm.nasm +echo 'testing nasm 64 bit' +../../cli/execute nasm64 nasm64.nasm +echo 'testing node' +../../cli/execute node node.js echo 'testing paradoc' -../../cli/execute bash test_paradoc.sh +../../cli/execute bash paradoc.sh +echo 'testing perl' +../../cli/execute perl perl.pl +echo 'testing php' +../../cli/execute php php.php +echo 'testing python2' +../../cli/execute python2 python2.py +echo 'testing python3' +../../cli/execute python3 python3.py +echo 'testing ruby' +../../cli/execute ruby ruby.rb +echo 'testing rust' +../../cli/execute rust rust.rs +echo 'testing swift' +../../cli/execute swift swift.swift +echo 'testing typescript' +../../cli/execute typescript typescript.ts diff --git a/lxc/tests/test.awk b/lxc/tests/awk.awk similarity index 100% rename from lxc/tests/test.awk rename to lxc/tests/awk.awk diff --git a/lxc/tests/test.sh b/lxc/tests/bash.sh similarity index 100% rename from lxc/tests/test.sh rename to lxc/tests/bash.sh diff --git a/lxc/tests/test.c b/lxc/tests/c.c similarity index 100% rename from lxc/tests/test.c rename to lxc/tests/c.c diff --git a/lxc/tests/test.cpp b/lxc/tests/cpp.cpp similarity index 100% rename from lxc/tests/test.cpp rename to lxc/tests/cpp.cpp diff --git a/lxc/tests/test.cs b/lxc/tests/csharp.cs similarity index 100% rename from lxc/tests/test.cs rename to lxc/tests/csharp.cs diff --git a/lxc/tests/testdeno.ts b/lxc/tests/deno.ts similarity index 100% rename from lxc/tests/testdeno.ts rename to lxc/tests/deno.ts diff --git a/lxc/tests/test.exs b/lxc/tests/elixir.exs similarity index 100% rename from lxc/tests/test.exs rename to lxc/tests/elixir.exs diff --git a/lxc/tests/test.el b/lxc/tests/emacs.el similarity index 100% rename from lxc/tests/test.el rename to lxc/tests/emacs.el diff --git a/lxc/tests/test.go b/lxc/tests/go.go similarity index 100% rename from lxc/tests/test.go rename to lxc/tests/go.go diff --git a/lxc/tests/test.hs b/lxc/tests/haskell.hs similarity index 100% rename from lxc/tests/test.hs rename to lxc/tests/haskell.hs diff --git a/lxc/tests/test.java b/lxc/tests/java.java similarity index 100% rename from lxc/tests/test.java rename to lxc/tests/java.java diff --git a/lxc/tests/jelly.jelly b/lxc/tests/jelly.jelly new file mode 100644 index 0000000..77a1774 --- /dev/null +++ b/lxc/tests/jelly.jelly @@ -0,0 +1 @@ +³ diff --git a/lxc/tests/test.jl b/lxc/tests/julia.jl similarity index 100% rename from lxc/tests/test.jl rename to lxc/tests/julia.jl diff --git a/lxc/tests/test.kt b/lxc/tests/kotlin.kt similarity index 100% rename from lxc/tests/test.kt rename to lxc/tests/kotlin.kt diff --git a/lxc/tests/test.nasm b/lxc/tests/nasm.nasm similarity index 100% rename from lxc/tests/test.nasm rename to lxc/tests/nasm.nasm diff --git a/lxc/tests/test64.nasm b/lxc/tests/nasm64.nasm similarity index 100% rename from lxc/tests/test64.nasm rename to lxc/tests/nasm64.nasm diff --git a/lxc/tests/test.nim b/lxc/tests/nim.nim similarity index 100% rename from lxc/tests/test.nim rename to lxc/tests/nim.nim diff --git a/lxc/tests/test.js b/lxc/tests/node.js similarity index 100% rename from lxc/tests/test.js rename to lxc/tests/node.js diff --git a/lxc/tests/test_paradoc.sh b/lxc/tests/paradoc.sh similarity index 100% rename from lxc/tests/test_paradoc.sh rename to lxc/tests/paradoc.sh diff --git a/lxc/tests/test.pl b/lxc/tests/perl.pl similarity index 100% rename from lxc/tests/test.pl rename to lxc/tests/perl.pl diff --git a/lxc/tests/test.php b/lxc/tests/php.php similarity index 100% rename from lxc/tests/test.php rename to lxc/tests/php.php diff --git a/lxc/tests/test2.py b/lxc/tests/python2.py similarity index 100% rename from lxc/tests/test2.py rename to lxc/tests/python2.py diff --git a/lxc/tests/test3.py b/lxc/tests/python3.py similarity index 100% rename from lxc/tests/test3.py rename to lxc/tests/python3.py diff --git a/lxc/tests/test.rb b/lxc/tests/ruby.rb similarity index 100% rename from lxc/tests/test.rb rename to lxc/tests/ruby.rb diff --git a/lxc/tests/test.rs b/lxc/tests/rust.rs similarity index 100% rename from lxc/tests/test.rs rename to lxc/tests/rust.rs diff --git a/lxc/tests/test.swift b/lxc/tests/swift.swift similarity index 100% rename from lxc/tests/test.swift rename to lxc/tests/swift.swift diff --git a/lxc/tests/test.jelly b/lxc/tests/test.jelly deleted file mode 100644 index e688ff7..0000000 --- a/lxc/tests/test.jelly +++ /dev/null @@ -1 +0,0 @@ -“3ḅaė;œ» diff --git a/lxc/tests/test.ts b/lxc/tests/typescript.ts similarity index 100% rename from lxc/tests/test.ts rename to lxc/tests/typescript.ts From 32452894c596fc016b9d8aa37f281ad52aa379c8 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 22 Jan 2021 02:45:52 -0600 Subject: [PATCH 70/73] update readme and test output --- lxc/test_all_lxc | 52 +++++++++++++++++----------------- readme.md | 45 ++++++++++++++++++----------- var/{archive.txt => notes.txt} | 0 3 files changed, 54 insertions(+), 43 deletions(-) rename var/{archive.txt => notes.txt} (100%) diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 473e888..ba64572 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -1,55 +1,55 @@ #!/usr/bin/env bash cd tests -echo 'testing awk' +echo -n 'testing awk = ' ../../cli/execute awk awk.awk -echo 'testing bash' +echo -n 'testing bash = ' ../../cli/execute bash bash.sh -echo 'testing c' +echo -n 'testing c = ' ../../cli/execute c c.c -echo 'testing cpp' +echo -n 'testing cpp = ' ../../cli/execute cpp cpp.cpp -echo 'testing csharp' +echo -n 'testing csharp = ' ../../cli/execute csharp csharp.cs -echo 'testing deno' +echo -n 'testing deno = ' ../../cli/execute deno deno.ts -echo 'testing elixir' +echo -n 'testing elixir = ' ../../cli/execute elixir elixir.exs -echo 'testing emacs' +echo -n 'testing emacs = ' ../../cli/execute emacs emacs.el -echo 'testing go' +echo -n 'testing go = ' ../../cli/execute go go.go -echo 'testing haskell' +echo -n 'testing haskell = ' ../../cli/execute haskell haskell.hs -echo 'testing java' +echo -n 'testing java = ' ../../cli/execute java java.java -echo 'testing jelly' +echo -n 'testing jelly = ' ../../cli/execute jelly jelly.jelly good -echo 'testing julia' +echo -n 'testing julia = ' ../../cli/execute julia julia.jl -echo 'testing kotlin' +echo -n 'testing kotlin = ' ../../cli/execute kotlin kotlin.kt -echo 'testing nasm 32 bit' +echo -n 'testing nasm 32 bit = ' ../../cli/execute nasm nasm.nasm -echo 'testing nasm 64 bit' +echo -n 'testing nasm 64 bit = ' ../../cli/execute nasm64 nasm64.nasm -echo 'testing node' +echo -n 'testing node = ' ../../cli/execute node node.js -echo 'testing paradoc' +echo -n 'testing paradoc = ' ../../cli/execute bash paradoc.sh -echo 'testing perl' +echo -n 'testing perl = ' ../../cli/execute perl perl.pl -echo 'testing php' +echo -n 'testing php = ' ../../cli/execute php php.php -echo 'testing python2' +echo -n 'testing python2 = ' ../../cli/execute python2 python2.py -echo 'testing python3' +echo -n 'testing python3 = ' ../../cli/execute python3 python3.py -echo 'testing ruby' +echo -n 'testing ruby = ' ../../cli/execute ruby ruby.rb -echo 'testing rust' +echo -n 'testing rust = ' ../../cli/execute rust rust.rs -echo 'testing swift' +echo -n 'testing swift = ' ../../cli/execute swift swift.swift -echo 'testing typescript' +echo -n 'testing typescript = ' ../../cli/execute typescript typescript.ts diff --git a/readme.md b/readme.md index 20b7ae0..83b132a 100644 --- a/readme.md +++ b/readme.md @@ -248,23 +248,34 @@ Content-Type: application/json
# Supported Languages -| | | -|:---------:|------------| -| awk | julia | -| bash | kotlin | -| brainfuck | lua | -| c | nasm | -| cpp | node | -| csharp | paradoc | -| deno | perl | -| erlang | php | -| elixir | python2 | -| emacs | python3 | -| elisp | ruby | -| go | rust | -| haskell | swift | -| java | typescript | -| jelly | | +`awk`, +`bash`, +`brainfuck`, +`c`, +`cpp`, +`csharp`, +`deno`, +`elixir`, +`emacs`, +`elisp`, +`go`, +`haskell`, +`java`, +`jelly`, +`julia`, +`kotlin`, +`lua`, +`nasm`, +`node`, +`paradoc`, +`perl`, +`php`, +`python2`, +`python3`, +`ruby`, +`rust`, +`swift`, +`typescript`,
diff --git a/var/archive.txt b/var/notes.txt similarity index 100% rename from var/archive.txt rename to var/notes.txt From 014ddb3559a8e4b9f050509d760d7b17bf6cec02 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 22 Jan 2021 02:48:39 -0600 Subject: [PATCH 71/73] fix nasm test --- lxc/tests/nasm64.nasm | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lxc/tests/nasm64.nasm b/lxc/tests/nasm64.nasm index 191b8d3..fbc5aef 100644 --- a/lxc/tests/nasm64.nasm +++ b/lxc/tests/nasm64.nasm @@ -1,18 +1,18 @@ SECTION .data - good: db "good", 0x0a, 0x0 - txtlen: equ $ - good + good: db "good", 0x0 + txtlen: equ $ - good SECTION .text GLOBAL _start _start: - ;sys_write - mov rax, 1 - mov rdi, 1 - mov rsi, good - mov rdx, txtlen - syscall - ;sys_exit - mov rax, 60 - mov rdi, 0 - syscall + ;sys_write + mov rax, 1 + mov rdi, 1 + mov rsi, good + mov rdx, txtlen + syscall + ;sys_exit + mov rax, 60 + mov rdi, 0 + syscall From 563cf19068183f056d9e6ee6009935894bf263c0 Mon Sep 17 00:00:00 2001 From: Brian Seymour Date: Fri, 22 Jan 2021 02:58:45 -0600 Subject: [PATCH 72/73] update readme --- readme.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/readme.md b/readme.md index 83b132a..5e7322a 100644 --- a/readme.md +++ b/readme.md @@ -169,7 +169,7 @@ cd api ./start ``` -For your own local installation, the API is available at +For your own local installation, the API is available at: ``` http://127.0.0.1:2000 @@ -177,9 +177,9 @@ http://127.0.0.1:2000 #### Versions Endpoint `GET /versions` -This endpoint takes no input and returns a JSON array of the currently installed languages. - -Truncated response sample: +This endpoint will return the supported languages along with the current version and aliases. To execute +code for a particular language using the `/execute` endpoint, either the name or one of the aliases must +be provided. ```json HTTP/1.1 200 OK Content-Type: application/json @@ -205,13 +205,16 @@ Content-Type: application/json #### Execute Endpoint `POST /execute` -This endpoint takes the following JSON payload and expects at least the language and source. If -source is not provided, a blank file is passed as the source. If no `args` are desired, it can either -be an empty array or left out entirely. +This endpoint requests execution of some arbitrary code. +- `language` (**required**) The language to use for execution, must be a string and supported by Piston (see list below). +- `source` (**required**) The source code to execute, must be a string. +- `stdin` (*optional*) The text to pass as stdin to the program. Must be a string or left out of the request. +- `args` (*optional*) The arguments to pass to the program. Must be an array or left out of the request. ```json { "language": "js", "source": "console.log(process.argv)", + "stdin": "", "args": [ "1", "2", @@ -235,13 +238,13 @@ Content-Type: application/json "stderr": "" } ``` -If an invalid language is supplied, a typical response will look like the following: +If a problem exists with the request, a `400` status code is returned and the reason in the `message` key. ```json HTTP/1.1 400 Bad Request Content-Type: application/json { - "message": "Provided language is not supported by Piston" + "message": "Supplied language is not supported by Piston" } ``` From b64598763d82a935104aa74b8d1ba8575671a09a Mon Sep 17 00:00:00 2001 From: Vrganj Date: Sat, 23 Jan 2021 20:10:10 +0100 Subject: [PATCH 73/73] Stop appending to output if longer than limit --- shared/execute.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/shared/execute.js b/shared/execute.js index 6547ca8..526efdd 100644 --- a/shared/execute.js +++ b/shared/execute.js @@ -1,6 +1,8 @@ const { writeFileSync, unlinkSync } = require('fs'); const { spawn } = require('child_process'); +const OUTPUT_LIMIT = 65535; + function execute(language, source, stdin = '', args = []) { return new Promise(resolve => { const stamp = new Date().getTime(); @@ -20,11 +22,15 @@ function execute(language, source, stdin = '', args = []) { let output = ''; process.stderr.on('data', chunk => { + if (stderr.length >= OUTPUT_LIMIT) return; + stderr += chunk; output += chunk; }); process.stdout.on('data', chunk => { + if (stdout.length >= OUTPUT_LIMIT) return; + stdout += chunk; output += chunk; }); @@ -32,9 +38,9 @@ function execute(language, source, stdin = '', args = []) { process.on('exit', code => { unlinkSync(sourceFile); - stderr = stderr.trim().substring(0, 65535); - stdout = stdout.trim().substring(0, 65535); - output = output.trim().substring(0, 65535); + stderr = stderr.trim().substring(0, OUTPUT_LIMIT); + stdout = stdout.trim().substring(0, OUTPUT_LIMIT); + output = output.trim().substring(0, OUTPUT_LIMIT); resolve({ stdout,