LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-compress.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 144 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 11 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * pgp-compress.c
       3              :  *        ZIP and ZLIB compression via zlib.
       4              :  *
       5              :  * Copyright (c) 2005 Marko Kreen
       6              :  * All rights reserved.
       7              :  *
       8              :  * Redistribution and use in source and binary forms, with or without
       9              :  * modification, are permitted provided that the following conditions
      10              :  * are met:
      11              :  * 1. Redistributions of source code must retain the above copyright
      12              :  *        notice, this list of conditions and the following disclaimer.
      13              :  * 2. Redistributions in binary form must reproduce the above copyright
      14              :  *        notice, this list of conditions and the following disclaimer in the
      15              :  *        documentation and/or other materials provided with the distribution.
      16              :  *
      17              :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18              :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19              :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20              :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21              :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22              :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23              :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24              :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25              :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26              :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27              :  * SUCH DAMAGE.
      28              :  *
      29              :  * contrib/pgcrypto/pgp-compress.c
      30              :  */
      31              : 
      32              : #include "postgres.h"
      33              : 
      34              : #include "pgp.h"
      35              : #include "px.h"
      36              : 
      37              : /*
      38              :  * Compressed pkt writer
      39              :  */
      40              : 
      41              : #ifdef HAVE_LIBZ
      42              : 
      43              : #include <zlib.h>
      44              : 
      45              : #define ZIP_OUT_BUF 8192
      46              : #define ZIP_IN_BLOCK 8192
      47              : 
      48              : struct ZipStat
      49              : {
      50              :         uint8           type;
      51              :         int                     buf_len;
      52              :         int                     hdr_done;
      53              :         z_stream        stream;
      54              :         uint8           buf[ZIP_OUT_BUF];
      55              : };
      56              : 
      57              : static void *
      58            0 : z_alloc(void *priv, unsigned n_items, unsigned item_len)
      59              : {
      60            0 :         return palloc(n_items * item_len);
      61              : }
      62              : 
      63              : static void
      64            0 : z_free(void *priv, void *addr)
      65              : {
      66            0 :         pfree(addr);
      67            0 : }
      68              : 
      69              : static int
      70            0 : compress_init(PushFilter *next, void *init_arg, void **priv_p)
      71              : {
      72            0 :         int                     res;
      73            0 :         struct ZipStat *st;
      74            0 :         PGP_Context *ctx = init_arg;
      75            0 :         uint8           type = ctx->compress_algo;
      76              : 
      77            0 :         if (type != PGP_COMPR_ZLIB && type != PGP_COMPR_ZIP)
      78            0 :                 return PXE_PGP_UNSUPPORTED_COMPR;
      79              : 
      80              :         /*
      81              :          * init
      82              :          */
      83            0 :         st = palloc0_object(struct ZipStat);
      84            0 :         st->buf_len = ZIP_OUT_BUF;
      85            0 :         st->stream.zalloc = z_alloc;
      86            0 :         st->stream.zfree = z_free;
      87              : 
      88            0 :         if (type == PGP_COMPR_ZIP)
      89            0 :                 res = deflateInit2(&st->stream, ctx->compress_level,
      90              :                                                    Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
      91              :         else
      92            0 :                 res = deflateInit(&st->stream, ctx->compress_level);
      93            0 :         if (res != Z_OK)
      94              :         {
      95            0 :                 pfree(st);
      96            0 :                 return PXE_PGP_COMPRESSION_ERROR;
      97              :         }
      98            0 :         *priv_p = st;
      99              : 
     100            0 :         return ZIP_IN_BLOCK;
     101            0 : }
     102              : 
     103              : /* writes compressed data packet */
     104              : 
     105              : /* can handle zero-len incoming data, but shouldn't */
     106              : static int
     107            0 : compress_process(PushFilter *next, void *priv, const uint8 *data, int len)
     108              : {
     109            0 :         int                     res,
     110              :                                 n_out;
     111            0 :         struct ZipStat *st = priv;
     112              : 
     113              :         /*
     114              :          * process data
     115              :          */
     116            0 :         st->stream.next_in = data;
     117            0 :         st->stream.avail_in = len;
     118            0 :         while (st->stream.avail_in > 0)
     119              :         {
     120            0 :                 st->stream.next_out = st->buf;
     121            0 :                 st->stream.avail_out = st->buf_len;
     122            0 :                 res = deflate(&st->stream, Z_NO_FLUSH);
     123            0 :                 if (res != Z_OK)
     124            0 :                         return PXE_PGP_COMPRESSION_ERROR;
     125              : 
     126            0 :                 n_out = st->buf_len - st->stream.avail_out;
     127            0 :                 if (n_out > 0)
     128              :                 {
     129            0 :                         res = pushf_write(next, st->buf, n_out);
     130            0 :                         if (res < 0)
     131            0 :                                 return res;
     132            0 :                 }
     133              :         }
     134              : 
     135            0 :         return 0;
     136            0 : }
     137              : 
     138              : static int
     139            0 : compress_flush(PushFilter *next, void *priv)
     140              : {
     141            0 :         int                     res,
     142              :                                 zres,
     143              :                                 n_out;
     144            0 :         struct ZipStat *st = priv;
     145              : 
     146            0 :         st->stream.next_in = NULL;
     147            0 :         st->stream.avail_in = 0;
     148            0 :         while (1)
     149              :         {
     150            0 :                 st->stream.next_out = st->buf;
     151            0 :                 st->stream.avail_out = st->buf_len;
     152            0 :                 zres = deflate(&st->stream, Z_FINISH);
     153            0 :                 if (zres != Z_STREAM_END && zres != Z_OK)
     154            0 :                         return PXE_PGP_COMPRESSION_ERROR;
     155              : 
     156            0 :                 n_out = st->buf_len - st->stream.avail_out;
     157            0 :                 if (n_out > 0)
     158              :                 {
     159            0 :                         res = pushf_write(next, st->buf, n_out);
     160            0 :                         if (res < 0)
     161            0 :                                 return res;
     162            0 :                 }
     163            0 :                 if (zres == Z_STREAM_END)
     164            0 :                         break;
     165              :         }
     166            0 :         return 0;
     167            0 : }
     168              : 
     169              : static void
     170            0 : compress_free(void *priv)
     171              : {
     172            0 :         struct ZipStat *st = priv;
     173              : 
     174            0 :         deflateEnd(&st->stream);
     175            0 :         px_memset(st, 0, sizeof(*st));
     176            0 :         pfree(st);
     177            0 : }
     178              : 
     179              : static const PushFilterOps
     180              :                         compress_filter = {
     181              :         compress_init, compress_process, compress_flush, compress_free
     182              : };
     183              : 
     184              : int
     185            0 : pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
     186              : {
     187            0 :         return pushf_create(res, &compress_filter, ctx, dst);
     188              : }
     189              : 
     190              : /*
     191              :  * Decompress
     192              :  */
     193              : struct DecomprData
     194              : {
     195              :         int                     buf_len;                /* = ZIP_OUT_BUF */
     196              :         int                     buf_data;               /* available data */
     197              :         uint8      *pos;
     198              :         z_stream        stream;
     199              :         int                     eof;
     200              :         uint8           buf[ZIP_OUT_BUF];
     201              : };
     202              : 
     203              : static int
     204            0 : decompress_init(void **priv_p, void *arg, PullFilter *src)
     205              : {
     206            0 :         PGP_Context *ctx = arg;
     207            0 :         struct DecomprData *dec;
     208            0 :         int                     res;
     209              : 
     210            0 :         if (ctx->compress_algo != PGP_COMPR_ZLIB
     211            0 :                 && ctx->compress_algo != PGP_COMPR_ZIP)
     212            0 :                 return PXE_PGP_UNSUPPORTED_COMPR;
     213              : 
     214            0 :         dec = palloc0_object(struct DecomprData);
     215            0 :         dec->buf_len = ZIP_OUT_BUF;
     216            0 :         *priv_p = dec;
     217              : 
     218            0 :         dec->stream.zalloc = z_alloc;
     219            0 :         dec->stream.zfree = z_free;
     220              : 
     221            0 :         if (ctx->compress_algo == PGP_COMPR_ZIP)
     222            0 :                 res = inflateInit2(&dec->stream, -15);
     223              :         else
     224            0 :                 res = inflateInit(&dec->stream);
     225            0 :         if (res != Z_OK)
     226              :         {
     227            0 :                 pfree(dec);
     228            0 :                 px_debug("decompress_init: inflateInit error");
     229            0 :                 return PXE_PGP_COMPRESSION_ERROR;
     230              :         }
     231              : 
     232            0 :         return 0;
     233            0 : }
     234              : 
     235              : static int
     236            0 : decompress_read(void *priv, PullFilter *src, int len,
     237              :                                 uint8 **data_p, uint8 *buf, int buflen)
     238              : {
     239            0 :         int                     res;
     240            0 :         int                     flush;
     241            0 :         struct DecomprData *dec = priv;
     242              : 
     243              : restart:
     244            0 :         if (dec->buf_data > 0)
     245              :         {
     246            0 :                 if (len > dec->buf_data)
     247            0 :                         len = dec->buf_data;
     248            0 :                 *data_p = dec->pos;
     249            0 :                 dec->pos += len;
     250            0 :                 dec->buf_data -= len;
     251            0 :                 return len;
     252              :         }
     253              : 
     254            0 :         if (dec->eof)
     255            0 :                 return 0;
     256              : 
     257            0 :         if (dec->stream.avail_in == 0)
     258              :         {
     259            0 :                 uint8      *tmp;
     260              : 
     261            0 :                 res = pullf_read(src, 8192, &tmp);
     262            0 :                 if (res < 0)
     263            0 :                         return res;
     264            0 :                 dec->stream.next_in = tmp;
     265            0 :                 dec->stream.avail_in = res;
     266            0 :         }
     267              : 
     268            0 :         dec->stream.next_out = dec->buf;
     269            0 :         dec->stream.avail_out = dec->buf_len;
     270            0 :         dec->pos = dec->buf;
     271              : 
     272              :         /*
     273              :          * Z_SYNC_FLUSH is tell zlib to output as much as possible. It should do
     274              :          * it anyway (Z_NO_FLUSH), but seems to reserve the right not to.  So lets
     275              :          * follow the API.
     276              :          */
     277            0 :         flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH;
     278            0 :         res = inflate(&dec->stream, flush);
     279            0 :         if (res != Z_OK && res != Z_STREAM_END)
     280              :         {
     281            0 :                 px_debug("decompress_read: inflate error: %d", res);
     282            0 :                 return PXE_PGP_CORRUPT_DATA;
     283              :         }
     284              : 
     285            0 :         dec->buf_data = dec->buf_len - dec->stream.avail_out;
     286            0 :         if (res == Z_STREAM_END)
     287              :         {
     288            0 :                 uint8      *tmp;
     289              : 
     290              :                 /*
     291              :                  * A stream must be terminated by a normal packet.  If the last stream
     292              :                  * packet in the source stream is a full packet, a normal empty packet
     293              :                  * must follow.  Since the underlying packet reader doesn't know that
     294              :                  * the compressed stream has been ended, we need to consume the
     295              :                  * terminating packet here.  This read does not harm even if the
     296              :                  * stream has already ended.
     297              :                  */
     298            0 :                 res = pullf_read(src, 1, &tmp);
     299              : 
     300            0 :                 if (res < 0)
     301            0 :                         return res;
     302            0 :                 else if (res > 0)
     303              :                 {
     304            0 :                         px_debug("decompress_read: extra bytes after end of stream");
     305            0 :                         return PXE_PGP_CORRUPT_DATA;
     306              :                 }
     307            0 :                 dec->eof = 1;
     308            0 :         }
     309            0 :         goto restart;
     310            0 : }
     311              : 
     312              : static void
     313            0 : decompress_free(void *priv)
     314              : {
     315            0 :         struct DecomprData *dec = priv;
     316              : 
     317            0 :         inflateEnd(&dec->stream);
     318            0 :         px_memset(dec, 0, sizeof(*dec));
     319            0 :         pfree(dec);
     320            0 : }
     321              : 
     322              : static const PullFilterOps
     323              :                         decompress_filter = {
     324              :         decompress_init, decompress_read, decompress_free
     325              : };
     326              : 
     327              : int
     328            0 : pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
     329              : {
     330            0 :         return pullf_create(res, &decompress_filter, ctx, src);
     331              : }
     332              : #else                                                   /* !HAVE_LIBZ */
     333              : 
     334              : int
     335              : pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
     336              : {
     337              :         return PXE_PGP_UNSUPPORTED_COMPR;
     338              : }
     339              : 
     340              : int
     341              : pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
     342              : {
     343              :         return PXE_PGP_UNSUPPORTED_COMPR;
     344              : }
     345              : 
     346              : #endif
        

Generated by: LCOV version 2.3.2-1