Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote branch 'agworld/stable' into stable

  • Loading branch information...
commit 637ed00766e793233f9e08004289c2ee81f8b5ef 2 parents dcf37c8 + 24bb4e3
@nex3 nex3 authored
View
2  doc-src/SASS_CHANGELOG.md
@@ -25,6 +25,8 @@
been successfully compiled. Thanks to [Christian Peters](https://github.com/ChristianPeters).
* Allow absolute paths to be used in an importer with a different root.
* Don't destructively modify the options when running `Sass::Plugin.force_update`.
+* Prevent Regexp buffer overflows when parsing long strings.
+ Thanks to [Agworld](https://github.com/Agworld).
### Deprecations -- Must Read!
View
20 lib/sass/scss/parser.rb
@@ -437,7 +437,7 @@ def declaration_or_ruleset
end
def selector_sequence
- if sel = tok(STATIC_SELECTOR)
+ if sel = tok(STATIC_SELECTOR, true)
return [sel]
end
@@ -681,7 +681,7 @@ def value!
# we don't parse it at all, and instead return a plain old string
# containing the value.
# This results in a dramatic speed increase.
- if val = tok(STATIC_VALUE)
+ if val = tok(STATIC_VALUE, true)
return space, Sass::Script::String.new(val.strip)
end
return space, sass_script(:parse)
@@ -770,7 +770,7 @@ def _interp_string(type)
end
def interp_ident(start = IDENT)
- return unless val = tok(start) || interpolation || tok(IDENT_HYPHEN_INTERP)
+ return unless val = tok(start) || interpolation || tok(IDENT_HYPHEN_INTERP, true)
res = [val]
while val = tok(NAME) || interpolation
res << val
@@ -944,9 +944,21 @@ def self.prior_snippet(scanner)
# This is important because `#tok` is called all the time.
NEWLINE = "\n"
- def tok(rx)
+ def tok(rx, last_group_lookahead = false)
res = @scanner.scan(rx)
if res
+ # This fixes https://github.com/nex3/sass/issues/104, which affects
+ # Ruby 1.8.7 and REE. This fix is to replace the ?= zero-width
+ # positive lookahead operator in the Regexp (which matches without
+ # consuming the matched group), with a match that does consume the
+ # group, but then rewinds the scanner and removes the group from the
+ # end of the matched string. This fix makes the assumption that the
+ # matched group will always occur at the end of the match; this
+ # assumption is asserted.
+ if last_group_lookahead && @scanner[-1]
+ @scanner.pos -= @scanner[-1].length
+ raise unless res.chomp!(@scanner[-1])
+ end
@line += res.count(NEWLINE)
@expected = nil
if !@strs.empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT
View
6 lib/sass/scss/rx.rb
@@ -112,7 +112,7 @@ def self.quote(str, flags = 0)
INTERP_START = /#\{/
MOZ_ANY = quote(":-moz-any(", Regexp::IGNORECASE)
- IDENT_HYPHEN_INTERP = /-(?=#\{)/
+ IDENT_HYPHEN_INTERP = /-(#\{)/
STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
@@ -120,9 +120,9 @@ def self.quote(str, flags = 0)
# We could use it for 1.9 only, but I don't want to introduce a cross-version
# behavior difference.
# In any case, almost all CSS idents will be matched by this.
- STATIC_VALUE = /(-?#{NMSTART}|#{STRING_NOINTERP}|\s(?!%)|#[a-f0-9]|[,%]|#{NUM}|\!important)+(?=[;}])/i
+ STATIC_VALUE = /(-?#{NMSTART}|#{STRING_NOINTERP}|\s(?!%)|#[a-f0-9]|[,%]|#{NUM}|\!important)+([;}])/i
- STATIC_SELECTOR = /(#{NMCHAR}|\s|[,>+*]|[:#.]#{NMSTART})+(?=[{])/i
+ STATIC_SELECTOR = /(#{NMCHAR}|\s|[,>+*]|[:#.]#{NMSTART})+([{])/i
end
end
end
View
25 test/sass/scss/scss_test.rb
@@ -1270,4 +1270,29 @@ def test_options_passed_to_script
foo {color: darken(black, 10%)}
SCSS
end
+
+ # ref: https://github.com/nex3/sass/issues/104
+ def test_no_buffer_overflow
+ template = render <<SCSS
+.aaa {
+ background-color: white;
+}
+.aaa .aaa .aaa {
+ background-color: black;
+}
+.bbb {
+ @extend .aaa;
+}
+.xxx {
+ @extend .bbb;
+}
+.yyy {
+ @extend .bbb;
+}
+.zzz {
+ @extend .bbb;
+}
+SCSS
+ Sass::SCSS::Parser.new(template, "test.scss").parse
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.