Skip to content

Commit

Permalink
Sanitize circular dependencies with a string representation.
Browse files Browse the repository at this point in the history
Circular dependencies and JSON serialization don't play well together.
Depending on the library it might throw a SystemStackTooDeep or even segfault
the interpreter.

Here we replace the circular depency with a "[...]" or "{...}" string
representation that should make it clear later on what happened.
  • Loading branch information
Jonas Pfenniger committed Jul 9, 2013
1 parent 299f326 commit 7350b7d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 6 deletions.
18 changes: 12 additions & 6 deletions lib/raven/processors/sanitizedata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ class SanitizeData < Processor
FIELDS_RE = /(authorization|password|passwd|secret)/i
VALUES_RE = /^\d{16}$/

def apply(value, key=nil, &block)
def apply(value, key=nil, visited, &block)
if value.is_a?(Hash)
return "{...}" if visited.include?(value.__id__)
visited += [value.__id__]

value.each.inject({}) do |memo, (k, v)|
memo[k] = apply(v, k, &block)
memo[k] = apply(v, k, visited, &block)
memo
end
elsif value.is_a?(Array)
value.map do |value|
apply(value, key, &block)
return "[...]" if visited.include?(value.__id__)
visited += [value.__id__]

value.map do |value_|
apply(value_, key, visited, &block)
end
else
block.call(key, value)
Expand All @@ -34,10 +40,10 @@ def sanitize(key, value)
end

def process(data)
apply(data) do |key, value|
apply(data, nil, []) do |key, value|
sanitize(key, value)
end
end
end
end
end
end
13 changes: 13 additions & 0 deletions spec/raven/sanitizedata_processor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,17 @@
result["ccnumba"].should eq(Raven::Processor::SanitizeData::MASK)
end

it 'should cleanup circular dependendencies' do
data = {}
data['data'] = data
data['ary'] = []
data['ary'].push('x' => data['ary'])
data['ary2'] = data['ary']

result = @processor.process(data)
result['data'].should eq('{...}')
result['ary'].first['x'].should eq('[...]')
result['ary2'].should_not eq('[...]')
end

end

0 comments on commit 7350b7d

Please sign in to comment.