zlib-streams 1.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/Makefile +21 -8
  2. package/dist/zlib-streams-dev.wasm +0 -0
  3. package/dist/zlib-streams.js +135 -62
  4. package/dist/zlib-streams.wasm +0 -0
  5. package/package.json +2 -2
  6. package/src/README.md +61 -1
  7. package/src/chunkcopy.h +565 -0
  8. package/src/compare256.h +56 -0
  9. package/src/cpu_features.h +22 -0
  10. package/src/deflate.c +2349 -0
  11. package/src/deflate.h +420 -0
  12. package/src/deflate_crc32.c +22 -0
  13. package/src/inffast.h +26 -0
  14. package/src/{inffast.c → inffast_chunk.c} +127 -71
  15. package/src/inffast_chunk.h +42 -0
  16. package/src/inflate.c +69 -33
  17. package/src/insert_string.h +80 -0
  18. package/src/wasm/api/zlib-streams.js +135 -62
  19. package/build/debug/src/inffast.d +0 -8
  20. package/build/debug/src/inffast.o +0 -0
  21. package/build/debug/src/inflate.d +0 -8
  22. package/build/debug/src/inflate.o +0 -0
  23. package/build/debug/src/inftrees.d +0 -6
  24. package/build/debug/src/inftrees.o +0 -0
  25. package/build/debug/src/zlib/adler32.d +0 -5
  26. package/build/debug/src/zlib/adler32.o +0 -0
  27. package/build/debug/src/zlib/contrib/infback9/infback9.d +0 -13
  28. package/build/debug/src/zlib/contrib/infback9/infback9.o +0 -0
  29. package/build/debug/src/zlib/contrib/infback9/inftree9.d +0 -7
  30. package/build/debug/src/zlib/contrib/infback9/inftree9.o +0 -0
  31. package/build/debug/src/zlib/crc32.d +0 -6
  32. package/build/debug/src/zlib/crc32.o +0 -0
  33. package/build/debug/src/zlib/trees.d +0 -7
  34. package/build/debug/src/zlib/trees.o +0 -0
  35. package/build/debug/src/zlib/zutil.d +0 -6
  36. package/build/debug/src/zlib/zutil.o +0 -0
  37. package/tmp/all_runs/payload_decompress_nowindow_debug__100k_lines.deflate64.log +0 -34
  38. package/tmp/all_runs/payload_decompress_nowindow_debug__100k_lines.deflate64.out +0 -100000
  39. package/tmp/all_runs/payload_decompress_nowindow_debug__10k_lines.deflate64.log +0 -2
  40. package/tmp/all_runs/payload_decompress_nowindow_debug__10k_lines.deflate64.out +0 -10000
  41. package/tmp/all_runs/payload_decompress_nowindow_debug__payload_63k.deflate64.log +0 -1
  42. package/tmp/all_runs/payload_decompress_nowindow_debug__payload_63k.deflate64.out +0 -0
  43. package/tmp/all_runs/payload_decompress_nowindow_debug__payload_64k.deflate64.log +0 -1
  44. package/tmp/all_runs/payload_decompress_nowindow_debug__payload_64k.deflate64.out +0 -0
  45. package/tmp/all_runs/payload_decompress_nowindow_debug__payload_65k.deflate64.log +0 -2
  46. package/tmp/all_runs/payload_decompress_nowindow_debug__payload_65k.deflate64.out +0 -0
  47. package/tmp/all_runs/payload_decompress_nowindow_debug__rand_block_gap.deflate64.log +0 -1
  48. package/tmp/all_runs/payload_decompress_nowindow_debug__rand_block_gap.deflate64.out +0 -0
  49. package/tmp/all_runs/payload_decompress_nowindow_debug__repeat_63k.deflate64.log +0 -1
  50. package/tmp/all_runs/payload_decompress_nowindow_debug__repeat_63k.deflate64.out +0 -0
  51. package/tmp/all_runs/payload_decompress_nowindow_debug__repeat_64k.deflate64.log +0 -1
  52. package/tmp/all_runs/payload_decompress_nowindow_debug__repeat_64k.deflate64.out +0 -0
  53. package/tmp/all_runs/payload_decompress_nowindow_debug__repeat_65k.deflate64.log +0 -2
  54. package/tmp/all_runs/payload_decompress_nowindow_debug__repeat_65k.deflate64.out +0 -0
  55. package/tmp/all_runs/payload_decompress_nowindow_debug__zeros_100k.deflate64.log +0 -2
  56. package/tmp/all_runs/payload_decompress_nowindow_debug__zeros_100k.deflate64.out +0 -0
  57. package/tmp/all_runs/payload_decompress_ref_debug__100k_lines.deflate64.log +0 -1
  58. package/tmp/all_runs/payload_decompress_ref_debug__100k_lines.deflate64.out +0 -100000
  59. package/tmp/all_runs/payload_decompress_ref_debug__10k_lines.deflate64.log +0 -1
  60. package/tmp/all_runs/payload_decompress_ref_debug__10k_lines.deflate64.out +0 -10000
  61. package/tmp/all_runs/payload_decompress_ref_debug__payload_63k.deflate64.log +0 -1
  62. package/tmp/all_runs/payload_decompress_ref_debug__payload_63k.deflate64.out +0 -0
  63. package/tmp/all_runs/payload_decompress_ref_debug__payload_64k.deflate64.log +0 -1
  64. package/tmp/all_runs/payload_decompress_ref_debug__payload_64k.deflate64.out +0 -0
  65. package/tmp/all_runs/payload_decompress_ref_debug__payload_65k.deflate64.log +0 -1
  66. package/tmp/all_runs/payload_decompress_ref_debug__payload_65k.deflate64.out +0 -0
  67. package/tmp/all_runs/payload_decompress_ref_debug__rand_block_gap.deflate64.log +0 -1
  68. package/tmp/all_runs/payload_decompress_ref_debug__rand_block_gap.deflate64.out +0 -0
  69. package/tmp/all_runs/payload_decompress_ref_debug__repeat_63k.deflate64.log +0 -1
  70. package/tmp/all_runs/payload_decompress_ref_debug__repeat_63k.deflate64.out +0 -0
  71. package/tmp/all_runs/payload_decompress_ref_debug__repeat_64k.deflate64.log +0 -1
  72. package/tmp/all_runs/payload_decompress_ref_debug__repeat_64k.deflate64.out +0 -0
  73. package/tmp/all_runs/payload_decompress_ref_debug__repeat_65k.deflate64.log +0 -1
  74. package/tmp/all_runs/payload_decompress_ref_debug__repeat_65k.deflate64.out +0 -0
  75. package/tmp/all_runs/payload_decompress_ref_debug__zeros_100k.deflate64.log +0 -1
  76. package/tmp/all_runs/payload_decompress_ref_debug__zeros_100k.deflate64.out +0 -0
  77. package/tmp/all_runs/payload_decompress_test_debug__100k_lines.deflate64.log +0 -34
  78. package/tmp/all_runs/payload_decompress_test_debug__100k_lines.deflate64.out +0 -100000
  79. package/tmp/all_runs/payload_decompress_test_debug__10k_lines.deflate64.log +0 -2
  80. package/tmp/all_runs/payload_decompress_test_debug__10k_lines.deflate64.out +0 -10000
  81. package/tmp/all_runs/payload_decompress_test_debug__payload_63k.deflate64.log +0 -1
  82. package/tmp/all_runs/payload_decompress_test_debug__payload_63k.deflate64.out +0 -0
  83. package/tmp/all_runs/payload_decompress_test_debug__payload_64k.deflate64.log +0 -1
  84. package/tmp/all_runs/payload_decompress_test_debug__payload_64k.deflate64.out +0 -0
  85. package/tmp/all_runs/payload_decompress_test_debug__payload_65k.deflate64.log +0 -2
  86. package/tmp/all_runs/payload_decompress_test_debug__payload_65k.deflate64.out +0 -0
  87. package/tmp/all_runs/payload_decompress_test_debug__rand_block_gap.deflate64.log +0 -1
  88. package/tmp/all_runs/payload_decompress_test_debug__rand_block_gap.deflate64.out +0 -0
  89. package/tmp/all_runs/payload_decompress_test_debug__repeat_63k.deflate64.log +0 -1
  90. package/tmp/all_runs/payload_decompress_test_debug__repeat_63k.deflate64.out +0 -0
  91. package/tmp/all_runs/payload_decompress_test_debug__repeat_64k.deflate64.log +0 -1
  92. package/tmp/all_runs/payload_decompress_test_debug__repeat_64k.deflate64.out +0 -0
  93. package/tmp/all_runs/payload_decompress_test_debug__repeat_65k.deflate64.log +0 -2
  94. package/tmp/all_runs/payload_decompress_test_debug__repeat_65k.deflate64.out +0 -0
  95. package/tmp/all_runs/payload_decompress_test_debug__zeros_100k.deflate64.log +0 -2
  96. package/tmp/all_runs/payload_decompress_test_debug__zeros_100k.deflate64.out +0 -0
  97. package/tmp/all_runs/wasm__100k_lines.deflate64.out +0 -100000
  98. package/tmp/all_runs/wasm__10k_lines.deflate64.out +0 -10000
  99. package/tmp/all_runs/wasm__payload_63k.deflate64.out +0 -0
  100. package/tmp/all_runs/wasm__payload_64k.deflate64.out +0 -0
  101. package/tmp/all_runs/wasm__payload_65k.deflate64.out +0 -0
  102. package/tmp/all_runs/wasm__rand_block_gap.deflate64.out +0 -0
  103. package/tmp/all_runs/wasm__repeat_63k.deflate64.out +0 -0
  104. package/tmp/all_runs/wasm__repeat_64k.deflate64.out +0 -0
  105. package/tmp/all_runs/wasm__repeat_65k.deflate64.out +0 -0
  106. package/tmp/all_runs/wasm__zeros_100k.deflate64.out +0 -0
  107. package/tmp/diagnose/diagnose_stream_mem.json +0 -4202
package/src/inflate.c CHANGED
@@ -91,7 +91,8 @@
91
91
  #include "zutil.h"
92
92
  #include "inftrees.h"
93
93
  #include "inflate.h"
94
- #include "inffast.h"
94
+ #include "inffast_chunk.h"
95
+ #include "chunkcopy.h"
95
96
 
96
97
  #ifndef BUILDFIXED
97
98
  # define BUILDFIXED
@@ -215,6 +216,7 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
215
216
  state->strm = strm;
216
217
  state->window = Z_NULL;
217
218
  state->mode = HEAD; /* to pass state test in inflateReset2() */
219
+ state->check = 1L; /* 1L is the result of adler32() zero length data */
218
220
  ret = inflateReset2(strm, windowBits);
219
221
  if (ret != Z_OK) {
220
222
  ZFREE(strm, state);
@@ -380,10 +382,20 @@ local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
380
382
 
381
383
  /* if it hasn't been done already, allocate space for the window */
382
384
  if (state->window == Z_NULL) {
385
+ unsigned wsize = 1U << state->wbits;
383
386
  state->window = (unsigned char FAR *)
384
- ZALLOC(strm, 1U << state->wbits,
387
+ ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE,
385
388
  sizeof(unsigned char));
386
389
  if (state->window == Z_NULL) return 1;
390
+ #ifdef INFLATE_CLEAR_UNUSED_UNDEFINED
391
+ /* Copies from the overflow portion of this buffer are undefined and
392
+ may cause analysis tools to raise a warning if we don't initialize
393
+ it. However, this undefined data overwrites other undefined data
394
+ and is subsequently either overwritten or left deliberately
395
+ undefined at the end of decode; so there's really no point.
396
+ */
397
+ zmemzero(state->window + wsize, CHUNKCOPY_CHUNK_SIZE);
398
+ #endif
387
399
  }
388
400
 
389
401
  /* if window not in use yet, initialize */
@@ -649,12 +661,12 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
649
661
  if (
650
662
  #endif
651
663
  ((BITS(8) << 8) + (hold >> 8)) % 31) {
652
- strm->msg = (z_const char *)"incorrect header check";
664
+ strm->msg = (char *)"incorrect header check";
653
665
  state->mode = BAD;
654
666
  break;
655
667
  }
656
668
  if (BITS(4) != Z_DEFLATED) {
657
- strm->msg = (z_const char *)"unknown compression method";
669
+ strm->msg = (char *)"unknown compression method";
658
670
  state->mode = BAD;
659
671
  break;
660
672
  }
@@ -663,7 +675,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
663
675
  if (state->wbits == 0)
664
676
  state->wbits = len;
665
677
  if (len > 15 || len > state->wbits) {
666
- strm->msg = (z_const char *)"invalid window size";
678
+ strm->msg = (char *)"invalid window size";
667
679
  state->mode = BAD;
668
680
  break;
669
681
  }
@@ -679,12 +691,12 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
679
691
  NEEDBITS(16);
680
692
  state->flags = (int)(hold);
681
693
  if ((state->flags & 0xff) != Z_DEFLATED) {
682
- strm->msg = (z_const char *)"unknown compression method";
694
+ strm->msg = (char *)"unknown compression method";
683
695
  state->mode = BAD;
684
696
  break;
685
697
  }
686
698
  if (state->flags & 0xe000) {
687
- strm->msg = (z_const char *)"unknown header flags set";
699
+ strm->msg = (char *)"unknown header flags set";
688
700
  state->mode = BAD;
689
701
  break;
690
702
  }
@@ -800,7 +812,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
800
812
  if (state->flags & 0x0200) {
801
813
  NEEDBITS(16);
802
814
  if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
803
- strm->msg = (z_const char *)"header crc mismatch";
815
+ strm->msg = (char *)"header crc mismatch";
804
816
  state->mode = BAD;
805
817
  break;
806
818
  }
@@ -862,7 +874,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
862
874
  state->mode = TABLE;
863
875
  break;
864
876
  case 3:
865
- strm->msg = (z_const char *)"invalid block type";
877
+ strm->msg = (char *)"invalid block type";
866
878
  state->mode = BAD;
867
879
  }
868
880
  DROPBITS(2);
@@ -871,7 +883,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
871
883
  BYTEBITS(); /* go to byte boundary */
872
884
  NEEDBITS(32);
873
885
  if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
874
- strm->msg = (z_const char *)"invalid stored block lengths";
886
+ strm->msg = (char *)"invalid stored block lengths";
875
887
  state->mode = BAD;
876
888
  break;
877
889
  }
@@ -913,7 +925,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
913
925
  #ifndef PKZIP_BUG_WORKAROUND
914
926
  if (state->nlen > 286 ||
915
927
  (!state->deflate64 && state->ndist > 30)) {
916
- strm->msg = (z_const char *)"too many length or distance symbols";
928
+ strm->msg = (char *)"too many length or distance symbols";
917
929
  state->mode = BAD;
918
930
  break;
919
931
  }
@@ -937,7 +949,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
937
949
  &(state->lenbits), state->work,
938
950
  state->deflate64);
939
951
  if (ret) {
940
- strm->msg = (z_const char *)"invalid code lengths set";
952
+ strm->msg = (char *)"invalid code lengths set";
941
953
  state->mode = BAD;
942
954
  break;
943
955
  }
@@ -961,7 +973,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
961
973
  NEEDBITS(here.bits + 2);
962
974
  DROPBITS(here.bits);
963
975
  if (state->have == 0) {
964
- strm->msg = (z_const char *)"invalid bit length repeat";
976
+ strm->msg = (char *)"invalid bit length repeat";
965
977
  state->mode = BAD;
966
978
  break;
967
979
  }
@@ -984,7 +996,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
984
996
  DROPBITS(7);
985
997
  }
986
998
  if (state->have + copy > state->nlen + state->ndist) {
987
- strm->msg = (z_const char *)"invalid bit length repeat";
999
+ strm->msg = (char *)"invalid bit length repeat";
988
1000
  state->mode = BAD;
989
1001
  break;
990
1002
  }
@@ -998,13 +1010,13 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
998
1010
 
999
1011
  /* check for end-of-block code (better have one) */
1000
1012
  if (state->lens[256] == 0) {
1001
- strm->msg = (z_const char *)"invalid code -- missing end-of-block";
1013
+ strm->msg = (char *)"invalid code -- missing end-of-block";
1002
1014
  state->mode = BAD;
1003
1015
  break;
1004
1016
  }
1005
1017
 
1006
1018
  /* build code tables -- note: do not change the lenbits or distbits
1007
- values here (9 and 6) without reading the comments in inftrees.h
1019
+ values here (10 and 9) without reading the comments in inftrees.h
1008
1020
  concerning the ENOUGH constants, which depend on those values */
1009
1021
  state->next = state->codes;
1010
1022
  state->lencode = (const code FAR *)(state->next);
@@ -1013,7 +1025,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1013
1025
  &(state->lenbits), state->work,
1014
1026
  state->deflate64);
1015
1027
  if (ret) {
1016
- strm->msg = (z_const char *)"invalid literal/lengths set";
1028
+ strm->msg = (char *)"invalid literal/lengths set";
1017
1029
  state->mode = BAD;
1018
1030
  break;
1019
1031
  }
@@ -1023,7 +1035,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1023
1035
  &(state->next), &(state->distbits), state->work,
1024
1036
  state->deflate64);
1025
1037
  if (ret) {
1026
- strm->msg = (z_const char *)"invalid distances set";
1038
+ strm->msg = (char *)"invalid distances set";
1027
1039
  state->mode = BAD;
1028
1040
  break;
1029
1041
  }
@@ -1035,9 +1047,10 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1035
1047
  state->mode = LEN;
1036
1048
  /* fallthrough */
1037
1049
  case LEN:
1038
- if (!state->deflate64 && have >= 6 && left >= 258) {
1050
+ if (!state->deflate64 && have >= INFLATE_FAST_MIN_INPUT &&
1051
+ left >= INFLATE_FAST_MIN_OUTPUT) {
1039
1052
  RESTORE();
1040
- inflate_fast(strm, out);
1053
+ inflate_fast_chunk_(strm, out);
1041
1054
  LOAD();
1042
1055
  if (state->mode == TYPE)
1043
1056
  state->back = -1;
@@ -1077,7 +1090,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1077
1090
  break;
1078
1091
  }
1079
1092
  if (here.op & 64) {
1080
- strm->msg = (z_const char *)"invalid literal/length code";
1093
+ strm->msg = (char *)"invalid literal/length code";
1081
1094
  state->mode = BAD;
1082
1095
  break;
1083
1096
  }
@@ -1115,7 +1128,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1115
1128
  DROPBITS(here.bits);
1116
1129
  state->back += here.bits;
1117
1130
  if (here.op & 64) {
1118
- strm->msg = (z_const char *)"invalid distance code";
1131
+ strm->msg = (char *)"invalid distance code";
1119
1132
  state->mode = BAD;
1120
1133
  break;
1121
1134
  }
@@ -1132,7 +1145,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1132
1145
  }
1133
1146
  #ifdef INFLATE_STRICT
1134
1147
  if (state->offset > state->dmax) {
1135
- strm->msg = (z_const char *)"invalid distance too far back";
1148
+ strm->msg = (char *)"invalid distance too far back";
1136
1149
  state->mode = BAD;
1137
1150
  break;
1138
1151
  }
@@ -1147,7 +1160,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1147
1160
  copy = state->offset - copy;
1148
1161
  if (copy > state->whave) {
1149
1162
  if (state->sane) {
1150
- strm->msg = (z_const char *)"invalid distance too far back";
1163
+ strm->msg = (char *)"invalid distance too far back";
1151
1164
  state->mode = BAD;
1152
1165
  break;
1153
1166
  }
@@ -1172,17 +1185,16 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1172
1185
  else
1173
1186
  from = state->window + (state->wnext - copy);
1174
1187
  if (copy > state->length) copy = state->length;
1188
+ if (copy > left) copy = left;
1189
+ put = chunkcopy_safe(put, from, copy, put + left);
1175
1190
  }
1176
1191
  else { /* copy from output */
1177
- from = put - state->offset;
1178
1192
  copy = state->length;
1193
+ if (copy > left) copy = left;
1194
+ put = chunkcopy_lapped_safe(put, state->offset, copy, put + left);
1179
1195
  }
1180
- if (copy > left) copy = left;
1181
1196
  left -= copy;
1182
1197
  state->length -= copy;
1183
- do {
1184
- *put++ = *from++;
1185
- } while (--copy);
1186
1198
  if (state->length == 0) state->mode = LEN;
1187
1199
  break;
1188
1200
  case LIT:
@@ -1206,7 +1218,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1206
1218
  state->flags ? hold :
1207
1219
  #endif
1208
1220
  ZSWAP32(hold)) != state->check) {
1209
- strm->msg = (z_const char *)"incorrect data check";
1221
+ strm->msg = (char *)"incorrect data check";
1210
1222
  state->mode = BAD;
1211
1223
  break;
1212
1224
  }
@@ -1220,7 +1232,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1220
1232
  if (state->wrap && state->flags) {
1221
1233
  NEEDBITS(32);
1222
1234
  if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
1223
- strm->msg = (z_const char *)"incorrect length check";
1235
+ strm->msg = (char *)"incorrect length check";
1224
1236
  state->mode = BAD;
1225
1237
  break;
1226
1238
  }
@@ -1251,6 +1263,29 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
1251
1263
  Note: a memory error from inflate() is non-recoverable.
1252
1264
  */
1253
1265
  inf_leave:
1266
+ #if defined(ZLIB_DEBUG)
1267
+ /* XXX(cavalcantii): I put this in place back in 2017 to help debug faulty
1268
+ * client code relying on undefined behavior when chunk_copy first landed.
1269
+ *
1270
+ * It is save to say after all these years that Chromium code is well
1271
+ * behaved and works fine with the optimization, therefore we can enable
1272
+ * this only for DEBUG builds.
1273
+ *
1274
+ * We write a defined value in the unused space to help mark
1275
+ * where the stream has ended. We don't use zeros as that can
1276
+ * mislead clients relying on undefined behavior (i.e. assuming
1277
+ * that the data is over when the buffer has a zero/null value).
1278
+ *
1279
+ * The basic idea is that if client code is not relying on the zlib context
1280
+ * to inform the amount of decompressed data, but instead reads the output
1281
+ * buffer until a zero/null is found, it will fail faster and harder
1282
+ * when the remaining of the buffer is marked with a symbol (e.g. 0x55).
1283
+ */
1284
+ if (left >= CHUNKCOPY_CHUNK_SIZE)
1285
+ memset(put, 0x55, CHUNKCOPY_CHUNK_SIZE);
1286
+ else
1287
+ memset(put, 0x55, left);
1288
+ #endif
1254
1289
  RESTORE();
1255
1290
  if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
1256
1291
  (state->mode < CHECK || flush != Z_FINISH)))
@@ -1464,8 +1499,9 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
1464
1499
  if (copy == Z_NULL) return Z_MEM_ERROR;
1465
1500
  window = Z_NULL;
1466
1501
  if (state->window != Z_NULL) {
1467
- window = (unsigned char FAR *)
1468
- ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
1502
+ window = (unsigned char FAR *)ZALLOC(
1503
+ source, (1U << state->wbits) + CHUNKCOPY_CHUNK_SIZE,
1504
+ sizeof(unsigned char));
1469
1505
  if (window == Z_NULL) {
1470
1506
  ZFREE(source, copy);
1471
1507
  return Z_MEM_ERROR;
@@ -0,0 +1,80 @@
1
+ /* insert_string.h
2
+ *
3
+ * Copyright 2019 The Chromium Authors
4
+ * Use of this source code is governed by a BSD-style license that can be
5
+ * found in the Chromium source repository LICENSE file.
6
+ */
7
+
8
+ #ifndef INSERT_STRING_H
9
+ #define INSERT_STRING_H
10
+
11
+ #ifndef INLINE
12
+ #if defined(_MSC_VER) && !defined(__clang__)
13
+ #define INLINE __inline
14
+ #else
15
+ #define INLINE inline
16
+ #endif
17
+ #endif
18
+
19
+ #include <stdint.h>
20
+
21
+ /**
22
+ * Some applications need to match zlib DEFLATE output exactly [3]. Use the
23
+ * canonical zlib Rabin-Karp rolling hash [1,2] in that case.
24
+ *
25
+ * [1] For a description of the Rabin and Karp algorithm, see "Algorithms"
26
+ * book by R. Sedgewick, Addison-Wesley, p252.
27
+ * [2] https://www.euccas.me/zlib/#zlib_rabin_karp and also "rolling hash"
28
+ * https://en.wikipedia.org/wiki/Rolling_hash
29
+ * [3] crbug.com/1316541 AOSP incremental client APK package OTA upgrades.
30
+ */
31
+ #ifdef CHROMIUM_ZLIB_NO_CASTAGNOLI
32
+ #define USE_ZLIB_RABIN_KARP_ROLLING_HASH
33
+ #endif
34
+
35
+ /* ===========================================================================
36
+ * Update a hash value with the given input byte (Rabin-Karp rolling hash).
37
+ * IN assertion: all calls to UPDATE_HASH are made with consecutive input
38
+ * characters, so that a running hash key can be computed from the previous
39
+ * key instead of complete recalculation each time.
40
+ */
41
+ #define UPDATE_HASH(s, h, c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
42
+
43
+ /* ===========================================================================
44
+ * Insert string str in the dictionary and set match_head to the previous head
45
+ * of the hash chain (the most recent string with same hash key). Return
46
+ * the previous length of the hash chain.
47
+ * If this file is compiled with -DFASTEST, the compression level is forced
48
+ * to 1, and no hash chains are maintained.
49
+ * IN assertion: all calls to INSERT_STRING are made with consecutive input
50
+ * characters and the first MIN_MATCH bytes of str are valid (except for
51
+ * the last MIN_MATCH-1 bytes of the input file).
52
+ */
53
+ local INLINE Pos insert_string(deflate_state* const s, const Pos str) {
54
+ Pos ret;
55
+ /* insert_string dictionary insertion: ANZAC++ hasher
56
+ * significantly improves data compression speed.
57
+ *
58
+ * Note: the generated compressed output is a valid DEFLATE stream, but will
59
+ * differ from canonical zlib output.
60
+ */
61
+ #if defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH)
62
+ UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH - 1)]);
63
+ #else
64
+ uint32_t value;
65
+ // Validated for little endian archs (i.e. x86, Arm). YMMV for big endian.
66
+ zmemcpy(&value, &s->window[str], sizeof(value));
67
+ s->ins_h = ((value * 66521 + 66521) >> 16) & s->hash_mask;
68
+ #endif
69
+
70
+ #ifdef FASTEST
71
+ ret = s->head[s->ins_h];
72
+ #else
73
+ ret = s->prev[str & s->w_mask] = s->head[s->ins_h];
74
+ #endif
75
+ s->head[s->ins_h] = str;
76
+
77
+ return ret;
78
+ }
79
+
80
+ #endif /* INSERT_STRING_H */
@@ -1,7 +1,39 @@
1
- /* eslint-disable no-unused-vars */
2
- /* global Buffer, process, TransformStream */
1
+ /*
2
+ Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
3
 
4
- let wasm, malloc, free, memory;
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the distribution.
13
+
14
+ 3. The names of the authors may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ /* global TransformStream */
30
+
31
+ const FORMAT_DEFLATE = "deflate";
32
+ const FORMAT_DEFLATE_RAW = "deflate-raw";
33
+ const FORMAT_DEFLATE64_RAW = "deflate64-raw";
34
+ const FORMAT_GZIP = "gzip";
35
+
36
+ let wasm, malloc, free, memory, initError;
5
37
 
6
38
  export function setWasmExports(wasmAPI) {
7
39
  wasm = wasmAPI;
@@ -12,53 +44,74 @@ export function setWasmExports(wasmAPI) {
12
44
  }
13
45
  }
14
46
 
47
+ export function setInitError(error) {
48
+ initError = error;
49
+ }
50
+
51
+ export function resetWasmExports() {
52
+ wasm = malloc = free = memory = initError = null;
53
+ }
54
+
15
55
  function _make(isCompress, type, options = {}) {
56
+ if (!wasm) {
57
+ const error = new Error("WASM module not loaded");
58
+ error.cause = initError;
59
+ throw error;
60
+ }
16
61
  const level = (typeof options.level === "number") ? options.level : -1;
17
62
  const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
18
63
  const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
19
64
 
20
65
  return new TransformStream({
21
66
  start() {
22
- let result;
23
- this.out = malloc(outBufferSize);
24
- this.in = malloc(inBufferSize);
25
- this.inBufferSize = inBufferSize;
26
- this._scratch = new Uint8Array(outBufferSize);
27
- if (isCompress) {
28
- this._process = wasm.deflate_process;
29
- this._last_consumed = wasm.deflate_last_consumed;
30
- this._end = wasm.deflate_end;
31
- this.streamHandle = wasm.deflate_new();
32
- if (type === "gzip") {
33
- result = wasm.deflate_init_gzip(this.streamHandle, level);
34
- } else if (type === "deflate-raw") {
35
- result = wasm.deflate_init_raw(this.streamHandle, level);
36
- } else {
37
- result = wasm.deflate_init(this.streamHandle, level);
67
+ try {
68
+ let result;
69
+ this.out = malloc(outBufferSize);
70
+ this.in = malloc(inBufferSize);
71
+ this.inBufferSize = inBufferSize;
72
+ if (!this.out || !this.in) {
73
+ throw new Error("allocation failed");
38
74
  }
39
- } else {
40
- if (type === "deflate64-raw") {
41
- this._process = wasm.inflate9_process;
42
- this._last_consumed = wasm.inflate9_last_consumed;
43
- this._end = wasm.inflate9_end;
44
- this.streamHandle = wasm.inflate9_new();
45
- result = wasm.inflate9_init_raw(this.streamHandle);
75
+ this._scratch = new Uint8Array(outBufferSize);
76
+ if (isCompress) {
77
+ this._process = wasm.deflate_process;
78
+ this._last_consumed = wasm.deflate_last_consumed;
79
+ this._end = wasm.deflate_end;
80
+ this.streamHandle = wasm.deflate_new();
81
+ if (type === FORMAT_GZIP) {
82
+ result = wasm.deflate_init_gzip(this.streamHandle, level);
83
+ } else if (type === FORMAT_DEFLATE_RAW) {
84
+ result = wasm.deflate_init_raw(this.streamHandle, level);
85
+ } else {
86
+ result = wasm.deflate_init(this.streamHandle, level);
87
+ }
46
88
  } else {
47
- this._process = wasm.inflate_process;
48
- this._last_consumed = wasm.inflate_last_consumed;
49
- this._end = wasm.inflate_end;
50
- this.streamHandle = wasm.inflate_new();
51
- if (type === "deflate-raw") {
52
- result = wasm.inflate_init_raw(this.streamHandle);
53
- } else if (type === "gzip") {
54
- result = wasm.inflate_init_gzip(this.streamHandle);
89
+ if (type === FORMAT_DEFLATE64_RAW) {
90
+ this._process = wasm.inflate9_process;
91
+ this._last_consumed = wasm.inflate9_last_consumed;
92
+ this._end = wasm.inflate9_end;
93
+ this.streamHandle = wasm.inflate9_new();
94
+ result = wasm.inflate9_init_raw(this.streamHandle);
55
95
  } else {
56
- result = wasm.inflate_init(this.streamHandle);
96
+ this._process = wasm.inflate_process;
97
+ this._last_consumed = wasm.inflate_last_consumed;
98
+ this._end = wasm.inflate_end;
99
+ this.streamHandle = wasm.inflate_new();
100
+ if (type === FORMAT_DEFLATE_RAW) {
101
+ result = wasm.inflate_init_raw(this.streamHandle);
102
+ } else if (type === FORMAT_GZIP) {
103
+ result = wasm.inflate_init_gzip(this.streamHandle);
104
+ } else {
105
+ result = wasm.inflate_init(this.streamHandle);
106
+ }
57
107
  }
58
108
  }
59
- }
60
- if (result !== 0) {
61
- throw new Error("init failed:" + result);
109
+ if (result !== 0) {
110
+ throw new Error("init failed:" + result);
111
+ }
112
+ } catch (error) {
113
+ disposeStream(this);
114
+ throw error;
62
115
  }
63
116
  },
64
117
  transform(chunk, controller) {
@@ -75,9 +128,13 @@ function _make(isCompress, type, options = {}) {
75
128
  if (!this.in || this.inBufferSize < toRead) {
76
129
  if (this.in && free) {
77
130
  free(this.in);
131
+ this.in = 0;
78
132
  }
79
133
  this.in = malloc(toRead);
80
134
  this.inBufferSize = toRead;
135
+ if (!this.in) {
136
+ throw new Error("allocation failed");
137
+ }
81
138
  }
82
139
  heap.set(buffer.subarray(offset, offset + toRead), this.in);
83
140
  const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
@@ -94,21 +151,13 @@ function _make(isCompress, type, options = {}) {
94
151
  }
95
152
  }
96
153
  const consumed = last_consumed(this.streamHandle);
97
- if (consumed === 0) {
154
+ if (consumed === 0 && prod === 0) {
98
155
  break;
99
156
  }
100
157
  offset += consumed;
101
158
  }
102
159
  } catch (error) {
103
- if (this._end && this.streamHandle) {
104
- this._end(this.streamHandle);
105
- }
106
- if (this.in && free) {
107
- free(this.in);
108
- }
109
- if (this.out && free) {
110
- free(this.out);
111
- }
160
+ disposeStream(this);
112
161
  controller.error(error);
113
162
  }
114
163
  },
@@ -139,30 +188,54 @@ function _make(isCompress, type, options = {}) {
139
188
  } catch (error) {
140
189
  controller.error(error);
141
190
  } finally {
142
- if (this._end && this.streamHandle) {
143
- const result = this._end(this.streamHandle);
144
- if (result !== 0) {
145
- controller.error(new Error("end error:" + result));
146
- }
147
- }
148
- if (this.in && free) {
149
- free(this.in);
150
- }
151
- if (this.out && free) {
152
- free(this.out);
191
+ const result = disposeStream(this);
192
+ if (result !== 0) {
193
+ controller.error(new Error("end error:" + result));
153
194
  }
154
195
  }
196
+ },
197
+ cancel() {
198
+ // release the stream handle and buffers when the pipeline is aborted,
199
+ // they would be leaked in the process-lifetime wasm heap otherwise
200
+ disposeStream(this);
155
201
  }
156
202
  });
203
+
204
+ function disposeStream(state) {
205
+ let endResult = 0;
206
+ if (state.streamHandle && state._end) {
207
+ endResult = state._end(state.streamHandle);
208
+ }
209
+ state.streamHandle = 0;
210
+ if (state.in && free) {
211
+ free(state.in);
212
+ }
213
+ state.in = 0;
214
+ if (state.out && free) {
215
+ free(state.out);
216
+ }
217
+ state.out = 0;
218
+ return endResult;
219
+ }
157
220
  }
158
221
 
159
222
  export class CompressionStreamZlib {
160
- constructor(type = "deflate", options) {
223
+ constructor(type = FORMAT_DEFLATE, options) {
161
224
  return _make(true, type, options);
162
225
  }
163
226
  }
164
227
  export class DecompressionStreamZlib {
165
- constructor(type = "deflate", options) {
228
+ constructor(type = FORMAT_DEFLATE, options) {
166
229
  return _make(false, type, options);
167
230
  }
168
- }
231
+ }
232
+ // These codecs are backed by the WASM module; they are unusable until setWasmExports() has run.
233
+ // The worker uses this flag to know it must fall back to the native CompressionStream when the
234
+ // module fails to load, rather than discarding a self-contained codec supplied through config.
235
+ CompressionStreamZlib.requiresModule = true;
236
+ DecompressionStreamZlib.requiresModule = true;
237
+ // Constructing these classes before the module is loaded throws, so capability probes cannot rely
238
+ // on trying the constructor; the formats are declared instead, next to the branches implementing
239
+ // them in _make().
240
+ CompressionStreamZlib.supportedFormats = [FORMAT_DEFLATE, FORMAT_DEFLATE_RAW, FORMAT_GZIP];
241
+ DecompressionStreamZlib.supportedFormats = [FORMAT_DEFLATE, FORMAT_DEFLATE_RAW, FORMAT_GZIP, FORMAT_DEFLATE64_RAW];
@@ -1,8 +0,0 @@
1
- build/debug/src/inffast.o: src/inffast.c src/zlib/zutil.h src/zlib/zlib.h \
2
- src/zlib/zconf.h src/inftrees.h src/inflate.h src/zlib/inffast.h
3
- src/zlib/zutil.h:
4
- src/zlib/zlib.h:
5
- src/zlib/zconf.h:
6
- src/inftrees.h:
7
- src/inflate.h:
8
- src/zlib/inffast.h:
Binary file
@@ -1,8 +0,0 @@
1
- build/debug/src/inflate.o: src/inflate.c src/zlib/zutil.h src/zlib/zlib.h \
2
- src/zlib/zconf.h src/inftrees.h src/inflate.h src/zlib/inffast.h
3
- src/zlib/zutil.h:
4
- src/zlib/zlib.h:
5
- src/zlib/zconf.h:
6
- src/inftrees.h:
7
- src/inflate.h:
8
- src/zlib/inffast.h:
Binary file
@@ -1,6 +0,0 @@
1
- build/debug/src/inftrees.o: src/inftrees.c src/zlib/zutil.h \
2
- src/zlib/zlib.h src/zlib/zconf.h src/inftrees.h
3
- src/zlib/zutil.h:
4
- src/zlib/zlib.h:
5
- src/zlib/zconf.h:
6
- src/inftrees.h:
Binary file