Commit f8be737d authored by Patrick Monnerat's avatar Patrick Monnerat
Browse files

content_encoding: accept up to 4 unknown trailer bytes after raw deflate data

Some servers issue raw deflate data that may be followed by an undocumented
trailer. This commit makes curl tolerate such a trailer of up to 4 bytes
before considering the data is in error.

Reported-by: clbr on github
Fixes #2719
parent 5b511b09
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -73,9 +73,9 @@
typedef enum {
  ZLIB_UNINIT,               /* uninitialized */
  ZLIB_INIT,                 /* initialized */
  ZLIB_INFLATING,       /* Inflating started. */
  ZLIB_INFLATING,            /* inflating started. */
  ZLIB_EXTERNAL_TRAILER,     /* reading external trailer */
  ZLIB_GZIP_HEADER,          /* reading gzip header */
  ZLIB_GZIP_TRAILER,    /* reading gzip trailer */
  ZLIB_GZIP_INFLATING,       /* inflating gzip stream */
  ZLIB_INIT_GZIP             /* initialized in transparent gzip mode */
} zlibInitState;
@@ -150,8 +150,8 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
  if(result || !zp->trailerlen)
    result = exit_zlib(conn, z, &zp->zlib_init, result);
  else {
    /* Only occurs for gzip with zlib < 1.2.0.4. */
    zp->zlib_init = ZLIB_GZIP_TRAILER;
    /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
    zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
  }
  return result;
}
@@ -233,6 +233,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
          z->next_in = orig_in;
          z->avail_in = nread;
          zp->zlib_init = ZLIB_INFLATING;
          zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
          done = FALSE;
          break;
        }
@@ -287,6 +288,9 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
  z->next_in = (Bytef *) buf;
  z->avail_in = (uInt) nbytes;

  if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
    return process_trailer(conn, zp);

  /* Now uncompress the data */
  return inflate_stream(conn, writer, ZLIB_INFLATING);
}
@@ -532,7 +536,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
  }
  break;

  case ZLIB_GZIP_TRAILER:
  case ZLIB_EXTERNAL_TRAILER:
    z->next_in = (Bytef *) buf;
    z->avail_in = (uInt) nbytes;
    return process_trailer(conn, zp);