Skip to content
Snippets Groups Projects

workaround for buggy lexers

Merged username-removed-25949 requested to merge haynes/gitlab-ce:lexer_error_workaround into master

It seems that some lexers can be buggy when used together with git blame.
This results in a 500 error when a user tries to open the blame page in some cases.
The workaround is pretty simple. Not only fall back to plaintext when the file content can't be guessed, but also when the lexer fails.

This closes #1521 (closed) and #1646 (closed)

/cc @DouweM @JobV It would be awesome to have this in a patch release for 7.11 or even in the release. But that's probably to late.

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
9 9
10 10 begin
11 11 lexer = Rugments::Lexer.guess(filename: blob_name, source: blob_content)
12 rescue Rugments::Lexer::AmbiguousGuess
12 result = formatter.format(lexer.lex(blob_content)).html_safe
13 rescue
  • I think it's bad practice to rescue from everything. What was wrong with the previous rescue argument?

  • The previous rescue arugment only took into account when Rugments couldn't guess a file.
    But lexer.lex can fail as well even with the correct syntax highlighting detected.
    This would result in errors like this for example:

    RuntimeError - empty stack!:
      rugments (1.0.0.beta6) lib/rugments/regex_lexer.rb:227:in `state'
      rugments (1.0.0.beta6) lib/rugments/regex_lexer.rb:268:in `stream_tokens'
      rugments (1.0.0.beta6) lib/rugments/lexer.rb:376:in `lex'
      rugments (1.0.0.beta6) lib/rugments/formatters/html.rb:72:in `process_tokens'
      rugments (1.0.0.beta6) lib/rugments/formatters/html.rb:42:in `format_untableized'
      rugments (1.0.0.beta6) lib/rugments/formatters/html.rb:35:in `format'
      app/helpers/blob_helper.rb:16:in `highlight'
      app/views/projects/blame/show.html.haml:39:in `block (2 levels) in _app_views_projects_blame_show_html_haml__4561567618660177775_70233404832100'
      app/views/projects/blame/show.html.haml:38:in `block in _app_views_projects_blame_show_html_haml__4561567618660177775_70233404832100'
      gitlab_git (7.1.2) lib/gitlab_git/blame.rb:20:in `block in each'
      gitlab_git (7.1.2) lib/gitlab_git/blame.rb:14:in `each'
      app/views/projects/blame/show.html.haml:14:in `_app_views_projects_blame_show_html_haml__4561567618660177775_70233404832100'
      actionview (4.1.9) lib/action_view/template.rb:145:in `block in render'
      activesupport (4.1.9) lib/active_support/notifications.rb:161:in `instrument'
      actionview (4.1.9) lib/action_view/template.rb:339:in `instrument'
      actionview (4.1.9) lib/action_view/template.rb:143:in `render'
      rack-mini-profiler (0.9.0) lib/mini_profiler/profiling_methods.rb:108:in `block in profile_method'
      actionview (4.1.9) lib/action_view/renderer/template_renderer.rb:55:in `block (2 levels) in render_template'
      actionview (4.1.9) lib/action_view/renderer/abstract_renderer.rb:38:in `block in instrument'
      activesupport (4.1.9) lib/active_support/notifications.rb:159:in `block in instrument'
      activesupport (4.1.9) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
      activesupport (4.1.9) lib/active_support/notifications.rb:159:in `instrument'
      actionview (4.1.9) lib/action_view/renderer/abstract_renderer.rb:38:in `instrument'
      actionview (4.1.9) lib/action_view/renderer/template_renderer.rb:54:in `block in render_template'
      actionview (4.1.9) lib/action_view/renderer/template_renderer.rb:62:in `render_with_layout'
      actionview (4.1.9) lib/action_view/renderer/template_renderer.rb:53:in `render_template'
      actionview (4.1.9) lib/action_view/renderer/template_renderer.rb:17:in `render'
      actionview (4.1.9) lib/action_view/renderer/renderer.rb:42:in `render_template'
      actionview (4.1.9) lib/action_view/renderer/renderer.rb:23:in `render'
      actionview (4.1.9) lib/action_view/rendering.rb:99:in `_render_template'
      actionpack (4.1.9) lib/action_controller/metal/streaming.rb:217:in `_render_template'
      actionview (4.1.9) lib/action_view/rendering.rb:82:in `render_to_body'
      actionpack (4.1.9) lib/action_controller/metal/rendering.rb:32:in `render_to_body'
      actionpack (4.1.9) lib/action_controller/metal/renderers.rb:32:in `render_to_body'
      actionpack (4.1.9) lib/abstract_controller/rendering.rb:25:in `render'
      actionpack (4.1.9) lib/action_controller/metal/rendering.rb:16:in `render'
      actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:41:in `block (2 levels) in render'
      activesupport (4.1.9) lib/active_support/core_ext/benchmark.rb:12:in `block in ms'
      /home/hannes/.rubies/ruby-2.1.5/lib/ruby/2.1.0/benchmark.rb:294:in `realtime'
      activesupport (4.1.9) lib/active_support/core_ext/benchmark.rb:12:in `ms'
      actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:41:in `block in render'
      actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:84:in `cleanup_view_runtime'
      activerecord (4.1.9) lib/active_record/railties/controller_runtime.rb:25:in `cleanup_view_runtime'
      actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:40:in `render'
      actionpack (4.1.9) lib/action_controller/metal/implicit_render.rb:10:in `default_render'
      actionpack (4.1.9) lib/action_controller/metal/implicit_render.rb:5:in `send_action'
      actionpack (4.1.9) lib/abstract_controller/base.rb:189:in `process_action'
      actionpack (4.1.9) lib/action_controller/metal/rendering.rb:10:in `process_action'
      actionpack (4.1.9) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
      activesupport (4.1.9) lib/active_support/callbacks.rb:113:in `call'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:229:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
      activesupport (4.1.9) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:229:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting'
      activesupport (4.1.9) lib/active_support/callbacks.rb:86:in `run_callbacks'
      actionpack (4.1.9) lib/abstract_controller/callbacks.rb:19:in `process_action'
      actionpack (4.1.9) lib/action_controller/metal/rescue.rb:29:in `process_action'
      actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
      activesupport (4.1.9) lib/active_support/notifications.rb:159:in `block in instrument'
      activesupport (4.1.9) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
      activesupport (4.1.9) lib/active_support/notifications.rb:159:in `instrument'
      actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
      actionpack (4.1.9) lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
      activerecord (4.1.9) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
      actionpack (4.1.9) lib/abstract_controller/base.rb:136:in `process'
      actionview (4.1.9) lib/action_view/rendering.rb:30:in `process'
      rack-mini-profiler (0.9.0) lib/mini_profiler/profiling_methods.rb:108:in `block in profile_method'
      actionpack (4.1.9) lib/action_controller/metal.rb:196:in `dispatch'
      actionpack (4.1.9) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
      actionpack (4.1.9) lib/action_controller/metal.rb:232:in `block in action'
      actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:82:in `dispatch'
      actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:50:in `call'
      actionpack (4.1.9) lib/action_dispatch/journey/router.rb:73:in `block in call'
      actionpack (4.1.9) lib/action_dispatch/journey/router.rb:59:in `call'
      actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:685:in `call'
      request_store (1.0.5) lib/request_store/middleware.rb:9:in `call'
      rack-cors (0.2.9) lib/rack/cors.rb:54:in `call'
      rack-attack (4.2.0) lib/rack/attack.rb:104:in `call'
      warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
      warden (1.2.3) lib/warden/manager.rb:34:in `call'
      rack (1.5.2) lib/rack/etag.rb:23:in `call'
      rack (1.5.2) lib/rack/conditionalget.rb:25:in `call'
      rack (1.5.2) lib/rack/head.rb:11:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/flash.rb:254:in `call'
      rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
      rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/cookies.rb:562:in `call'
      activerecord (4.1.9) lib/active_record/query_cache.rb:36:in `call'
      activerecord (4.1.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
      activesupport (4.1.9) lib/active_support/callbacks.rb:82:in `run_callbacks'
      actionpack (4.1.9) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/reloader.rb:73:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
      better_errors (1.0.1) lib/better_errors/middleware.rb:84:in `protected_app_call'
      better_errors (1.0.1) lib/better_errors/middleware.rb:79:in `better_errors_call'
      better_errors (1.0.1) lib/better_errors/middleware.rb:56:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
      railties (4.1.9) lib/rails/rack/logger.rb:38:in `call_app'
      railties (4.1.9) lib/rails/rack/logger.rb:20:in `block in call'
      activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `block in tagged'
      activesupport (4.1.9) lib/active_support/tagged_logging.rb:26:in `tagged'
      activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `tagged'
      railties (4.1.9) lib/rails/rack/logger.rb:20:in `call'
      quiet_assets (1.0.2) lib/quiet_assets.rb:18:in `call_with_quiet_assets'
      actionpack (4.1.9) lib/action_dispatch/middleware/request_id.rb:21:in `call'
      rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
      rack (1.5.2) lib/rack/runtime.rb:17:in `call'
      rack (1.5.2) lib/rack/lock.rb:17:in `call'
      actionpack (4.1.9) lib/action_dispatch/middleware/static.rb:84:in `call'
      lib/gitlab/middleware/static.rb:9:in `call'
      rack (1.5.2) lib/rack/sendfile.rb:112:in `call'
      rack-mini-profiler (0.9.0) lib/mini_profiler/profiler.rb:298:in `call'
      railties (4.1.9) lib/rails/engine.rb:514:in `call'
      railties (4.1.9) lib/rails/application.rb:144:in `call'
      railties (4.1.9) lib/rails/railtie.rb:194:in `method_missing'
      rack (1.5.2) lib/rack/builder.rb:138:in `call'
      rack (1.5.2) lib/rack/urlmap.rb:65:in `block in call'
      rack (1.5.2) lib/rack/urlmap.rb:50:in `call'
      unicorn (4.6.3) lib/unicorn/http_server.rb:552:in `process_client'
      unicorn-worker-killer (0.4.2) lib/unicorn/worker_killer.rb:51:in `process_client'
      unicorn (4.6.3) lib/unicorn/http_server.rb:632:in `worker_loop'
      unicorn (4.6.3) lib/unicorn/http_server.rb:500:in `spawn_missing_workers'
      unicorn (4.6.3) lib/unicorn/http_server.rb:511:in `maintain_worker_count'
      unicorn (4.6.3) lib/unicorn/http_server.rb:277:in `join'
      unicorn (4.6.3) bin/unicorn_rails:209:in `<top (required)>'
       () home/hannes/.gem/ruby/2.1.5/bin/unicorn_rails:23:in `<main>'

    I don't know in what other ways the lexer can fail, so I decided to rescue from everything here and fall back to the plaintext lexer if there is an error.
    It's a workaround until we can properly fix how we handle lexers.
    In the meantime this at least prevents 500 errors.

    See the two linked bugs linked in the MR for more infos.

Please register or sign in to reply
Loading