LCOV - code coverage report
Current view: top level - g10 - compress.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 138 169 81.7 %
Date: 2016-11-29 15:00:56 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* compress.c - compress filter
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
       3             :  *               2003, 2006, 2010 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : /* Note that the code in compress-bz2.c is nearly identical to the
      22             :    code here, so if you fix a bug here, look there to see if a
      23             :    matching bug needs to be fixed.  I tried to have one set of
      24             :    functions that could do ZIP, ZLIB, and BZIP2, but it became
      25             :    dangerously unreadable with #ifdefs and if(algo) -dshaw */
      26             : 
      27             : #include <config.h>
      28             : #include <stdio.h>
      29             : #include <stdlib.h>
      30             : #include <string.h>
      31             : #include <unistd.h>
      32             : #include <errno.h>
      33             : #ifdef HAVE_ZIP
      34             : # include <zlib.h>
      35             : # if defined(__riscos__) && defined(USE_ZLIBRISCOS)
      36             : #  include "zlib-riscos.h"
      37             : # endif
      38             : #endif
      39             : 
      40             : #include "gpg.h"
      41             : #include "util.h"
      42             : #include "packet.h"
      43             : #include "filter.h"
      44             : #include "main.h"
      45             : #include "options.h"
      46             : 
      47             : 
      48             : #ifdef __riscos__
      49             : #define BYTEF_CAST(a) ((Bytef *)(a))
      50             : #else
      51             : #define BYTEF_CAST(a) (a)
      52             : #endif
      53             : 
      54             : 
      55             : 
      56             : int compress_filter_bz2( void *opaque, int control,
      57             :                          IOBUF a, byte *buf, size_t *ret_len);
      58             : 
      59             : #ifdef HAVE_ZIP
      60             : static void
      61         372 : init_compress( compress_filter_context_t *zfx, z_stream *zs )
      62             : {
      63             :     int rc;
      64             :     int level;
      65             : 
      66             : #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
      67             :     static int zlib_initialized = 0;
      68             : 
      69             :     if (!zlib_initialized)
      70             :         zlib_initialized = riscos_load_module("ZLib", zlib_path, 1);
      71             : #endif
      72             : 
      73         372 :     if( opt.compress_level >= 1 && opt.compress_level <= 9 )
      74           0 :         level = opt.compress_level;
      75         372 :     else if( opt.compress_level == -1 )
      76         372 :         level = Z_DEFAULT_COMPRESSION;
      77             :     else {
      78           0 :         log_error("invalid compression level; using default level\n");
      79           0 :         level = Z_DEFAULT_COMPRESSION;
      80             :     }
      81             : 
      82         744 :     if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
      83             :                                             -13, 8, Z_DEFAULT_STRATEGY)
      84         372 :                             : deflateInit( zs, level )
      85             :                             ) != Z_OK ) {
      86           0 :         log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
      87           0 :                                rc == Z_MEM_ERROR ? "out of core" :
      88           0 :                                rc == Z_VERSION_ERROR ? "invalid lib version" :
      89             :                                                        "unknown error" );
      90             :     }
      91             : 
      92         372 :     zfx->outbufsize = 8192;
      93         372 :     zfx->outbuf = xmalloc( zfx->outbufsize );
      94         372 : }
      95             : 
      96             : static int
      97        2103 : do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
      98             : {
      99             :     int rc;
     100             :     int zrc;
     101             :     unsigned n;
     102             : 
     103             :     do {
     104        2103 :         zs->next_out = BYTEF_CAST (zfx->outbuf);
     105        2103 :         zs->avail_out = zfx->outbufsize;
     106        2103 :         if( DBG_FILTER )
     107           0 :             log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
     108             :                     (unsigned)zs->avail_in, (unsigned)zs->avail_out, flush );
     109        2103 :         zrc = deflate( zs, flush );
     110        2103 :         if( zrc == Z_STREAM_END && flush == Z_FINISH )
     111             :             ;
     112        1731 :         else if( zrc != Z_OK ) {
     113           0 :             if( zs->msg )
     114           0 :                 log_fatal("zlib deflate problem: %s\n", zs->msg );
     115             :             else
     116           0 :                 log_fatal("zlib deflate problem: rc=%d\n", zrc );
     117             :         }
     118        2103 :         n = zfx->outbufsize - zs->avail_out;
     119        2103 :         if( DBG_FILTER )
     120           0 :             log_debug("leave deflate: "
     121             :                       "avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
     122             :                 (unsigned)zs->avail_in, (unsigned)zs->avail_out,
     123             :                                                (unsigned)n, zrc );
     124             : 
     125        2103 :         if( (rc=iobuf_write( a, zfx->outbuf, n )) ) {
     126           0 :             log_debug("deflate: iobuf_write failed\n");
     127           0 :             return rc;
     128             :         }
     129        2103 :     } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
     130        1602 :     return 0;
     131             : }
     132             : 
     133             : static void
     134         423 : init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
     135             : {
     136             :     int rc;
     137             : 
     138             :     /****************
     139             :      * PGP uses a windowsize of 13 bits. Using a negative value for
     140             :      * it forces zlib not to expect a zlib header.  This is a
     141             :      * undocumented feature Peter Gutmann told me about.
     142             :      *
     143             :      * We must use 15 bits for the inflator because CryptoEx uses 15
     144             :      * bits thus the output would get scrambled w/o error indication
     145             :      * if we would use 13 bits.  For the uncompressing this does not
     146             :      * matter at all.
     147             :      */
     148         846 :     if( (rc = zfx->algo == 1? inflateInit2( zs, -15)
     149         423 :                             : inflateInit( zs )) != Z_OK ) {
     150           0 :         log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
     151           0 :                                rc == Z_MEM_ERROR ? "out of core" :
     152           0 :                                rc == Z_VERSION_ERROR ? "invalid lib version" :
     153             :                                                        "unknown error" );
     154             :     }
     155             : 
     156         423 :     zfx->inbufsize = 2048;
     157         423 :     zfx->inbuf = xmalloc( zfx->inbufsize );
     158         423 :     zs->avail_in = 0;
     159         423 : }
     160             : 
     161             : static int
     162        1372 : do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
     163             :                IOBUF a, size_t *ret_len )
     164             : {
     165             :     int zrc;
     166        1372 :     int rc = 0;
     167        1372 :     int leave = 0;
     168             :     size_t n;
     169             :     int nread, count;
     170        1372 :     int refill = !zs->avail_in;
     171             : 
     172        1372 :     if( DBG_FILTER )
     173           0 :         log_debug("begin inflate: avail_in=%u, avail_out=%u, inbuf=%u\n",
     174             :                 (unsigned)zs->avail_in, (unsigned)zs->avail_out,
     175             :                 (unsigned)zfx->inbufsize );
     176             :     do {
     177        5317 :         if( zs->avail_in < zfx->inbufsize && refill ) {
     178        4368 :             n = zs->avail_in;
     179        4368 :             if( !n )
     180        4368 :             zs->next_in = BYTEF_CAST (zfx->inbuf);
     181        4368 :             count = zfx->inbufsize - n;
     182        4368 :             nread = iobuf_read( a, zfx->inbuf + n, count );
     183        4368 :             if( nread == -1 ) nread = 0;
     184        4368 :             n += nread;
     185             :             /* Algo 1 has no zlib header which requires us to to give
     186             :              * inflate an extra dummy byte to read. To be on the safe
     187             :              * side we allow for up to 4 ff bytes.  */
     188        4368 :             if( nread < count && zfx->algo == 1 && zfx->algo1hack < 4) {
     189         260 :                 *(zfx->inbuf + n) = 0xFF;
     190         260 :                 zfx->algo1hack++;
     191         260 :                 n++;
     192         260 :                 leave = 1;
     193             :             }
     194        4368 :             zs->avail_in = n;
     195             :         }
     196        5317 :         refill = 1;
     197        5317 :         if( DBG_FILTER )
     198           0 :             log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
     199             :                     (unsigned)zs->avail_in, (unsigned)zs->avail_out);
     200        5317 :         zrc = inflate ( zs, Z_SYNC_FLUSH );
     201        5317 :         if( DBG_FILTER )
     202           0 :             log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
     203             :                    (unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc);
     204        5317 :         if( zrc == Z_STREAM_END )
     205         423 :             rc = -1; /* eof */
     206        4894 :         else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
     207           0 :             if( zs->msg )
     208           0 :                 log_fatal("zlib inflate problem: %s\n", zs->msg );
     209             :             else
     210           0 :                 log_fatal("zlib inflate problem: rc=%d\n", zrc );
     211             :         }
     212        9685 :     } while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
     213        9262 :              && !leave);
     214             : 
     215        1372 :     *ret_len = zfx->outbufsize - zs->avail_out;
     216        1372 :     if( DBG_FILTER )
     217           0 :         log_debug("do_uncompress: returning %u bytes (%u ignored)\n",
     218           0 :                   (unsigned int)*ret_len, (unsigned int)zs->avail_in );
     219        1372 :     return rc;
     220             : }
     221             : 
     222             : static int
     223        4192 : compress_filter( void *opaque, int control,
     224             :                  IOBUF a, byte *buf, size_t *ret_len)
     225             : {
     226        4192 :     size_t size = *ret_len;
     227        4192 :     compress_filter_context_t *zfx = opaque;
     228        4192 :     z_stream *zs = zfx->opaque;
     229        4192 :     int rc=0;
     230             : 
     231        4192 :     if( control == IOBUFCTRL_UNDERFLOW ) {
     232        1372 :         if( !zfx->status ) {
     233         423 :             zs = zfx->opaque = xmalloc_clear( sizeof *zs );
     234         423 :             init_uncompress( zfx, zs );
     235         423 :             zfx->status = 1;
     236             :         }
     237             : 
     238        1372 :         zs->next_out = BYTEF_CAST (buf);
     239        1372 :         zs->avail_out = size;
     240        1372 :         zfx->outbufsize = size; /* needed only for calculation */
     241        1372 :         rc = do_uncompress( zfx, zs, a, ret_len );
     242             :     }
     243        2820 :     else if( control == IOBUFCTRL_FLUSH ) {
     244        1230 :         if( !zfx->status ) {
     245             :             PACKET pkt;
     246             :             PKT_compressed cd;
     247         372 :             if(zfx->algo != COMPRESS_ALGO_ZIP
     248         149 :                && zfx->algo != COMPRESS_ALGO_ZLIB)
     249           0 :               BUG();
     250         372 :             memset( &cd, 0, sizeof cd );
     251         372 :             cd.len = 0;
     252         372 :             cd.algorithm = zfx->algo;
     253             :             /* Fixme: We should force a new CTB here:
     254             :                cd.new_ctb = zfx->new_ctb;
     255             :             */
     256         372 :             init_packet( &pkt );
     257         372 :             pkt.pkttype = PKT_COMPRESSED;
     258         372 :             pkt.pkt.compressed = &cd;
     259         372 :             if( build_packet( a, &pkt ))
     260           0 :                 log_bug("build_packet(PKT_COMPRESSED) failed\n");
     261         372 :             zs = zfx->opaque = xmalloc_clear( sizeof *zs );
     262         372 :             init_compress( zfx, zs );
     263         372 :             zfx->status = 2;
     264             :         }
     265             : 
     266        1230 :         zs->next_in = BYTEF_CAST (buf);
     267        1230 :         zs->avail_in = size;
     268        1230 :         rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
     269             :     }
     270        1590 :     else if( control == IOBUFCTRL_FREE ) {
     271         795 :         if( zfx->status == 1 ) {
     272         423 :             inflateEnd(zs);
     273         423 :             xfree(zs);
     274         423 :             zfx->opaque = NULL;
     275         423 :             xfree(zfx->outbuf); zfx->outbuf = NULL;
     276             :         }
     277         372 :         else if( zfx->status == 2 ) {
     278         372 :             zs->next_in = BYTEF_CAST (buf);
     279         372 :             zs->avail_in = 0;
     280         372 :             do_compress( zfx, zs, Z_FINISH, a );
     281         372 :             deflateEnd(zs);
     282         372 :             xfree(zs);
     283         372 :             zfx->opaque = NULL;
     284         372 :             xfree(zfx->outbuf); zfx->outbuf = NULL;
     285             :         }
     286         795 :         if (zfx->release)
     287         423 :           zfx->release (zfx);
     288             :     }
     289         795 :     else if( control == IOBUFCTRL_DESC )
     290           0 :         mem2str (buf, "compress_filter", *ret_len);
     291        4192 :     return rc;
     292             : }
     293             : #endif /*HAVE_ZIP*/
     294             : 
     295             : static void
     296         424 : release_context (compress_filter_context_t *ctx)
     297             : {
     298         424 :   xfree(ctx->inbuf);
     299         424 :   ctx->inbuf = NULL;
     300         424 :   xfree(ctx->outbuf);
     301         424 :   ctx->outbuf = NULL;
     302         424 :   xfree (ctx);
     303         424 : }
     304             : 
     305             : /****************
     306             :  * Handle a compressed packet
     307             :  */
     308             : int
     309         424 : handle_compressed (ctrl_t ctrl, void *procctx, PKT_compressed *cd,
     310             :                    int (*callback)(IOBUF, void *), void *passthru )
     311             : {
     312             :     compress_filter_context_t *cfx;
     313             :     int rc;
     314             : 
     315         424 :     if(check_compress_algo(cd->algorithm))
     316           0 :       return GPG_ERR_COMPR_ALGO;
     317         424 :     cfx = xmalloc_clear (sizeof *cfx);
     318         424 :     cfx->release = release_context;
     319         424 :     cfx->algo = cd->algorithm;
     320         424 :     push_compress_filter(cd->buf,cfx,cd->algorithm);
     321         424 :     if( callback )
     322          45 :         rc = callback(cd->buf, passthru );
     323             :     else
     324         379 :       rc = proc_packets (ctrl,procctx, cd->buf);
     325         424 :     cd->buf = NULL;
     326         424 :     return rc;
     327             : }
     328             : 
     329             : void
     330         796 : push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo)
     331             : {
     332         796 :   push_compress_filter2(out,zfx,algo,0);
     333         796 : }
     334             : 
     335             : void
     336         796 : push_compress_filter2(IOBUF out,compress_filter_context_t *zfx,
     337             :                       int algo,int rel)
     338             : {
     339         796 :   if(algo>=0)
     340         796 :     zfx->algo=algo;
     341             :   else
     342           0 :     zfx->algo=DEFAULT_COMPRESS_ALGO;
     343             : 
     344         796 :   switch(zfx->algo)
     345             :     {
     346             :     case COMPRESS_ALGO_NONE:
     347           0 :       break;
     348             : 
     349             : #ifdef HAVE_ZIP
     350             :     case COMPRESS_ALGO_ZIP:
     351             :     case COMPRESS_ALGO_ZLIB:
     352         795 :       iobuf_push_filter2(out,compress_filter,zfx,rel);
     353         795 :       break;
     354             : #endif
     355             : 
     356             : #ifdef HAVE_BZIP2
     357             :     case COMPRESS_ALGO_BZIP2:
     358           1 :       iobuf_push_filter2(out,compress_filter_bz2,zfx,rel);
     359           1 :       break;
     360             : #endif
     361             : 
     362             :     default:
     363           0 :       BUG();
     364             :     }
     365         796 : }

Generated by: LCOV version 1.11