Commit 3bfc08be authored by Mark Chao's avatar Mark Chao

Fix syntax highlight taking too long

Use Timeout to switch to plain rendering
parent ba99dfcd
---
title: Set timeout for syntax highlighting
merge_request:
author:
type: security
module Gitlab module Gitlab
class Highlight class Highlight
TIMEOUT_BACKGROUND = 30.seconds
TIMEOUT_FOREGROUND = 3.seconds
def self.highlight(blob_name, blob_content, repository: nil, plain: false) def self.highlight(blob_name, blob_content, repository: nil, plain: false)
new(blob_name, blob_content, repository: repository) new(blob_name, blob_content, repository: repository)
.highlight(blob_content, continue: false, plain: plain) .highlight(blob_content, continue: false, plain: plain)
...@@ -51,11 +54,20 @@ module Gitlab ...@@ -51,11 +54,20 @@ module Gitlab
end end
def highlight_rich(text, continue: true) def highlight_rich(text, continue: true)
@formatter.format(lexer.lex(text, continue: continue), tag: lexer.tag).html_safe tag = lexer.tag
tokens = lexer.lex(text, continue: continue)
Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag).html_safe }
rescue Timeout::Error => e
Gitlab::Sentry.track_exception(e)
highlight_plain(text)
rescue rescue
highlight_plain(text) highlight_plain(text)
end end
def timeout_time
Sidekiq.server? ? TIMEOUT_BACKGROUND : TIMEOUT_FOREGROUND
end
def link_dependencies(text, highlighted_text) def link_dependencies(text, highlighted_text)
Gitlab::DependencyLinker.link(blob_name, text, highlighted_text) Gitlab::DependencyLinker.link(blob_name, text, highlighted_text)
end end
......
...@@ -56,5 +56,22 @@ describe Gitlab::Highlight do ...@@ -56,5 +56,22 @@ describe Gitlab::Highlight do
described_class.highlight('file.name', 'Contents') described_class.highlight('file.name', 'Contents')
end end
context 'timeout' do
subject { described_class.new('file.name', 'Contents') }
it 'utilizes timeout for web' do
expect(Timeout).to receive(:timeout).with(described_class::TIMEOUT_FOREGROUND).and_call_original
subject.highlight("Content")
end
it 'utilizes longer timeout for sidekiq' do
allow(Sidekiq).to receive(:server?).and_return(true)
expect(Timeout).to receive(:timeout).with(described_class::TIMEOUT_BACKGROUND).and_call_original
subject.highlight("Content")
end
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment