Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

Commit

Permalink
Bug 803931 - Compiler is vulnerable to the billion laughs attack. r=g…
Browse files Browse the repository at this point in the history
…andalf
  • Loading branch information
stasm committed Jun 24, 2013
1 parent 0c9f193 commit c2c59a9
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ LIB_FILES = \
tests/lib/context/*.js \
tests/lib/compiler/*.js \
tests/integration/*.js
ifeq ($(INSECURE), 1)
LIB_FILES += tests/lib/compiler/insecure/*.js
endif

BINDINGS?=html

Expand Down
7 changes: 7 additions & 0 deletions lib/l20n/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ define(function (require, exports, module) {

// Private

var MAX_PLACEABLE_LENGTH = 2500;

var _emitter = new EventEmitter();
var _parser = new Parser(true);
var _env = {};
Expand Down Expand Up @@ -537,6 +539,11 @@ define(function (require, exports, module) {
throw new RuntimeError('Placeables must be strings or ' +
'numbers');
}
if (part.length > MAX_PLACEABLE_LENGTH) {
throw new RuntimeError('Placeable has too many characters, ' +
'maximum allowed is ' +
MAX_PLACEABLE_LENGTH);
}
parts.push(part);
}
} finally {
Expand Down
9 changes: 9 additions & 0 deletions lib/l20n/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ define(function (require, exports, module) {

/* Private */

var MAX_PLACEABLES = 100;

var _source, _index, _length, _emitter;

var getLOL;
Expand Down Expand Up @@ -385,6 +387,8 @@ define(function (require, exports, module) {
var body; // body of a complex string
var bstart = _index; // buffer start index
var complex = false;
var placeables = 0; // number of placeables found, capped by
// MAX_PLACEABLES

// unescape \\ \' \" \{{
var pos = _source.indexOf('\\');
Expand Down Expand Up @@ -412,6 +416,10 @@ define(function (require, exports, module) {
body = [];
complex = true;
}
if (placeables > MAX_PLACEABLES - 1) {
throw error('Too many placeables, maximum allowed is ' +
MAX_PLACEABLES);
}
if (bstart < pos) {
body.push({
type: 'String',
Expand All @@ -426,6 +434,7 @@ define(function (require, exports, module) {
_source.charCodeAt(_index+1) !== 125) {
throw error('Expected "}}"');
}
placeables++;
pos = _index + 2;
bstart = pos;
pos = _source.indexOf('{{', pos);
Expand Down
120 changes: 120 additions & 0 deletions tests/lib/compiler/insecure/dos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
var Parser = require('../../../../lib/l20n/parser').Parser;
var Compiler = process.env.L20N_COV
? require('../../../../build/cov/lib/l20n/compiler').Compiler
: require('../../../../lib/l20n/compiler').Compiler;

var parser = new Parser();
var compiler = new Compiler();

// Bug 803931 - Compiler is vulnerable to the billion laughs attack
describe('Reference bombs', function(){
var source, ctxdata, ast, env;
beforeEach(function() {
ast = parser.parse(source);
env = compiler.reset().compile(ast);
});

describe('Billion Laughs', function(){
before(function() {
source = ' \
<lol0 "LOL"> \
<lol1 "{{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}}"> \
<lol2 "{{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}}"> \
<lol3 "{{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}}"> \
<lol4 "{{lol3}} {{lol3}} {{lol3}} {{lol3}} {{lol3}} {{lol3}} {{lol3}} {{lol3}} {{lol3}} {{lol3}}"> \
<lol5 "{{lol4}} {{lol4}} {{lol4}} {{lol4}} {{lol4}} {{lol4}} {{lol4}} {{lol4}} {{lol4}} {{lol4}}"> \
<lol6 "{{lol5}} {{lol5}} {{lol5}} {{lol5}} {{lol5}} {{lol5}} {{lol5}} {{lol5}} {{lol5}} {{lol5}}"> \
<lol7 "{{lol6}} {{lol6}} {{lol6}} {{lol6}} {{lol6}} {{lol6}} {{lol6}} {{lol6}} {{lol6}} {{lol6}}"> \
<lol8 "{{lol7}} {{lol7}} {{lol7}} {{lol7}} {{lol7}} {{lol7}} {{lol7}} {{lol7}} {{lol7}} {{lol7}}"> \
<lol9 "{{lol8}} {{lol8}} {{lol8}} {{lol8}} {{lol8}} {{lol8}} {{lol8}} {{lol8}} {{lol8}} {{lol8}}"> \
<lolz "{{ lol9 }}"> \
';
});
it('throws', function() {
(function() {
env.lolz.getString();
}).should.throw(/too many characters/);
});
});

describe('Quadratic Blowup', function(){
before(function() {
source = ' \
/* \
* Project Gutenberg\'s Alice\'s Adventures in Wonderland, \
* by Lewis Carroll \
* \
* This eBook is for the use of anyone anywhere at no cost and with \
* almost no restrictions whatsoever. You may copy it, give it away \
* or re-use it under the terms of the Project Gutenberg License \
* included with this eBook or online at www.gutenberg.org \
*/ \
\
<alice """ \
\
CHAPTER I. Down the Rabbit-Hole \
\
Alice was beginning to get very tired of sitting by her sister on \
the bank, and of having nothing to do: once or twice she had peeped \
into the book her sister was reading, but it had no pictures or \
conversations in it, \'and what is the use of a book,\' thought \
Alice \'without pictures or conversation?\' \
\
So she was considering in her own mind (as well as she could, for \
the hot day made her feel very sleepy and stupid), whether the \
pleasure of making a daisy-chain would be worth the trouble of \
getting up and picking the daisies, when suddenly a White Rabbit \
with pink eyes ran close by her. \
\
There was nothing so VERY remarkable in that; nor did Alice think \
it so VERY much out of the way to hear the Rabbit say to itself, \
\'Oh dear! Oh dear! I shall be late!\' (when she thought it over \
afterwards, it occurred to her that she ought to have wondered at \
this, but at the time it all seemed quite natural); but when the \
Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and \
looked at it, and then hurried on, Alice started to her feet, for \
it flashed across her mind that she had never before seen a rabbit \
with either a waistcoat-pocket, or a watch to take out of it, and \
burning with curiosity, she ran across the field after it, and \
fortunately was just in time to see it pop down a large rabbit-hole \
under the hedge. \
\
In another moment down went Alice after it, never once considering \
how in the world she was to get out again. \
\
The rabbit-hole went straight on like a tunnel for some way, and \
then dipped suddenly down, so suddenly that Alice had not a moment \
to think about stopping herself before she found herself falling \
down a very deep well. \
\
"""> \
\
<malice """ \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
{{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \
"""> \
';
});
it('throws', function() {
(function() {
env.malice.getString();
}).should.throw(/too many placeables/i);
});
});

});

0 comments on commit c2c59a9

Please sign in to comment.