Browse Source

* Fix integer overflow bug.

git-svn-id: trunk@3208 -
daniel 19 years ago
parent
commit
8d3042e8be
1 changed files with 99 additions and 107 deletions
  1. 99 107
      packages/base/paszlib/zdeflate.pas

+ 99 - 107
packages/base/paszlib/zdeflate.pas

@@ -374,7 +374,7 @@ procedure  flush_pending (var strm : z_stream); forward;
 {local}
 {local}
 function read_buf(strm : z_streamp;
 function read_buf(strm : z_streamp;
                   buf : Pbyte;
                   buf : Pbyte;
-                  size : cardinal) : integer; forward;
+                  size : cardinal) : cardinal; forward;
 {$ifdef ASMV}
 {$ifdef ASMV}
 procedure match_init; { asm code initialization }
 procedure match_init; { asm code initialization }
 function longest_match(var deflate_state; cur_match : IPos) : cardinal; forward;
 function longest_match(var deflate_state; cur_match : IPos) : cardinal; forward;
@@ -698,9 +698,7 @@ begin
               and s^.hash_mask;
               and s^.hash_mask;
 
 
   for n := 0 to length - MIN_MATCH do
   for n := 0 to length - MIN_MATCH do
-  begin
     INSERT_STRING(s^, n, hash_head);
     INSERT_STRING(s^, n, hash_head);
-  end;
   {if (hash_head <> 0) then
   {if (hash_head <> 0) then
     hash_head := 0;  - to make compiler happy }
     hash_head := 0;  - to make compiler happy }
   deflateSetDictionary := Z_OK;
   deflateSetDictionary := Z_OK;
@@ -1139,31 +1137,25 @@ end;
   (See also flush_pending()). }
   (See also flush_pending()). }
 
 
 {local}
 {local}
-function read_buf(strm : z_streamp; buf : Pbyte; size : cardinal) : integer;
-var
-  len : cardinal;
-begin
-  len := strm^.avail_in;
+function read_buf(strm:z_streamp;buf:Pbyte;size:cardinal):cardinal;
 
 
-  if (len > size) then
-    len := size;
-  if (len = 0) then
-  begin
-    read_buf := 0;
-    exit;
-  end;
+var len:cardinal;
 
 
+begin
+  len:=strm^.avail_in;
+  if len>size then
+    len:=size;
   dec(strm^.avail_in, len);
   dec(strm^.avail_in, len);
 
 
-  if deflate_state_ptr(strm^.state)^.noheader = 0 then
-  begin
-    strm^.adler := adler32(strm^.adler, strm^.next_in, len);
-  end;
-  move(strm^.next_in^,buf^,len);
-  inc(strm^.next_in, len);
-  inc(strm^.total_in, len);
-
-  read_buf := len;
+  if len<>0 then
+    begin
+      if deflate_state_ptr(strm^.state)^.noheader=0 then
+        strm^.adler:=adler32(strm^.adler,strm^.next_in,len);
+      move(strm^.next_in^,buf^,len);
+      inc(strm^.next_in,len);
+      inc(strm^.total_in,len);
+    end;
+  read_buf:=len;
 end;
 end;
 
 
 { ===========================================================================
 { ===========================================================================
@@ -1754,7 +1746,7 @@ begin
     if (s.strstart = 0) or (longint(s.strstart) >= max_start) then
     if (s.strstart = 0) or (longint(s.strstart) >= max_start) then
     begin
     begin
       { strstart = 0 is possible when wraparound on 16-bit machine }
       { strstart = 0 is possible when wraparound on 16-bit machine }
-      s.lookahead := cardinal(s.strstart - max_start);
+      s.lookahead := cardinal(s.strstart) - cardinal(max_start);
       s.strstart := cardinal(max_start);
       s.strstart := cardinal(max_start);
       {FLUSH_BLOCK(s, FALSE);}
       {FLUSH_BLOCK(s, FALSE);}
       FLUSH_BLOCK_ONLY(s, FALSE);
       FLUSH_BLOCK_ONLY(s, FALSE);
@@ -1837,9 +1829,7 @@ begin
       dictionary, and set hash_head to the head of the hash chain: }
       dictionary, and set hash_head to the head of the hash chain: }
 
 
     if (s.lookahead >= MIN_MATCH) then
     if (s.lookahead >= MIN_MATCH) then
-    begin
       INSERT_STRING(s, s.strstart, hash_head);
       INSERT_STRING(s, s.strstart, hash_head);
-    end;
 
 
     { Find the longest match, discarding those <= prev_length.
     { Find the longest match, discarding those <= prev_length.
       At this point we have always match_length < MIN_MATCH }
       At this point we have always match_length < MIN_MATCH }
@@ -1960,33 +1950,30 @@ begin
   hash_head := ZNIL;
   hash_head := ZNIL;
 
 
   { Process the input block. }
   { Process the input block. }
-  while TRUE do
-  begin
+  repeat
     { Make sure that we always have enough lookahead, except
     { Make sure that we always have enough lookahead, except
       at the end of the input file. We need MAX_MATCH bytes
       at the end of the input file. We need MAX_MATCH bytes
       for the next match, plus MIN_MATCH bytes to insert the
       for the next match, plus MIN_MATCH bytes to insert the
       string following the next match. }
       string following the next match. }
 
 
     if (s.lookahead < MIN_LOOKAHEAD) then
     if (s.lookahead < MIN_LOOKAHEAD) then
-    begin
-      fill_window(s);
-      if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then
       begin
       begin
-        deflate_slow := need_more;
-        exit;
+        fill_window(s);
+        if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then
+          begin
+            deflate_slow := need_more;
+            exit;
+          end;
+
+        if s.lookahead=0 then
+          break; { flush the current block }
       end;
       end;
 
 
-      if (s.lookahead = 0) then
-        break; { flush the current block }
-    end;
-
     { Insert the string window[strstart .. strstart+2] in the
     { Insert the string window[strstart .. strstart+2] in the
       dictionary, and set hash_head to the head of the hash chain: }
       dictionary, and set hash_head to the head of the hash chain: }
 
 
     if (s.lookahead >= MIN_MATCH) then
     if (s.lookahead >= MIN_MATCH) then
-    begin
       INSERT_STRING(s, s.strstart, hash_head);
       INSERT_STRING(s, s.strstart, hash_head);
-    end;
 
 
     { Find the longest match, discarding those <= prev_length. }
     { Find the longest match, discarding those <= prev_length. }
 
 
@@ -1996,106 +1983,111 @@ begin
 
 
     if (hash_head <> ZNIL) and (s.prev_length < s.max_lazy_match) and
     if (hash_head <> ZNIL) and (s.prev_length < s.max_lazy_match) and
        (s.strstart - hash_head <= {MAX_DIST}(s.w_size-MIN_LOOKAHEAD)) then
        (s.strstart - hash_head <= {MAX_DIST}(s.w_size-MIN_LOOKAHEAD)) then
-    begin
+      begin
         { To simplify the code, we prevent matches with the string
         { To simplify the code, we prevent matches with the string
           of window index 0 (in particular we have to avoid a match
           of window index 0 (in particular we have to avoid a match
           of the string with itself at the start of the input file). }
           of the string with itself at the start of the input file). }
 
 
         if (s.strategy <> Z_HUFFMAN_ONLY) then
         if (s.strategy <> Z_HUFFMAN_ONLY) then
-        begin
           s.match_length := longest_match (s, hash_head);
           s.match_length := longest_match (s, hash_head);
-        end;
         { longest_match() sets match_start }
         { longest_match() sets match_start }
 
 
         if (s.match_length <= 5) and ((s.strategy = Z_FILTERED) or
         if (s.match_length <= 5) and ((s.strategy = Z_FILTERED) or
              ((s.match_length = MIN_MATCH) and
              ((s.match_length = MIN_MATCH) and
               (s.strstart - s.match_start > TOO_FAR))) then
               (s.strstart - s.match_start > TOO_FAR))) then
-        begin
+          begin
             { If prev_match is also MIN_MATCH, match_start is garbage
             { If prev_match is also MIN_MATCH, match_start is garbage
               but we will ignore the current match anyway. }
               but we will ignore the current match anyway. }
 
 
             s.match_length := MIN_MATCH-1;
             s.match_length := MIN_MATCH-1;
-        end;
-    end;
+          end;
+      end;
     { If there was a match at the previous step and the current
     { If there was a match at the previous step and the current
       match is not better, output the previous match: }
       match is not better, output the previous match: }
 
 
-    if (s.prev_length >= MIN_MATCH)
-      and (s.match_length <= s.prev_length) then
-    begin
-      max_insert := s.strstart + s.lookahead - MIN_MATCH;
-      { Do not insert strings in hash table beyond this. }
-      {$ifdef DEBUG}
-      check_match(s, s.strstart-1, s.prev_match, s.prev_length);
-      {$endif}
+    if (s.prev_length>=MIN_MATCH) and (s.match_length<=s.prev_length) then
+      begin
+        max_insert := s.strstart + s.lookahead - MIN_MATCH;
+        { Do not insert strings in hash table beyond this. }
+        {$ifdef DEBUG}
+        check_match(s, s.strstart-1, s.prev_match, s.prev_length);
+        {$endif}
 
 
-      {_tr_tally_dist(s, s->strstart -1 - s->prev_match,
-	                s->prev_length - MIN_MATCH, bflush);}
-      bflush := _tr_tally(s, s.strstart -1 - s.prev_match,
-                           s.prev_length - MIN_MATCH);
+        {_tr_tally_dist(s, s->strstart -1 - s->prev_match,
+  	                  s->prev_length - MIN_MATCH, bflush);}
+        bflush := _tr_tally(s, s.strstart -1 - s.prev_match,
+                             s.prev_length - MIN_MATCH);
 
 
       { Insert in hash table all strings up to the end of the match.
       { Insert in hash table all strings up to the end of the match.
         strstart-1 and strstart are already inserted. If there is not
         strstart-1 and strstart are already inserted. If there is not
         enough lookahead, the last two strings are not inserted in
         enough lookahead, the last two strings are not inserted in
         the hash table. }
         the hash table. }
 
 
-      dec(s.lookahead, s.prev_length-1);
-      dec(s.prev_length, 2);
-      repeat
+{$ifdef debug}
+        if s.lookahead<s.prev_length-1 then
+           runerror(255);
+{$endif}
+        dec(s.lookahead, s.prev_length-1);
+        dec(s.prev_length, 2);
+        repeat
+          inc(s.strstart);
+          if s.strstart<=max_insert then
+            INSERT_STRING(s, s.strstart, hash_head);
+          dec(s.prev_length);
+        until s.prev_length = 0;
+        s.match_available := false;
+        s.match_length := MIN_MATCH-1;
         inc(s.strstart);
         inc(s.strstart);
-        if (s.strstart <= max_insert) then
-        begin
-          INSERT_STRING(s, s.strstart, hash_head);
-        end;
-        dec(s.prev_length);
-      until (s.prev_length = 0);
-      s.match_available := FALSE;
-      s.match_length := MIN_MATCH-1;
-      inc(s.strstart);
 
 
-      if (bflush) then  {FLUSH_BLOCK(s, FALSE);}
-      begin
-        FLUSH_BLOCK_ONLY(s, FALSE);
-        if (s.strm^.avail_out = 0) then
-        begin
-          deflate_slow := need_more;
-          exit;
-        end;
-      end;
-    end
+        if bflush then  {FLUSH_BLOCK(s, FALSE);}
+          begin
+            FLUSH_BLOCK_ONLY(s,false);
+            if s.strm^.avail_out=0 then
+              begin
+                deflate_slow := need_more;
+                exit;
+              end;
+          end;
+      end
     else
     else
-      if (s.match_available) then
-      begin
-        { If there was no match at the previous position, output a
-          single literal. If there was a match but the current match
-          is longer, truncate the previous match to a single literal. }
-        {$IFDEF DEBUG}
-        Tracevv(char(s.window^[s.strstart-1]));
-        {$ENDIF}
-        bflush := _tr_tally (s, 0, s.window^[s.strstart-1]);
-
-        if bflush then
-        begin
-          FLUSH_BLOCK_ONLY(s, FALSE);
-        end;
-        inc(s.strstart);
-        dec(s.lookahead);
-        if (s.strm^.avail_out = 0) then
+      if s.match_available then
         begin
         begin
-          deflate_slow := need_more;
-          exit;
-        end;
-      end
+          { If there was no match at the previous position, output a
+            single literal. If there was a match but the current match
+            is longer, truncate the previous match to a single literal. }
+          {$IFDEF DEBUG}
+          Tracevv(char(s.window^[s.strstart-1]));
+          {$ENDIF}
+          bflush := _tr_tally (s, 0, s.window^[s.strstart-1]);
+
+          if bflush then
+            FLUSH_BLOCK_ONLY(s, FALSE);
+          inc(s.strstart);
+{$ifdef debug}
+          if s.lookahead=0 then
+             runerror(255);
+{$endif}
+          dec(s.lookahead);
+          if (s.strm^.avail_out = 0) then
+            begin
+              deflate_slow := need_more;
+              exit;
+            end;
+        end
       else
       else
-      begin
+        begin
         { There is no previous match to compare with, wait for
         { There is no previous match to compare with, wait for
           the next step to decide. }
           the next step to decide. }
 
 
-        s.match_available := TRUE;
-        inc(s.strstart);
-        dec(s.lookahead);
-      end;
-  end;
+          s.match_available := TRUE;
+          inc(s.strstart);
+{$ifdef debug}
+          if s.lookahead=0 then
+             runerror(255);
+{$endif}
+          dec(s.lookahead);
+        end;
+  until false;
 
 
   {$IFDEF DEBUG}
   {$IFDEF DEBUG}
   Assert (flush <> Z_NO_FLUSH, 'no flush?');
   Assert (flush <> Z_NO_FLUSH, 'no flush?');