/src/openssl111/crypto/comp/c_zlib.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * | 
| 4 |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
| 5 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 6 |  |  * in the file LICENSE in the source distribution or at | 
| 7 |  |  * https://www.openssl.org/source/license.html | 
| 8 |  |  */ | 
| 9 |  |  | 
| 10 |  | #include <stdio.h> | 
| 11 |  | #include <stdlib.h> | 
| 12 |  | #include <string.h> | 
| 13 |  | #include <openssl/objects.h> | 
| 14 |  | #include "internal/comp.h" | 
| 15 |  | #include <openssl/err.h> | 
| 16 |  | #include "crypto/cryptlib.h" | 
| 17 |  | #include "internal/bio.h" | 
| 18 |  | #include "comp_local.h" | 
| 19 |  |  | 
| 20 |  | COMP_METHOD *COMP_zlib(void); | 
| 21 |  |  | 
| 22 |  | static COMP_METHOD zlib_method_nozlib = { | 
| 23 |  |     NID_undef, | 
| 24 |  |     "(undef)", | 
| 25 |  |     NULL, | 
| 26 |  |     NULL, | 
| 27 |  |     NULL, | 
| 28 |  |     NULL, | 
| 29 |  | }; | 
| 30 |  |  | 
| 31 |  | #ifndef ZLIB | 
| 32 |  | # undef ZLIB_SHARED | 
| 33 |  | #else | 
| 34 |  |  | 
| 35 |  | # include <zlib.h> | 
| 36 |  |  | 
| 37 |  | static int zlib_stateful_init(COMP_CTX *ctx); | 
| 38 |  | static void zlib_stateful_finish(COMP_CTX *ctx); | 
| 39 |  | static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, | 
| 40 |  |                                         unsigned int olen, unsigned char *in, | 
| 41 |  |                                         unsigned int ilen); | 
| 42 |  | static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, | 
| 43 |  |                                       unsigned int olen, unsigned char *in, | 
| 44 |  |                                       unsigned int ilen); | 
| 45 |  |  | 
| 46 |  | /* memory allocations functions for zlib initialisation */ | 
| 47 |  | static void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size) | 
| 48 |  | { | 
| 49 |  |     void *p; | 
| 50 |  |  | 
| 51 |  |     p = OPENSSL_zalloc(no * size); | 
| 52 |  |     return p; | 
| 53 |  | } | 
| 54 |  |  | 
| 55 |  | static void zlib_zfree(void *opaque, void *address) | 
| 56 |  | { | 
| 57 |  |     OPENSSL_free(address); | 
| 58 |  | } | 
| 59 |  |  | 
| 60 |  |  | 
| 61 |  | static COMP_METHOD zlib_stateful_method = { | 
| 62 |  |     NID_zlib_compression, | 
| 63 |  |     LN_zlib_compression, | 
| 64 |  |     zlib_stateful_init, | 
| 65 |  |     zlib_stateful_finish, | 
| 66 |  |     zlib_stateful_compress_block, | 
| 67 |  |     zlib_stateful_expand_block | 
| 68 |  | }; | 
| 69 |  |  | 
| 70 |  | /* | 
| 71 |  |  * When OpenSSL is built on Windows, we do not want to require that | 
| 72 |  |  * the ZLIB.DLL be available in order for the OpenSSL DLLs to | 
| 73 |  |  * work.  Therefore, all ZLIB routines are loaded at run time | 
| 74 |  |  * and we do not link to a .LIB file when ZLIB_SHARED is set. | 
| 75 |  |  */ | 
| 76 |  | # if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) | 
| 77 |  | #  include <windows.h> | 
| 78 |  | # endif                         /* !(OPENSSL_SYS_WINDOWS || | 
| 79 |  |                                  * OPENSSL_SYS_WIN32) */ | 
| 80 |  |  | 
| 81 |  | # ifdef ZLIB_SHARED | 
| 82 |  | #  include "internal/dso.h" | 
| 83 |  |  | 
| 84 |  | /* Function pointers */ | 
| 85 |  | typedef int (*compress_ft) (Bytef *dest, uLongf * destLen, | 
| 86 |  |                             const Bytef *source, uLong sourceLen); | 
| 87 |  | typedef int (*inflateEnd_ft) (z_streamp strm); | 
| 88 |  | typedef int (*inflate_ft) (z_streamp strm, int flush); | 
| 89 |  | typedef int (*inflateInit__ft) (z_streamp strm, | 
| 90 |  |                                 const char *version, int stream_size); | 
| 91 |  | typedef int (*deflateEnd_ft) (z_streamp strm); | 
| 92 |  | typedef int (*deflate_ft) (z_streamp strm, int flush); | 
| 93 |  | typedef int (*deflateInit__ft) (z_streamp strm, int level, | 
| 94 |  |                                 const char *version, int stream_size); | 
| 95 |  | typedef const char *(*zError__ft) (int err); | 
| 96 |  | static compress_ft p_compress = NULL; | 
| 97 |  | static inflateEnd_ft p_inflateEnd = NULL; | 
| 98 |  | static inflate_ft p_inflate = NULL; | 
| 99 |  | static inflateInit__ft p_inflateInit_ = NULL; | 
| 100 |  | static deflateEnd_ft p_deflateEnd = NULL; | 
| 101 |  | static deflate_ft p_deflate = NULL; | 
| 102 |  | static deflateInit__ft p_deflateInit_ = NULL; | 
| 103 |  | static zError__ft p_zError = NULL; | 
| 104 |  |  | 
| 105 |  | static int zlib_loaded = 0;     /* only attempt to init func pts once */ | 
| 106 |  | static DSO *zlib_dso = NULL; | 
| 107 |  |  | 
| 108 |  | #  define compress                p_compress | 
| 109 |  | #  define inflateEnd              p_inflateEnd | 
| 110 |  | #  define inflate                 p_inflate | 
| 111 |  | #  define inflateInit_            p_inflateInit_ | 
| 112 |  | #  define deflateEnd              p_deflateEnd | 
| 113 |  | #  define deflate                 p_deflate | 
| 114 |  | #  define deflateInit_            p_deflateInit_ | 
| 115 |  | #  define zError                  p_zError | 
| 116 |  | # endif                         /* ZLIB_SHARED */ | 
| 117 |  |  | 
| 118 |  | struct zlib_state { | 
| 119 |  |     z_stream istream; | 
| 120 |  |     z_stream ostream; | 
| 121 |  | }; | 
| 122 |  |  | 
| 123 |  | static int zlib_stateful_init(COMP_CTX *ctx) | 
| 124 |  | { | 
| 125 |  |     int err; | 
| 126 |  |     struct zlib_state *state = OPENSSL_zalloc(sizeof(*state)); | 
| 127 |  |  | 
| 128 |  |     if (state == NULL) | 
| 129 |  |         goto err; | 
| 130 |  |  | 
| 131 |  |     state->istream.zalloc = zlib_zalloc; | 
| 132 |  |     state->istream.zfree = zlib_zfree; | 
| 133 |  |     state->istream.opaque = Z_NULL; | 
| 134 |  |     state->istream.next_in = Z_NULL; | 
| 135 |  |     state->istream.next_out = Z_NULL; | 
| 136 |  |     err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); | 
| 137 |  |     if (err != Z_OK) | 
| 138 |  |         goto err; | 
| 139 |  |  | 
| 140 |  |     state->ostream.zalloc = zlib_zalloc; | 
| 141 |  |     state->ostream.zfree = zlib_zfree; | 
| 142 |  |     state->ostream.opaque = Z_NULL; | 
| 143 |  |     state->ostream.next_in = Z_NULL; | 
| 144 |  |     state->ostream.next_out = Z_NULL; | 
| 145 |  |     err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, | 
| 146 |  |                        ZLIB_VERSION, sizeof(z_stream)); | 
| 147 |  |     if (err != Z_OK) | 
| 148 |  |         goto err; | 
| 149 |  |  | 
| 150 |  |     ctx->data = state; | 
| 151 |  |     return 1; | 
| 152 |  |  err: | 
| 153 |  |     OPENSSL_free(state); | 
| 154 |  |     return 0; | 
| 155 |  | } | 
| 156 |  |  | 
| 157 |  | static void zlib_stateful_finish(COMP_CTX *ctx) | 
| 158 |  | { | 
| 159 |  |     struct zlib_state *state = ctx->data; | 
| 160 |  |     inflateEnd(&state->istream); | 
| 161 |  |     deflateEnd(&state->ostream); | 
| 162 |  |     OPENSSL_free(state); | 
| 163 |  | } | 
| 164 |  |  | 
| 165 |  | static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, | 
| 166 |  |                                         unsigned int olen, unsigned char *in, | 
| 167 |  |                                         unsigned int ilen) | 
| 168 |  | { | 
| 169 |  |     int err = Z_OK; | 
| 170 |  |     struct zlib_state *state = ctx->data; | 
| 171 |  |  | 
| 172 |  |     if (state == NULL) | 
| 173 |  |         return -1; | 
| 174 |  |  | 
| 175 |  |     state->ostream.next_in = in; | 
| 176 |  |     state->ostream.avail_in = ilen; | 
| 177 |  |     state->ostream.next_out = out; | 
| 178 |  |     state->ostream.avail_out = olen; | 
| 179 |  |     if (ilen > 0) | 
| 180 |  |         err = deflate(&state->ostream, Z_SYNC_FLUSH); | 
| 181 |  |     if (err != Z_OK) | 
| 182 |  |         return -1; | 
| 183 |  |     return olen - state->ostream.avail_out; | 
| 184 |  | } | 
| 185 |  |  | 
| 186 |  | static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, | 
| 187 |  |                                       unsigned int olen, unsigned char *in, | 
| 188 |  |                                       unsigned int ilen) | 
| 189 |  | { | 
| 190 |  |     int err = Z_OK; | 
| 191 |  |     struct zlib_state *state = ctx->data; | 
| 192 |  |  | 
| 193 |  |     if (state == NULL) | 
| 194 |  |         return 0; | 
| 195 |  |  | 
| 196 |  |     state->istream.next_in = in; | 
| 197 |  |     state->istream.avail_in = ilen; | 
| 198 |  |     state->istream.next_out = out; | 
| 199 |  |     state->istream.avail_out = olen; | 
| 200 |  |     if (ilen > 0) | 
| 201 |  |         err = inflate(&state->istream, Z_SYNC_FLUSH); | 
| 202 |  |     if (err != Z_OK) | 
| 203 |  |         return -1; | 
| 204 |  |     return olen - state->istream.avail_out; | 
| 205 |  | } | 
| 206 |  |  | 
| 207 |  | #endif | 
| 208 |  |  | 
| 209 |  | COMP_METHOD *COMP_zlib(void) | 
| 210 | 18 | { | 
| 211 | 18 |     COMP_METHOD *meth = &zlib_method_nozlib; | 
| 212 |  |  | 
| 213 |  | #ifdef ZLIB_SHARED | 
| 214 |  |     /* LIBZ may be externally defined, and we should respect that value */ | 
| 215 |  | # ifndef LIBZ | 
| 216 |  | #  if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) | 
| 217 |  | #   define LIBZ "ZLIB1" | 
| 218 |  | #  elif defined(OPENSSL_SYS_VMS) | 
| 219 |  | #   define LIBZ "LIBZ" | 
| 220 |  | #  else | 
| 221 |  | #   define LIBZ "z" | 
| 222 |  | #  endif | 
| 223 |  | # endif | 
| 224 |  |  | 
| 225 |  |     if (!zlib_loaded) { | 
| 226 |  |         zlib_dso = DSO_load(NULL, LIBZ, NULL, 0); | 
| 227 |  |         if (zlib_dso != NULL) { | 
| 228 |  |             p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); | 
| 229 |  |             p_inflateEnd | 
| 230 |  |                 = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); | 
| 231 |  |             p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); | 
| 232 |  |             p_inflateInit_ | 
| 233 |  |                 = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); | 
| 234 |  |             p_deflateEnd | 
| 235 |  |                 = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd"); | 
| 236 |  |             p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate"); | 
| 237 |  |             p_deflateInit_ | 
| 238 |  |                 = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); | 
| 239 |  |             p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); | 
| 240 |  |  | 
| 241 |  |             if (p_compress && p_inflateEnd && p_inflate | 
| 242 |  |                 && p_inflateInit_ && p_deflateEnd | 
| 243 |  |                 && p_deflate && p_deflateInit_ && p_zError) | 
| 244 |  |                 zlib_loaded++; | 
| 245 |  |  | 
| 246 |  |             if (!OPENSSL_init_crypto(OPENSSL_INIT_ZLIB, NULL)) { | 
| 247 |  |                 comp_zlib_cleanup_int(); | 
| 248 |  |                 return meth; | 
| 249 |  |             } | 
| 250 |  |             if (zlib_loaded) | 
| 251 |  |                 meth = &zlib_stateful_method; | 
| 252 |  |         } | 
| 253 |  |     } | 
| 254 |  | #endif | 
| 255 |  | #if defined(ZLIB) | 
| 256 |  |     meth = &zlib_stateful_method; | 
| 257 |  | #endif | 
| 258 |  |  | 
| 259 | 18 |     return meth; | 
| 260 | 18 | } | 
| 261 |  |  | 
| 262 |  | void comp_zlib_cleanup_int(void) | 
| 263 | 0 | { | 
| 264 |  | #ifdef ZLIB_SHARED | 
| 265 |  |     DSO_free(zlib_dso); | 
| 266 |  |     zlib_dso = NULL; | 
| 267 |  | #endif | 
| 268 | 0 | } | 
| 269 |  |  | 
| 270 |  | #ifdef ZLIB | 
| 271 |  |  | 
| 272 |  | /* Zlib based compression/decompression filter BIO */ | 
| 273 |  |  | 
| 274 |  | typedef struct { | 
| 275 |  |     unsigned char *ibuf;        /* Input buffer */ | 
| 276 |  |     int ibufsize;               /* Buffer size */ | 
| 277 |  |     z_stream zin;               /* Input decompress context */ | 
| 278 |  |     unsigned char *obuf;        /* Output buffer */ | 
| 279 |  |     int obufsize;               /* Output buffer size */ | 
| 280 |  |     unsigned char *optr;        /* Position in output buffer */ | 
| 281 |  |     int ocount;                 /* Amount of data in output buffer */ | 
| 282 |  |     int odone;                  /* deflate EOF */ | 
| 283 |  |     int comp_level;             /* Compression level to use */ | 
| 284 |  |     z_stream zout;              /* Output compression context */ | 
| 285 |  | } BIO_ZLIB_CTX; | 
| 286 |  |  | 
| 287 |  | # define ZLIB_DEFAULT_BUFSIZE 1024 | 
| 288 |  |  | 
| 289 |  | static int bio_zlib_new(BIO *bi); | 
| 290 |  | static int bio_zlib_free(BIO *bi); | 
| 291 |  | static int bio_zlib_read(BIO *b, char *out, int outl); | 
| 292 |  | static int bio_zlib_write(BIO *b, const char *in, int inl); | 
| 293 |  | static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); | 
| 294 |  | static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); | 
| 295 |  |  | 
| 296 |  | static const BIO_METHOD bio_meth_zlib = { | 
| 297 |  |     BIO_TYPE_COMP, | 
| 298 |  |     "zlib", | 
| 299 |  |     /* TODO: Convert to new style write function */ | 
| 300 |  |     bwrite_conv, | 
| 301 |  |     bio_zlib_write, | 
| 302 |  |     /* TODO: Convert to new style read function */ | 
| 303 |  |     bread_conv, | 
| 304 |  |     bio_zlib_read, | 
| 305 |  |     NULL,                      /* bio_zlib_puts, */ | 
| 306 |  |     NULL,                      /* bio_zlib_gets, */ | 
| 307 |  |     bio_zlib_ctrl, | 
| 308 |  |     bio_zlib_new, | 
| 309 |  |     bio_zlib_free, | 
| 310 |  |     bio_zlib_callback_ctrl | 
| 311 |  | }; | 
| 312 |  |  | 
| 313 |  | const BIO_METHOD *BIO_f_zlib(void) | 
| 314 |  | { | 
| 315 |  |     return &bio_meth_zlib; | 
| 316 |  | } | 
| 317 |  |  | 
| 318 |  | static int bio_zlib_new(BIO *bi) | 
| 319 |  | { | 
| 320 |  |     BIO_ZLIB_CTX *ctx; | 
| 321 |  | # ifdef ZLIB_SHARED | 
| 322 |  |     (void)COMP_zlib(); | 
| 323 |  |     if (!zlib_loaded) { | 
| 324 |  |         COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED); | 
| 325 |  |         return 0; | 
| 326 |  |     } | 
| 327 |  | # endif | 
| 328 |  |     ctx = OPENSSL_zalloc(sizeof(*ctx)); | 
| 329 |  |     if (ctx == NULL) { | 
| 330 |  |         COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); | 
| 331 |  |         return 0; | 
| 332 |  |     } | 
| 333 |  |     ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; | 
| 334 |  |     ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; | 
| 335 |  |     ctx->zin.zalloc = Z_NULL; | 
| 336 |  |     ctx->zin.zfree = Z_NULL; | 
| 337 |  |     ctx->zout.zalloc = Z_NULL; | 
| 338 |  |     ctx->zout.zfree = Z_NULL; | 
| 339 |  |     ctx->comp_level = Z_DEFAULT_COMPRESSION; | 
| 340 |  |     BIO_set_init(bi, 1); | 
| 341 |  |     BIO_set_data(bi, ctx); | 
| 342 |  |  | 
| 343 |  |     return 1; | 
| 344 |  | } | 
| 345 |  |  | 
| 346 |  | static int bio_zlib_free(BIO *bi) | 
| 347 |  | { | 
| 348 |  |     BIO_ZLIB_CTX *ctx; | 
| 349 |  |     if (!bi) | 
| 350 |  |         return 0; | 
| 351 |  |     ctx = BIO_get_data(bi); | 
| 352 |  |     if (ctx->ibuf) { | 
| 353 |  |         /* Destroy decompress context */ | 
| 354 |  |         inflateEnd(&ctx->zin); | 
| 355 |  |         OPENSSL_free(ctx->ibuf); | 
| 356 |  |     } | 
| 357 |  |     if (ctx->obuf) { | 
| 358 |  |         /* Destroy compress context */ | 
| 359 |  |         deflateEnd(&ctx->zout); | 
| 360 |  |         OPENSSL_free(ctx->obuf); | 
| 361 |  |     } | 
| 362 |  |     OPENSSL_free(ctx); | 
| 363 |  |     BIO_set_data(bi, NULL); | 
| 364 |  |     BIO_set_init(bi, 0); | 
| 365 |  |  | 
| 366 |  |     return 1; | 
| 367 |  | } | 
| 368 |  |  | 
| 369 |  | static int bio_zlib_read(BIO *b, char *out, int outl) | 
| 370 |  | { | 
| 371 |  |     BIO_ZLIB_CTX *ctx; | 
| 372 |  |     int ret; | 
| 373 |  |     z_stream *zin; | 
| 374 |  |     BIO *next = BIO_next(b); | 
| 375 |  |  | 
| 376 |  |     if (!out || !outl) | 
| 377 |  |         return 0; | 
| 378 |  |     ctx = BIO_get_data(b); | 
| 379 |  |     zin = &ctx->zin; | 
| 380 |  |     BIO_clear_retry_flags(b); | 
| 381 |  |     if (!ctx->ibuf) { | 
| 382 |  |         ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); | 
| 383 |  |         if (ctx->ibuf == NULL) { | 
| 384 |  |             COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); | 
| 385 |  |             return 0; | 
| 386 |  |         } | 
| 387 |  |         inflateInit(zin); | 
| 388 |  |         zin->next_in = ctx->ibuf; | 
| 389 |  |         zin->avail_in = 0; | 
| 390 |  |     } | 
| 391 |  |  | 
| 392 |  |     /* Copy output data directly to supplied buffer */ | 
| 393 |  |     zin->next_out = (unsigned char *)out; | 
| 394 |  |     zin->avail_out = (unsigned int)outl; | 
| 395 |  |     for (;;) { | 
| 396 |  |         /* Decompress while data available */ | 
| 397 |  |         while (zin->avail_in) { | 
| 398 |  |             ret = inflate(zin, 0); | 
| 399 |  |             if ((ret != Z_OK) && (ret != Z_STREAM_END)) { | 
| 400 |  |                 COMPerr(COMP_F_BIO_ZLIB_READ, COMP_R_ZLIB_INFLATE_ERROR); | 
| 401 |  |                 ERR_add_error_data(2, "zlib error:", zError(ret)); | 
| 402 |  |                 return 0; | 
| 403 |  |             } | 
| 404 |  |             /* If EOF or we've read everything then return */ | 
| 405 |  |             if ((ret == Z_STREAM_END) || !zin->avail_out) | 
| 406 |  |                 return outl - zin->avail_out; | 
| 407 |  |         } | 
| 408 |  |  | 
| 409 |  |         /* | 
| 410 |  |          * No data in input buffer try to read some in, if an error then | 
| 411 |  |          * return the total data read. | 
| 412 |  |          */ | 
| 413 |  |         ret = BIO_read(next, ctx->ibuf, ctx->ibufsize); | 
| 414 |  |         if (ret <= 0) { | 
| 415 |  |             /* Total data read */ | 
| 416 |  |             int tot = outl - zin->avail_out; | 
| 417 |  |             BIO_copy_next_retry(b); | 
| 418 |  |             if (ret < 0) | 
| 419 |  |                 return (tot > 0) ? tot : ret; | 
| 420 |  |             return tot; | 
| 421 |  |         } | 
| 422 |  |         zin->avail_in = ret; | 
| 423 |  |         zin->next_in = ctx->ibuf; | 
| 424 |  |     } | 
| 425 |  | } | 
| 426 |  |  | 
| 427 |  | static int bio_zlib_write(BIO *b, const char *in, int inl) | 
| 428 |  | { | 
| 429 |  |     BIO_ZLIB_CTX *ctx; | 
| 430 |  |     int ret; | 
| 431 |  |     z_stream *zout; | 
| 432 |  |     BIO *next = BIO_next(b); | 
| 433 |  |  | 
| 434 |  |     if (!in || !inl) | 
| 435 |  |         return 0; | 
| 436 |  |     ctx = BIO_get_data(b); | 
| 437 |  |     if (ctx->odone) | 
| 438 |  |         return 0; | 
| 439 |  |     zout = &ctx->zout; | 
| 440 |  |     BIO_clear_retry_flags(b); | 
| 441 |  |     if (!ctx->obuf) { | 
| 442 |  |         ctx->obuf = OPENSSL_malloc(ctx->obufsize); | 
| 443 |  |         /* Need error here */ | 
| 444 |  |         if (ctx->obuf == NULL) { | 
| 445 |  |             COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); | 
| 446 |  |             return 0; | 
| 447 |  |         } | 
| 448 |  |         ctx->optr = ctx->obuf; | 
| 449 |  |         ctx->ocount = 0; | 
| 450 |  |         deflateInit(zout, ctx->comp_level); | 
| 451 |  |         zout->next_out = ctx->obuf; | 
| 452 |  |         zout->avail_out = ctx->obufsize; | 
| 453 |  |     } | 
| 454 |  |     /* Obtain input data directly from supplied buffer */ | 
| 455 |  |     zout->next_in = (void *)in; | 
| 456 |  |     zout->avail_in = inl; | 
| 457 |  |     for (;;) { | 
| 458 |  |         /* If data in output buffer write it first */ | 
| 459 |  |         while (ctx->ocount) { | 
| 460 |  |             ret = BIO_write(next, ctx->optr, ctx->ocount); | 
| 461 |  |             if (ret <= 0) { | 
| 462 |  |                 /* Total data written */ | 
| 463 |  |                 int tot = inl - zout->avail_in; | 
| 464 |  |                 BIO_copy_next_retry(b); | 
| 465 |  |                 if (ret < 0) | 
| 466 |  |                     return (tot > 0) ? tot : ret; | 
| 467 |  |                 return tot; | 
| 468 |  |             } | 
| 469 |  |             ctx->optr += ret; | 
| 470 |  |             ctx->ocount -= ret; | 
| 471 |  |         } | 
| 472 |  |  | 
| 473 |  |         /* Have we consumed all supplied data? */ | 
| 474 |  |         if (!zout->avail_in) | 
| 475 |  |             return inl; | 
| 476 |  |  | 
| 477 |  |         /* Compress some more */ | 
| 478 |  |  | 
| 479 |  |         /* Reset buffer */ | 
| 480 |  |         ctx->optr = ctx->obuf; | 
| 481 |  |         zout->next_out = ctx->obuf; | 
| 482 |  |         zout->avail_out = ctx->obufsize; | 
| 483 |  |         /* Compress some more */ | 
| 484 |  |         ret = deflate(zout, 0); | 
| 485 |  |         if (ret != Z_OK) { | 
| 486 |  |             COMPerr(COMP_F_BIO_ZLIB_WRITE, COMP_R_ZLIB_DEFLATE_ERROR); | 
| 487 |  |             ERR_add_error_data(2, "zlib error:", zError(ret)); | 
| 488 |  |             return 0; | 
| 489 |  |         } | 
| 490 |  |         ctx->ocount = ctx->obufsize - zout->avail_out; | 
| 491 |  |     } | 
| 492 |  | } | 
| 493 |  |  | 
| 494 |  | static int bio_zlib_flush(BIO *b) | 
| 495 |  | { | 
| 496 |  |     BIO_ZLIB_CTX *ctx; | 
| 497 |  |     int ret; | 
| 498 |  |     z_stream *zout; | 
| 499 |  |     BIO *next = BIO_next(b); | 
| 500 |  |  | 
| 501 |  |     ctx = BIO_get_data(b); | 
| 502 |  |     /* If no data written or already flush show success */ | 
| 503 |  |     if (!ctx->obuf || (ctx->odone && !ctx->ocount)) | 
| 504 |  |         return 1; | 
| 505 |  |     zout = &ctx->zout; | 
| 506 |  |     BIO_clear_retry_flags(b); | 
| 507 |  |     /* No more input data */ | 
| 508 |  |     zout->next_in = NULL; | 
| 509 |  |     zout->avail_in = 0; | 
| 510 |  |     for (;;) { | 
| 511 |  |         /* If data in output buffer write it first */ | 
| 512 |  |         while (ctx->ocount) { | 
| 513 |  |             ret = BIO_write(next, ctx->optr, ctx->ocount); | 
| 514 |  |             if (ret <= 0) { | 
| 515 |  |                 BIO_copy_next_retry(b); | 
| 516 |  |                 return ret; | 
| 517 |  |             } | 
| 518 |  |             ctx->optr += ret; | 
| 519 |  |             ctx->ocount -= ret; | 
| 520 |  |         } | 
| 521 |  |         if (ctx->odone) | 
| 522 |  |             return 1; | 
| 523 |  |  | 
| 524 |  |         /* Compress some more */ | 
| 525 |  |  | 
| 526 |  |         /* Reset buffer */ | 
| 527 |  |         ctx->optr = ctx->obuf; | 
| 528 |  |         zout->next_out = ctx->obuf; | 
| 529 |  |         zout->avail_out = ctx->obufsize; | 
| 530 |  |         /* Compress some more */ | 
| 531 |  |         ret = deflate(zout, Z_FINISH); | 
| 532 |  |         if (ret == Z_STREAM_END) | 
| 533 |  |             ctx->odone = 1; | 
| 534 |  |         else if (ret != Z_OK) { | 
| 535 |  |             COMPerr(COMP_F_BIO_ZLIB_FLUSH, COMP_R_ZLIB_DEFLATE_ERROR); | 
| 536 |  |             ERR_add_error_data(2, "zlib error:", zError(ret)); | 
| 537 |  |             return 0; | 
| 538 |  |         } | 
| 539 |  |         ctx->ocount = ctx->obufsize - zout->avail_out; | 
| 540 |  |     } | 
| 541 |  | } | 
| 542 |  |  | 
| 543 |  | static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) | 
| 544 |  | { | 
| 545 |  |     BIO_ZLIB_CTX *ctx; | 
| 546 |  |     int ret, *ip; | 
| 547 |  |     int ibs, obs; | 
| 548 |  |     BIO *next = BIO_next(b); | 
| 549 |  |  | 
| 550 |  |     if (next == NULL) | 
| 551 |  |         return 0; | 
| 552 |  |     ctx = BIO_get_data(b); | 
| 553 |  |     switch (cmd) { | 
| 554 |  |  | 
| 555 |  |     case BIO_CTRL_RESET: | 
| 556 |  |         ctx->ocount = 0; | 
| 557 |  |         ctx->odone = 0; | 
| 558 |  |         ret = 1; | 
| 559 |  |         break; | 
| 560 |  |  | 
| 561 |  |     case BIO_CTRL_FLUSH: | 
| 562 |  |         ret = bio_zlib_flush(b); | 
| 563 |  |         if (ret > 0) | 
| 564 |  |             ret = BIO_flush(next); | 
| 565 |  |         break; | 
| 566 |  |  | 
| 567 |  |     case BIO_C_SET_BUFF_SIZE: | 
| 568 |  |         ibs = -1; | 
| 569 |  |         obs = -1; | 
| 570 |  |         if (ptr != NULL) { | 
| 571 |  |             ip = ptr; | 
| 572 |  |             if (*ip == 0) | 
| 573 |  |                 ibs = (int)num; | 
| 574 |  |             else | 
| 575 |  |                 obs = (int)num; | 
| 576 |  |         } else { | 
| 577 |  |             ibs = (int)num; | 
| 578 |  |             obs = ibs; | 
| 579 |  |         } | 
| 580 |  |  | 
| 581 |  |         if (ibs != -1) { | 
| 582 |  |             OPENSSL_free(ctx->ibuf); | 
| 583 |  |             ctx->ibuf = NULL; | 
| 584 |  |             ctx->ibufsize = ibs; | 
| 585 |  |         } | 
| 586 |  |  | 
| 587 |  |         if (obs != -1) { | 
| 588 |  |             OPENSSL_free(ctx->obuf); | 
| 589 |  |             ctx->obuf = NULL; | 
| 590 |  |             ctx->obufsize = obs; | 
| 591 |  |         } | 
| 592 |  |         ret = 1; | 
| 593 |  |         break; | 
| 594 |  |  | 
| 595 |  |     case BIO_C_DO_STATE_MACHINE: | 
| 596 |  |         BIO_clear_retry_flags(b); | 
| 597 |  |         ret = BIO_ctrl(next, cmd, num, ptr); | 
| 598 |  |         BIO_copy_next_retry(b); | 
| 599 |  |         break; | 
| 600 |  |  | 
| 601 |  |     case BIO_CTRL_WPENDING: | 
| 602 |  |         if (ctx->obuf == NULL) | 
| 603 |  |             return 0; | 
| 604 |  |  | 
| 605 |  |         if (ctx->odone) { | 
| 606 |  |             ret = ctx->ocount; | 
| 607 |  |         } else { | 
| 608 |  |             ret = ctx->ocount; | 
| 609 |  |             if (ret == 0) | 
| 610 |  |                 /* Unknown amount pending but we are not finished */ | 
| 611 |  |                 ret = 1; | 
| 612 |  |         } | 
| 613 |  |         if (ret == 0) | 
| 614 |  |             ret = BIO_ctrl(next, cmd, num, ptr); | 
| 615 |  |         break; | 
| 616 |  |  | 
| 617 |  |     case BIO_CTRL_PENDING: | 
| 618 |  |         ret = ctx->zin.avail_in; | 
| 619 |  |         if (ret == 0) | 
| 620 |  |             ret = BIO_ctrl(next, cmd, num, ptr); | 
| 621 |  |         break; | 
| 622 |  |  | 
| 623 |  |     default: | 
| 624 |  |         ret = BIO_ctrl(next, cmd, num, ptr); | 
| 625 |  |         break; | 
| 626 |  |  | 
| 627 |  |     } | 
| 628 |  |  | 
| 629 |  |     return ret; | 
| 630 |  | } | 
| 631 |  |  | 
| 632 |  | static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) | 
| 633 |  | { | 
| 634 |  |     BIO *next = BIO_next(b); | 
| 635 |  |     if (next == NULL) | 
| 636 |  |         return 0; | 
| 637 |  |     return BIO_callback_ctrl(next, cmd, fp); | 
| 638 |  | } | 
| 639 |  |  | 
| 640 |  | #endif |