--- /usr/share/novnc/include/jsunzip.js.bckp 2016-11-21 11:55:25.398249613 +0100 +++ /usr/share/novnc/include/jsunzip.js 2016-12-13 13:41:36.482542892 +0100 @@ -206,7 +206,8 @@ this.OK = 0; this.DATA_ERROR = (-3); -this.WINDOW_SIZE = 32768; +this.WINDOW_SIZE = 32768; // must be a power of 2 +this.WINDOW_MASK = this.WINDOW_SIZE-1; /* ------------------------------ * * -- internal data structures -- * @@ -226,6 +227,7 @@ this.dest = []; this.history = []; + this.historyIndex = 0; this.ltree = new that.TREE(); /* dynamic length/symbol tree */ this.dtree = new that.TREE(); /* dynamic distance tree */ @@ -499,10 +501,10 @@ if (sym < 256) { ddest[ddestlength++] = sym; // ? String.fromCharCode(sym); - d.history.push(sym); + d.history[(d.historyIndex++) & this.WINDOW_MASK] = sym; } else { - var length, dist, offs; + var length, dist, offs, rawOffs; var i; sym -= 257; @@ -513,16 +515,18 @@ dist = this.decode_symbol(d, dt); /* possibly get more bits from distance code */ - offs = d.history.length - this.read_bits(d, this.dist_bits[dist], this.dist_base[dist]); + rawOffs = this.read_bits(d, this.dist_bits[dist], this.dist_base[dist]); + + if (rawOffs > this.WINDOW_SIZE || rawOffs > d.history.length) + throw ("Invalid zlib offset " + rawOffs); + + offs = d.historyIndex + this.WINDOW_SIZE - rawOffs - if (offs < 0) - throw ("Invalid zlib offset " + offs); - /* copy match */ for (i = offs; i < offs + length; ++i) { //ddest[ddestlength++] = ddest[i]; - ddest[ddestlength++] = d.history[i]; - d.history.push(d.history[i]); + ddest[ddestlength++] = d.history[i & this.WINDOW_MASK]; + d.history[(d.historyIndex++) & this.WINDOW_MASK] = d.history[i & this.WINDOW_MASK]; } } } @@ -556,7 +560,7 @@ /* copy block */ for (i = length; i; --i) { - d.history.push(d.source[d.sourceIndex]); + d.history[(d.historyIndex++) & this.WINDOW_MASK] = d.source[d.sourceIndex]; d.dest[d.dest.length] = d.source[d.sourceIndex++]; } @@ -668,8 +672,9 @@ } while (!bfinal && d.sourceIndex < d.source.length); - d.history = d.history.slice(-this.WINDOW_SIZE); + // normalize + d.historyIndex = d.historyIndex & this.WINDOW_MASK; return { 'status' : this.OK, 'data' : d.dest }; }