From 1556548ff6633cbfac8f463a82628f45afb24856 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 4 Feb 2014 11:12:53 +1100 Subject: [PATCH] BUGFIX: JS errors could crash our process --- lib/pretty_text.rb | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index 54c3e16027f..e430931f5a2 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -125,7 +125,7 @@ module PrettyText baked = nil - @mutex.synchronize do + protect do context = v8 # we need to do this to work in a multi site environment, many sites, many settings decorate_context(context) @@ -152,14 +152,12 @@ module PrettyText # leaving this here, cause it invokes v8, don't want to implement twice def self.avatar_img(avatar_template, size) - r = nil - @mutex.synchronize do + protect do v8['avatarTemplate'] = avatar_template v8['size'] = size decorate_context(v8) - r = v8.eval("Discourse.Utilities.avatarImg({ avatarTemplate: avatarTemplate, size: size });") + v8.eval("Discourse.Utilities.avatarImg({ avatarTemplate: avatarTemplate, size: size });") end - r end def self.cook(text, opts={}) @@ -253,6 +251,32 @@ module PrettyText protected + class JavaScriptError < StandardError + attr_accessor :message, :backtrace + + def initialize(message, backtrace) + @message = message + @backtrace = backtrace + end + + end + + def self.protect + rval = nil + @mutex.synchronize do + begin + rval = yield + # This may seem a bit odd, but we don't want to leak out + # objects that require locks on the v8 vm, to get a backtrace + # you need a lock, if this happens in the wrong spot you can + # deadlock a process + rescue V8::Error => e + raise JavaScriptError.new(e.message, e.backtrace) + end + end + rval + end + def self.ctx_load(ctx, *files) files.each do |file| ctx.load(app_root + file)