Browse Source

fixes for errors

Arjun Barrett 4 years ago
parent
commit
b18737f53f
6 changed files with 89 additions and 93 deletions
  1. 3 3
      docs/README.md
  2. 1 1
      package.json
  3. 1 1
      rs/fflate/Cargo.toml
  4. 15 22
      rs/fflate/src/lib.rs
  5. 63 59
      src/index.ts
  6. 6 7
      src/worker.ts

+ 3 - 3
docs/README.md

@@ -96,7 +96,7 @@
 
 ### AsyncFlateStreamHandler
 
-Ƭ  **AsyncFlateStreamHandler**: (err: [Error](interfaces/flateerror.md#error),data: Uint8Array,final: boolean) => void
+Ƭ  **AsyncFlateStreamHandler**: (err: [FlateError](interfaces/flateerror.md),data: Uint8Array,final: boolean) => void
 
 Handler for asynchronous data (de)compression streams
 
@@ -118,7 +118,7 @@ ___
 
 ### FlateCallback
 
-Ƭ  **FlateCallback**: (err: [Error](interfaces/flateerror.md#error) \| string,data: Uint8Array) => void
+Ƭ  **FlateCallback**: (err: [FlateError](interfaces/flateerror.md),data: Uint8Array) => void
 
 Callback for asynchronous (de)compression methods
 
@@ -154,7 +154,7 @@ ___
 
 ### UnzipCallback
 
-Ƭ  **UnzipCallback**: (err: [Error](interfaces/flateerror.md#error) \| string,data: [Unzipped](interfaces/unzipped.md)) => void
+Ƭ  **UnzipCallback**: (err: [FlateError](interfaces/flateerror.md),data: [Unzipped](interfaces/unzipped.md)) => void
 
 Callback for asynchronous ZIP decompression
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "fflate",
-  "version": "0.6.10",
+  "version": "0.7.0",
   "description": "High performance (de)compression in an 8kB package",
   "main": "./lib/index.cjs",
   "module": "./esm/browser.js",

+ 1 - 1
rs/fflate/Cargo.toml

@@ -28,7 +28,7 @@ miniz_oxide = "*"
 opt-level = 3
 lto = true
 # TO FIX
-debug = true
+# debug = true
 
 [features]
 std = []

+ 15 - 22
rs/fflate/src/lib.rs

@@ -9,7 +9,7 @@
 use lazy_static::lazy_static;
 
 // #[cfg(feature = "std")]
-use std::{vec::Vec, io::{Read, Write, Error, ErrorKind}, ops::Range};
+use std::{convert::TryInto, io::{Read, Write, Error, ErrorKind}, ops::Range, vec::Vec};
 
 const fleb: [usize; 32] = [
     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0,
@@ -149,19 +149,13 @@ lazy_static! {
 }
 
 #[inline(always)]
-unsafe fn bits(dat: &[u8], pos: usize, mask: u8) -> u8 {
-    let b = pos >> 3;
-    ((*dat.get_unchecked(b) as u16 | ((*dat.get_unchecked(b + 1) as u16) << 8)) >> (pos & 7)) as u8 & mask
+fn read_u16(buf: &[u8], bt: usize) -> u16 {
+    u16::from_le_bytes(buf[bt..bt + 2].try_into().unwrap())
 }
 
 #[inline(always)]
-unsafe fn bits16(dat: &[u8], pos: usize, mask: u16) -> u16 {
-    let b = pos >> 3;
-    ((*dat.get_unchecked(b) as u32
-        | ((*dat.get_unchecked(b + 1) as u32) << 8)
-        | ((*dat.get_unchecked(b + 2) as u32) << 16))
-        >> (pos & 7)) as u16
-        & mask
+fn read_u32(buf: &[u8], bt: usize) -> u32 {
+    u32::from_le_bytes(buf[bt..bt + 4].try_into().unwrap())
 }
 
 #[inline(always)]
@@ -294,18 +288,21 @@ fn max(dat: &[u8]) -> u8 {
 
 unsafe fn inflt(dat: &[u8], buf: &mut Vec<u8>, st: &mut InflateState) -> Result<(), InflateError> {
     let mut pos = st.pos;
+    let mut bb: u32;
     let sl = dat.len();
     if sl == 0 || (st.head && sl < 5) { return Ok(()); }
     let tbts = sl << 3;
     loop {
         if st.head {
-            st.bfinal = bits(dat, pos, 1) != 0;
-            let btype = bits(dat, pos + 1, 3);
+            bb = if (pos >> 3) + 4 > sl { read_u16(buf, pos >> 3) as u32 } else { read_u32(buf, pos >> 3) };
+            let off = pos & 7;
+            st.bfinal = (bb >> off) & 1 != 0;
+            let btype = (bb >> (off + 1)) & 3;
             pos += 3;
             match btype {
                 0 => {
                     let s = shft(pos) + 4;
-                    let t = s + (dat[s - 4] as u16 | ((dat[s - 3] as u16) << 8)) as usize;
+                    let t = s + read_u16(dat, s) as usize;
                     if t > dat.len() {
                         if st.last {
                             return Err(InflateError::UnexpectedEOF);
@@ -390,16 +387,14 @@ unsafe fn inflt(dat: &[u8], buf: &mut Vec<u8>, st: &mut InflateState) -> Result<
             }
         }
         st.head = false;
-        let lms = (1u16 << st.lbits) - 1;
-        let dms = (1u16 << st.dbits) - 1;
+        let lms = (1usize << st.lbits) - 1;
+        let dms = (1usize << st.dbits) - 1;
         let top = tbts - (st.lbits + st.dbits + 18) as usize;
         let lm = st.lmap;
         let dm = st.dmap;
         let lst = st.last;
         while lst || pos < top {
-            let c = lm[
-                bits16(dat, pos, lms) as usize
-            ];
+            let c = lm[gbits16(dat, pos, lms)];
             if c == 0 {
                 return Err(InflateError::InvalidLengthOrLiteral);
             }
@@ -418,9 +413,7 @@ unsafe fn inflt(dat: &[u8], buf: &mut Vec<u8>, st: &mut InflateState) -> Result<
                     add = bits(dat, pos, (1 << b) - 1) as usize + fl[i];
                     pos += b;
                 }
-                let d = dm[
-                    bits16(dat, pos, dms) as usize
-                ];
+                let d = dm[gbits16(dat, pos, dms)];
                 if d == 0 {
                     return Err(InflateError::InvalidDistance);
                 }

+ 63 - 59
src/index.ts

@@ -203,7 +203,7 @@ const ec = [
   'invalid distance',
   'stream finished',
   'no stream handler',
-  0 as unknown as string, // determined by compression function
+  , // determined by compression function
   'no callback',
   'invalid UTF-8 data',
   'extra field too long',
@@ -1037,8 +1037,8 @@ const astrmify = <T>(fns: (() => unknown[])[], strm: Astrm, opts: T | 0, init: (
   )
   w.postMessage(opts);
   strm.push = (d, f) => {
-    if (t) err(4);
     if (!strm.ondata) err(5);
+    if (t) strm.ondata(err(4, 0, 1), null, !!f);
     w.postMessage([d, t = f], [d.buffer]);
   };
   strm.terminate = () => { w.terminate(); };
@@ -1153,8 +1153,8 @@ export class Deflate {
    * @param final Whether this is the last chunk
    */
   push(chunk: Uint8Array, final?: boolean) {
-    if (this.d) err(4);
     if (!this.ondata) err(5);
+    if (this.d) err(4);
     this.d = final;
     this.p(chunk, final || false);
   }
@@ -1256,8 +1256,8 @@ export class Inflate {
   ondata: FlateStreamHandler;
 
   private e(c: Uint8Array) {
-    if (this.d) err(4);
     if (!this.ondata) err(5);
+    if (this.d) err(4);
     const l = this.p.length;
     const n = new u8(l + c.length);
     n.set(this.p), n.set(c, l), this.p = n;
@@ -2628,61 +2628,65 @@ export class Zip {
    * @param file The file stream to add
    */
   add(file: ZipInputFile) {
-    if (this.d & 2) err(4);
-    const f = strToU8(file.filename), fl = f.length;
-    const com = file.comment, o = com && strToU8(com);
-    const u = fl != file.filename.length || (o && (com.length != o.length));
-    const hl = fl + exfl(file.extra) + 30;
-    if (fl > 65535) err(11);
-    const header = new u8(hl);
-    wzh(header, 0, file, f, u);
-    let chks: Uint8Array[] = [header];
-    const pAll = () => {
-      for (const chk of chks) this.ondata(null, chk, false);
-      chks = [];
-    };
-    let tr = this.d;
-    this.d = 0;
-    const ind = this.u.length;
-    const uf = mrg(file, {
-      f,
-      u,
-      o,
-      t: () => { 
-        if (file.terminate) file.terminate();
-      },
-      r: () => {
-        pAll();
-        if (tr) {
-          const nxt = this.u[ind + 1];
-          if (nxt) nxt.r();
-          else this.d = 1;
-        }
-        tr = 1;
-      }
-    } as ZIFE);
-    let cl = 0;
-    file.ondata = (err, dat, final) => {
-      if (err) {
-        this.ondata(err, dat, final);
-        this.terminate();
-      } else {
-        cl += dat.length;
-        chks.push(dat);
-        if (final) {
-          const dd = new u8(16);
-          wbytes(dd, 0, 0x8074B50)
-          wbytes(dd, 4, file.crc);
-          wbytes(dd, 8, cl);
-          wbytes(dd, 12, file.size);
-          chks.push(dd);
-          uf.c = cl, uf.b = hl + cl + 16, uf.crc = file.crc, uf.size = file.size;
-          if (tr) uf.r();
+    if (!this.ondata) err(5);
+    // finishing or finished
+    if (this.d & 2) this.ondata(err(4 + (this.d & 1) * 8, 0, 1), null, false);
+    else {
+      const f = strToU8(file.filename), fl = f.length;
+      const com = file.comment, o = com && strToU8(com);
+      const u = fl != file.filename.length || (o && (com.length != o.length));
+      const hl = fl + exfl(file.extra) + 30;
+      if (fl > 65535) this.ondata(err(11, 0, 1), null, false);
+      const header = new u8(hl);
+      wzh(header, 0, file, f, u);
+      let chks: Uint8Array[] = [header];
+      const pAll = () => {
+        for (const chk of chks) this.ondata(null, chk, false);
+        chks = [];
+      };
+      let tr = this.d;
+      this.d = 0;
+      const ind = this.u.length;
+      const uf = mrg(file, {
+        f,
+        u,
+        o,
+        t: () => { 
+          if (file.terminate) file.terminate();
+        },
+        r: () => {
+          pAll();
+          if (tr) {
+            const nxt = this.u[ind + 1];
+            if (nxt) nxt.r();
+            else this.d = 1;
+          }
           tr = 1;
-        } else if (tr) pAll();
+        }
+      } as ZIFE);
+      let cl = 0;
+      file.ondata = (err, dat, final) => {
+        if (err) {
+          this.ondata(err, dat, final);
+          this.terminate();
+        } else {
+          cl += dat.length;
+          chks.push(dat);
+          if (final) {
+            const dd = new u8(16);
+            wbytes(dd, 0, 0x8074B50)
+            wbytes(dd, 4, file.crc);
+            wbytes(dd, 8, cl);
+            wbytes(dd, 12, file.size);
+            chks.push(dd);
+            uf.c = cl, uf.b = hl + cl + 16, uf.crc = file.crc, uf.size = file.size;
+            if (tr) uf.r();
+            tr = 1;
+          } else if (tr) pAll();
+        }
       }
+      this.u.push(uf);
     }
-    this.u.push(uf);
   }
 
   /**
@@ -2692,8 +2696,8 @@ export class Zip {
    */
   end() {
     if (this.d & 2) {
-      if (this.d & 1) err(12);
-      err(4);
+      this.ondata(err(4 + (this.d & 1) * 8, 0, 1), null, true);
+      return;
     }
     if (this.d) this.e();
     else this.u.push({
@@ -3110,7 +3114,7 @@ export class Unzip {
                 if (!sc) file.ondata(null, et, true);
                 else {
                   const ctr = this.o[cmp];
-                  if (!ctr) err(14, 'unknown compression type ' + cmp);
+                  if (!ctr) file.ondata(err(14, 'unknown compression type ' + cmp, 1), null, false);
                   d = sc < 0 ? new ctr(fn) : new ctr(fn, sc, su);
                   d.ondata = (err, dat, final) => { file.ondata(err, dat, final); }
                   for (const dat of chks) d.push(dat, false);

+ 6 - 7
src/worker.ts

@@ -3,16 +3,15 @@ const ch2: Record<string, string> = {};
 export default <T>(c: string, id: number, msg: unknown, transfer: ArrayBuffer[], cb: (err: Error, msg: T) => void) => {
   const w = new Worker(ch2[id] ||= URL.createObjectURL(
     new Blob([
-      c + ';addEventListener("error",function(e){e=e.error;postMessage([e.message,e.code,e.stack])})'
+      c + ';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})'
     ], { type: 'text/javascript' })
   ));
   w.onmessage = e => {
-    const d = e.data;
-    if (Array.isArray(d)) {
-      const err = new Error(d[0]);
-      err['code'] = d[1];
-      // if Error#stack DNE, still undefined
-      err.stack = d[2];
+    const d = e.data, ed = d.$e$;
+    if (ed) {
+      const err = new Error(ed[0]);
+      err['code'] = ed[1];
+      err.stack = ed[2];
       cb(err, null);
     } else cb(null, d);
   }