From 30e3c6abe542c6a9f5955e1d65896a0c3bab534f Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 16 Dec 2017 01:22:40 +0000 Subject: avoid reusing env on hijack Hijackers may capture and reuse `env' indefinitely, so we must not use it in those cases for future requests. For non-hijack requests, we continue to reuse the `env' object to reduce memory recycling. Reported-and-tested-by: Sam Saffron --- t/hijack.ru | 12 ++++++++++++ t/t0200-rack-hijack.sh | 23 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 't') diff --git a/t/hijack.ru b/t/hijack.ru index 4adec61..02260e2 100644 --- a/t/hijack.ru +++ b/t/hijack.ru @@ -11,11 +11,15 @@ class DieIfUsed warn "closed DieIfUsed #{@@n += 1}\n" end end + +envs = [] + run lambda { |env| case env["PATH_INFO"] when "/hijack_req" if env["rack.hijack?"] io = env["rack.hijack"].call + envs << env if io.respond_to?(:read_nonblock) && env["rack.hijack_io"].respond_to?(:read_nonblock) @@ -33,11 +37,19 @@ run lambda { |env| { "Content-Length" => r.bytesize.to_s, "rack.hijack" => proc do |io| + envs << env io.write(r) io.close end }, DieIfUsed.new ] + when "/normal_env_id" + b = "#{env.object_id}\n" + h = { + 'Content-Type' => 'text/plain', + 'Content-Length' => b.bytesize.to_s, + } + [ 200, h, [ b ] ] end } diff --git a/t/t0200-rack-hijack.sh b/t/t0200-rack-hijack.sh index de3eb82..fee0791 100755 --- a/t/t0200-rack-hijack.sh +++ b/t/t0200-rack-hijack.sh @@ -1,6 +1,6 @@ #!/bin/sh . ./test-lib.sh -t_plan 5 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [ 1,2]))" +t_plan 9 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [ 1,2]))" t_begin "setup and start" && { unicorn_setup @@ -8,14 +8,35 @@ t_begin "setup and start" && { unicorn_wait_start } +t_begin "normal env reused between requests" && { + env_a="$(curl -sSf http://$listen/normal_env_id)" + b="$(curl -sSf http://$listen/normal_env_id)" + test x"$env_a" = x"$b" +} + t_begin "check request hijack" && { test "xrequest.hijacked" = x"$(curl -sSfv http://$listen/hijack_req)" } +t_begin "env changed after request hijack" && { + env_b="$(curl -sSf http://$listen/normal_env_id)" + test x"$env_a" != x"$env_b" +} + t_begin "check response hijack" && { test "xresponse.hijacked" = x"$(curl -sSfv http://$listen/hijack_res)" } +t_begin "env changed after response hijack" && { + env_c="$(curl -sSf http://$listen/normal_env_id)" + test x"$env_b" != x"$env_c" +} + +t_begin "env continues to be reused between requests" && { + b="$(curl -sSf http://$listen/normal_env_id)" + test x"$env_c" = x"$b" +} + t_begin "killing succeeds after hijack" && { kill $unicorn_pid } -- cgit v1.2.3-24-ge0c7