diff --git a/src/highlight.js b/src/highlight.js index ab8203654a..7afe48ff19 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -694,6 +694,12 @@ https://highlightjs.org/ if (lastMatch.type=="begin" && match.type=="end" && lastMatch.index == match.index && lexeme === "") { // spit the "skipped" character that our regex choked on back into the output sequence mode_buffer += codeToHighlight.slice(match.index, match.index + 1); + if (!SAFE_MODE) { + var err = new Error('0 width match regex'); + err.languageName = languageName; + err.badRule = lastMatch.rule; + throw(err); + } return 1; } lastMatch = match; @@ -1018,6 +1024,7 @@ https://highlightjs.org/ hljs.inherit = inherit; hljs.addPlugin = addPlugin; hljs.debugMode = function() { SAFE_MODE = false; } + hljs.safeMode = function() { SAFE_MODE = true; } // Common regexps hljs.IDENT_RE = '[a-zA-Z]\\w*'; diff --git a/test/detect/index.js b/test/detect/index.js index 17c071e7f0..f22b7ea31f 100644 --- a/test/detect/index.js +++ b/test/detect/index.js @@ -5,6 +5,7 @@ delete require.cache[require.resolve('../../build/lib/highlight')] const fs = require('fs').promises; const hljs = require('../../build'); +hljs.debugMode(); // tests run in debug mode so errors are raised const path = require('path'); const utility = require('../utility'); diff --git a/test/index.js b/test/index.js index b224f325e3..fdb0cc6bad 100644 --- a/test/index.js +++ b/test/index.js @@ -1,5 +1,8 @@ 'use strict'; +const hljs = require('../build'); +hljs.debugMode(); // tests run in debug mode so errors are raised + // Tests specific to the API exposed inside the hljs object. // Right now, that only includes tests for several common regular expressions. require('./api'); diff --git a/test/parser/should-not-destroyData.js b/test/parser/should-not-destroyData.js index bce13a1a31..630e6af3b2 100644 --- a/test/parser/should-not-destroyData.js +++ b/test/parser/should-not-destroyData.js @@ -5,6 +5,7 @@ describe("bugs", function () { // CONTEXT: https://github.com/highlightjs/highlight.js/pull/2219 describe("a grammar with a mode that makes a 0 width match", () => { it("should instead count it as a 1 character match", () => { + hljs.safeMode(); hljs.registerLanguage('test-language', (hljs) => { // broken regex from old Fortran ruleset @@ -28,6 +29,12 @@ describe("bugs", function () { // Incorrect prior output: // 'The number is 23_longint yes.' ) + hljs.debugMode(); + should(() => { + hljs.highlight('test-language', 'The number is 123_longint yes.').value + }).throw(Error, { + message: "0 width match regex", + languageName: "test-language"}) }) }) })