From 9f153b33e6f0e44d73535d297f61f4db96a8436c Mon Sep 17 00:00:00 2001 From: Jon Yurek Date: Wed, 16 Mar 2011 16:46:41 -0400 Subject: [PATCH] Prevent recursive data structures --- lib/hoptoad_notifier/notice.rb | 8 +++++--- test/recursion_test.rb | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 test/recursion_test.rb diff --git a/lib/hoptoad_notifier/notice.rb b/lib/hoptoad_notifier/notice.rb index 5c571d7..e4e3de7 100644 --- a/lib/hoptoad_notifier/notice.rb +++ b/lib/hoptoad_notifier/notice.rb @@ -226,14 +226,16 @@ def clean_unserializable_data_from(attribute) # Removes non-serializable data. Allowed data types are strings, arrays, # and hashes. All other types are converted to strings. # TODO: move this onto Hash - def clean_unserializable_data(data) + def clean_unserializable_data(data, stack = []) + return "[possible infinite recursion halted]" if stack.any?{|item| item == data.object_id } + if data.respond_to?(:to_hash) data.to_hash.inject({}) do |result, (key, value)| - result.merge(key => clean_unserializable_data(value)) + result.merge(key => clean_unserializable_data(value, stack + [data.object_id])) end elsif data.respond_to?(:to_ary) data.collect do |value| - clean_unserializable_data(value) + clean_unserializable_data(value, stack + [data.object_id]) end else data.to_s diff --git a/test/recursion_test.rb b/test/recursion_test.rb new file mode 100644 index 0000000..c39d8be --- /dev/null +++ b/test/recursion_test.rb @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '/helper' + +class RecursionTest < Test::Unit::TestCase + should "not allow infinite recursion" do + hash = {:a => :a} + hash[:hash] = hash + notice = HoptoadNotifier::Notice.new(:parameters => hash) + assert_equal "[possible infinite recursion halted]", notice.parameters[:hash] + end +end