Skip to content

Commit

Permalink
fix: remove side effects in ZLib
Browse files Browse the repository at this point in the history
  • Loading branch information
tsvetomir committed Aug 31, 2020
1 parent 99ca52b commit 7f4ab18
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 32 deletions.
52 changes: 36 additions & 16 deletions lib/utils/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,50 @@

// String encode/decode helpers

import { shrinkBuf } from './common';
import { Buf8, shrinkBuf } from './common';


// Quick check if we can use fast array to bin string conversion
//
// - apply(Array) can fail on Android 2.2
// - apply(Uint8Array) can fail on iOS 5.1 Safari
//
var STR_APPLY_OK = true;
var STR_APPLY_UIA_OK = true;
let strApplyOK = function() {
let result = true;
try {
String.fromCharCode.apply(null, [ 0 ]);
} catch (_) {
result = false;
}

try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; }
try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }
strApplyOK = () => result;
return result;
}

let strApplyUintOK = function() {
let result = true;
try {
String.fromCharCode.apply(null, new Uint8Array(1));
} catch (_) {
result = false;
}

// Table with utf8 lengths (calculated by first byte of sequence)
// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
// because max possible codepoint is 0x10ffff
var _utf8len = new Uint8Array(256);
for (var q = 0; q < 256; q++) {
_utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
strApplyUintOK = () => result;
return result;
}
_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start

let utf8len = function(c) {
// Table with utf8 lengths (calculated by first byte of sequence)
// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
// because max possible codepoint is 0x10ffff
var table = Buf8(256);
for (var q = 0; q < 256; q++) {
table[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
}
table[254] = table[254] = 1; // Invalid sequence start

utf8len = arg => table[arg];
return table[c];
}

// convert string to array (typed, when possible)
export function string2buf(str) {
Expand Down Expand Up @@ -87,7 +107,7 @@ function _buf2binstring(buf, len) {
// If the length of the buffer is smaller than that, we can use this optimization,
// otherwise we will take a slower path.
if (len < 65534) {
if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) {
if ((buf.subarray && strApplyUintOK()) || (!buf.subarray && strApplyOK())) {
return String.fromCharCode.apply(null, shrinkBuf(buf, len));
}
}
Expand Down Expand Up @@ -131,7 +151,7 @@ export function buf2string(buf, max) {
// quick process ascii
if (c < 0x80) { utf16buf[out++] = c; continue; }

c_len = _utf8len[c];
c_len = utf8len(c);
// skip 5 & 6 byte codes
if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }

Expand Down Expand Up @@ -183,5 +203,5 @@ export function utf8border(buf, max) {
// return max too.
if (pos === 0) { return max; }

return (pos + _utf8len[buf[pos]] > max) ? pos : max;
return (pos + utf8len(buf[pos]) > max) ? pos : max;
}
10 changes: 6 additions & 4 deletions lib/zlib/crc32.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ function makeTable() {
return table;
}

// Create table on load. Just 255 signed longs. Not a problem.
var crcTable = makeTable();

let crcTable = function() {
const table = makeTable();
crcTable = () => table;
return table;
}

export default function crc32(crc, buf, len, pos) {
var t = crcTable,
var t = crcTable(),
end = pos + len;

crc ^= -1;
Expand Down
36 changes: 24 additions & 12 deletions lib/zlib/trees.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,37 +113,31 @@ var bl_order =
var DIST_CODE_LEN = 512; /* see definition of array dist_code below */

// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
var static_ltree = new Array((L_CODES + 2) * 2);
zero(static_ltree);
var static_ltree;
/* The static literal tree. Since the bit lengths are imposed, there is no
* need for the L_CODES extra codes used during heap construction. However
* The codes 286 and 287 are needed to build a canonical tree (see _tr_init
* below).
*/

var static_dtree = new Array(D_CODES * 2);
zero(static_dtree);
var static_dtree;
/* The static distance tree. (Actually a trivial tree since all codes use
* 5 bits.)
*/

var _dist_code = new Array(DIST_CODE_LEN);
zero(_dist_code);
var _dist_code;
/* Distance codes. The first 256 values correspond to the distances
* 3 .. 258, the last 256 values correspond to the top 8 bits of
* the 15 bit distances.
*/

var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1);
zero(_length_code);
var _length_code;
/* length code for each normalized match length (0 == MIN_MATCH) */

var base_length = new Array(LENGTH_CODES);
zero(base_length);
var base_length;
/* First normalized length for each code (0 = MIN_MATCH) */

var base_dist = new Array(D_CODES);
zero(base_dist);
var base_dist;
/* First normalized distance for each code (0 = distance of 1) */


Expand Down Expand Up @@ -399,6 +393,24 @@ function tr_static_init() {
var bl_count = new Array(MAX_BITS + 1);
/* number of codes at each bit length for an optimal tree */

static_ltree = new Array((L_CODES + 2) * 2);
zero(static_ltree);

static_dtree = new Array(D_CODES * 2);
zero(static_dtree);

_dist_code = new Array(DIST_CODE_LEN);
zero(_dist_code);

_length_code = new Array(MAX_MATCH - MIN_MATCH + 1);
zero(_length_code);

base_length = new Array(LENGTH_CODES);
zero(base_length);

base_dist = new Array(D_CODES);
zero(base_dist);

// do check in _tr_init()
//if (static_init_done) return;

Expand Down

0 comments on commit 7f4ab18

Please sign in to comment.