From fb41089c8c06f3589a0dad6b5b333735bc14dee3 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Sun, 3 Jan 2016 14:48:42 +0000 Subject: [PATCH] Fixes #715 - stack too deep in comment scan. Using recursion was a short sighted idea. --- History.md | 1 + lib/imports/inliner.js | 50 +++++++++++++++++++--------------------- test/integration-test.js | 15 ++++++++++++ 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/History.md b/History.md index 9965dc0d..882a53c4 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ * Fixed issue [#693](https://github.com/jakubpawlowicz/clean-css/issues/693) - restructuring edge case. * Fixed issue [#711](https://github.com/jakubpawlowicz/clean-css/issues/711) - border fuzzy matching. * Fixed issue [#714](https://github.com/jakubpawlowicz/clean-css/issues/714) - stringifying property level at rules. +* Fixed issue [#715](https://github.com/jakubpawlowicz/clean-css/issues/715) - stack too deep in comment scan. [3.4.8 / 2015-11-13](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.7...v3.4.8) ================== diff --git a/lib/imports/inliner.js b/lib/imports/inliner.js index 9a586516..c6686a70 100644 --- a/lib/imports/inliner.js +++ b/lib/imports/inliner.js @@ -123,32 +123,30 @@ function commentScanner(data) { if (noComments) return false; - // idx can be still within last matched comment (many @import statements inside one comment) - if (idx > lastStartIndex && idx < lastEndIndex) - return true; - - comment = data.match(commentRegex); - - if (!comment) { - noComments = true; - return false; - } - - // get the indexes relative to the current data chunk - lastStartIndex = localStartIndex = comment.index; - localEndIndex = localStartIndex + comment[0].length; - - // calculate the indexes relative to the full original data - globalEndIndex = localEndIndex + lastEndIndex; - globalStartIndex = globalEndIndex - comment[0].length; - - // chop off data up to and including current comment block - data = data.substring(localEndIndex); - lastEndIndex = globalEndIndex; - - // re-run scan if comment ended before the idx - if (globalEndIndex < idx) - return scanner(idx); + do { + // idx can be still within last matched comment (many @import statements inside one comment) + if (idx > lastStartIndex && idx < lastEndIndex) + return true; + + comment = data.match(commentRegex); + + if (!comment) { + noComments = true; + return false; + } + + // get the indexes relative to the current data chunk + lastStartIndex = localStartIndex = comment.index; + localEndIndex = localStartIndex + comment[0].length; + + // calculate the indexes relative to the full original data + globalEndIndex = localEndIndex + lastEndIndex; + globalStartIndex = globalEndIndex - comment[0].length; + + // chop off data up to and including current comment block + data = data.substring(localEndIndex); + lastEndIndex = globalEndIndex; + } while (globalEndIndex < idx); return globalEndIndex > idx && idx > globalStartIndex; }; diff --git a/test/integration-test.js b/test/integration-test.js index ecc8ef9e..3c1f09c0 100644 --- a/test/integration-test.js +++ b/test/integration-test.js @@ -4,6 +4,17 @@ var path = require('path'); var optimizerContext = require('./test-helper').optimizerContext; var lineBreak = require('os').EOL; +function generateComments(count) { + var output = []; + var i; + + for (i = 0; i < count; i++) { + output.push('/* */'); + } + + return output.join(''); +} + vows.describe('integration tests') .addBatch( optimizerContext('identity', { @@ -2075,6 +2086,10 @@ vows.describe('integration tests') 'remote inside local after imported content': [ '@import url(test/fixtures/partials/one.css);@import url(test/fixtures/partials/remote.css);', '.one{color:red}' + ], + 'scanning comments and stack too deep exception': [ + generateComments(30000) + '@import url(fonts.google.com/some.css);', + '' ] }, { root: process.cwd() }) ) -- 2.34.1