syntect: bug/panic caused by Vue.js syntax definition

When trying to highlight Vue.js files using the same syntax file that works well in Sublime, Syntect panics:

thread '<unnamed>' panicked at 'begin <= end (13 <= 7) when slicing `<style lang="stylus" scoped>`', libcore/str/mod.rs:2098:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:511
   5: std::panicking::continue_panic_fmt
             at libstd/panicking.rs:426
   6: rust_begin_unwind
             at libstd/panicking.rs:337
   7: core::panicking::panic_fmt
             at libcore/panicking.rs:92
   8: core::str::slice_error_fail
             at libcore/str/mod.rs:0
   9: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::Range<usize>>::index::{{closure}}
  10: <syntect::highlighting::highlighter::HighlightIterator<'a, 'b> as core::iter::iterator::Iterator>::next
  11: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::from_iter
  12: syntect::html::highlighted_snippet_for_string
  13: <std::thread::local::LocalKey<
T>>::with
  14: syntect_server::rocket_route_fn_index
  15: rocket::rocket::Rocket::dispatch
  16: <rocket::rocket::Rocket as hyper::server::Handler>::handle
  17: <hyper::server::Worker<H>>::handle_connection
  18: hyper::server::listener::spawn_with::{{closure}}

(only the bits above syntect::html::highlighted_snippet_for_string are relevant)

I believe the above is pointing to https://github.com/trishume/syntect/blob/231eafce087beac80064b902c9eadefb1d078c1f/src/highlighting/highlighter.rs#L119 as the culprit, but I haven’t investigated what would cause this.

The syntax file I am using is here: vue.sublime-syntax (tmLanguage file here)

This file produces the panic (but highlights fine in ST3 with the same syntax file): https://raw.githubusercontent.com/vuejs/vue-cli/0ba111eed859aad02156e807ef71d0052b2e7f17/packages/%40vue/cli-ui-addon-webpack/src/components/ModuleListItem.vue

This file highlights fine in both Syntect and ST3 with the same syntax file: https://raw.githubusercontent.com/vuejs/vue-cli/0ba111eed859aad02156e807ef71d0052b2e7f17/packages/%40vue/cli-ui-addon-webpack/src/components/ModuleList.vue

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 20 (8 by maintainers)

Commits related to this issue

Most upvoted comments

I managed to create this minimal (?) example that triggers the same error:

Consider this Sublime Syntax:

%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Dummy
file_extensions:
  - dummy
scope: source.dummy
contexts:
  main:
    - match: (?=(foo))
      captures:
        1: keyword
      push:
        - match: (foo)
          captures:
            1: keyword

and the following test.dummy file:

foo

This will cause syntect to panic with:

thread 'main' panicked at 'begin <= end (3 <= 0) when slicing `foo

This is the content of HighlightIterators changes field:

[(0, Push(<source.dummy>)), (0, Push(<keyword>)), (3, Pop(1)), (0, Push(<keyword>)), (3, Pop(1))]

I don’t understand enough about the internals of syntect and sublime syntax definitions, but I believe this is somehow related to the negative lookahead in the (?=(foo)) regex. For some reason, this causes syntect to create the additional (0, Push(<keyword>)) entry.

If someone can give a hint / point me in the right direction, I can try to look into this.

A similar (the same?) bug was reported here for OCaml files. This can be reproduced with syncat and the current master of syntect:

test.ml

let line_count filename =
   let f = open_in filename in
   let rec loop count =
     match try Some (input_line f) with End_of_file -> None
     with
       | Some(_) -> loop (count+1)
       | None -> count in
   loop 0

or minimal.ml:

with a -> b

The stack trace is the same as above:

▶ RUST_BACKTRACE=1 cargo run --example syncat --  /home/shark/Dropbox/Informatik/rust/bat-test/errors/test.ml
let line_count filename =
   let f = open_in filename in
   let rec loop count =
thread 'main' panicked at 'begin <= end (54 <= 40) when slicing `     match try Some (input_line f) with End_of_file -> None
`', libcore/str/mod.rs:2095:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:475
   5: std::panicking::continue_panic_fmt
             at libstd/panicking.rs:390
   6: rust_begin_unwind
             at libstd/panicking.rs:325
   7: core::panicking::panic_fmt
             at libcore/panicking.rs:77
   8: core::str::slice_error_fail
             at libcore/str/mod.rs:0
   9: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::Range<usize>>::index::{{closure}}
             at /checkout/src/libcore/str/mod.rs:1891
  10: <core::option::Option<T>>::unwrap_or_else
             at /checkout/src/libcore/option.rs:386
  11: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::Range<usize>>::index
             at /checkout/src/libcore/str/mod.rs:1891
  12: core::str::traits::<impl core::ops::index::Index<core::ops::range::Range<usize>> for str>::index
             at /checkout/src/libcore/str/mod.rs:1667
  13: <syntect::highlighting::highlighter::HighlightIterator<'a, 'b> as core::iter::iterator::Iterator>::next
             at src/highlighting/highlighter.rs:123
  14: <alloc::vec::Vec<T>>::extend_desugared
             at /checkout/src/liballoc/vec.rs:1969
  15: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::spec_extend
             at /checkout/src/liballoc/vec.rs:1866
  16: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::from_iter
             at /checkout/src/liballoc/vec.rs:1861
  17: <alloc::vec::Vec<T> as core::iter::traits::FromIterator<T>>::from_iter
             at /checkout/src/liballoc/vec.rs:1761
  18: core::iter::iterator::Iterator::collect
             at /checkout/src/libcore/iter/iterator.rs:1415
  19: syntect::easy::HighlightLines::highlight
             at src/easy.rs:65
  20: syncat::main
             at examples/syncat.rs:112
  21: std::rt::lang_start::{{closure}}
             at /checkout/src/libstd/rt.rs:74
  22: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:310
  23: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:105
  24: std::rt::lang_start_internal
             at libstd/panicking.rs:289
             at libstd/panic.rs:392
             at libstd/rt.rs:58
  25: std::rt::lang_start
             at /checkout/src/libstd/rt.rs:74
  26: main
  27: __libc_start_main
  28: _start