[PATCHES] MSZIP support for cabinet files
Jeremy Allison
jra at samba.org
Wed Jun 28 00:36:12 UTC 2017
On Tue, Jun 27, 2017 at 05:59:49PM +0200, Günther Deschner via samba-technical wrote:
> Hi,
>
> attached some patches (mostly from Aurelien) that add MSZIP compression
> support to our cabinet file marshalling code. This work is one of the
> prerequisites for the future MS-PAR protocol support.
>
> Please review & push.
I'm a bit scared of integer wrap (see some below). Can you
convince me it's safe ?
:-) :-).
Cheers,
Jeremy.
> +static enum ndr_err_code ndr_push_folder_cfdata(struct ndr_push *ndr,
> + const struct CFDATA *r,
> + enum cf_compress_type cab_ctype,
> + size_t num_cfdata)
> +{
> + size_t i;
> + enum ndr_compression_alg ndr_ctype = 0;
> +
> + ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
> +
> + if (cab_ctype == CF_COMPRESS_MSZIP) {
> + ndr_ctype = NDR_COMPRESSION_MSZIP_CAB;
> + NDR_CHECK(ndr_push_compression_state_init(ndr, ndr_ctype, &ndr->cstate));
> + }
> +
> + for (i = 0; i < num_cfdata; i++, r++) {
> + uint32_t compressed_offset, compressed_length = 0;
> + uint32_t csum, csum_offset;
> + uint32_t csumPartial;
> +
> + /*
> + * checksum is a function of the size fields
> + * and the potentially compressed data bytes,
> + * which haven't been compressed yet so
> + * remember offset, write zeroes, fill out
> + * later
> + */
> + csum_offset = ndr->offset;
> + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
> +
> + /*
> + * similarly, we don't know the compressed
> + * size yet, remember offset, write zeros,
> + * fill out later
> + */
> + compressed_offset = ndr->offset;
> + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
> + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->cbUncomp));
> +
> +
> + switch (cab_ctype) {
> + case CF_COMPRESS_NONE:
> + /* just copy the data */
> + NDR_CHECK(ndr_push_bytes(ndr, r->ab.data, r->ab.length));
> + compressed_length = r->cbUncomp;
> +
> + break;
> +
> + case CF_COMPRESS_LZX:
> + /*
> + * we have not yet worked out the details of LZX
> + * compression
> + */
> + return NDR_ERR_COMPRESSION;
> +
> + case CF_COMPRESS_MSZIP: {
> + struct ndr_push *push_sub, *push_compress;
> +
> + /* compress via subcontext */
> + NDR_CHECK(ndr_push_subcontext_start(ndr, &push_sub, 0, -1));
> + push_sub->cstate = ndr->cstate;
> + NDR_CHECK(ndr_push_compression_start(push_sub, &push_compress, ndr_ctype, -1));
> + ndr_set_flags(&push_compress->flags, LIBNDR_FLAG_REMAINING);
> + NDR_CHECK(ndr_push_DATA_BLOB(push_compress, NDR_SCALARS, r->ab));
> + NDR_CHECK(ndr_push_compression_end(push_sub, push_compress, ndr_ctype, -1));
> + NDR_CHECK(ndr_push_subcontext_end(ndr, push_sub, 0, -1));
> + compressed_length = push_sub->offset;
> +
> + break;
> + }
> + default:
> + return NDR_ERR_BAD_SWITCH;
> + }
> +
> + /* we can now write the compressed size and the checksum */
> + SSVAL(ndr->data, compressed_offset, compressed_length);
> +
> + /*
> + * Checksum over compressed data.
> + *
> + * The 8 bytes are the header size.
> + */
> +
> + csumPartial = ndr_cab_compute_checksum(&ndr->data[csum_offset + 8],
^^^^^^^^^^^^^^^^
Integer wrap checks ?
Didn't cnum_offset come from the client ?
> + compressed_length, 0);
> +
> + /*
> + * Checksum over header (compressed and uncompressed length).
> + *
> + * The first 4 bytes are the checksum size.
> + * The second 4 bytes are the size of the compressed and
> + * uncompressed length fields.
> + */
> + csum = ndr_cab_compute_checksum(&ndr->data[csum_offset + 4],
^^^^^^^^^^^^^^^^
Integer wrap checks ?
And here also ?
> + 4,
> + csumPartial);
> +
> + SIVAL(ndr->data, csum_offset, csum);
> + }
> +
> + ndr_push_compression_state_free(ndr->cstate);
> + ndr->cstate = NULL;
> +
> + return NDR_ERR_SUCCESS;
> +}
> +
> _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r)
> {
> uint32_t cntr_cffolders_0;
> uint32_t cntr_cffiles_0;
> - uint32_t cntr_cfdata_0;
> + uint32_t processed_cfdata = 0;
> {
> uint32_t _flags_save_STRUCT = ndr->flags;
> ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
> NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
> +
> if (ndr_flags & NDR_SCALARS) {
> - uint32_t next_offset = 0;
> + uint32_t i;
> NDR_CHECK(ndr_push_align(ndr, 4));
> NDR_CHECK(ndr_push_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
> for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (r->cfheader.cFolders); cntr_cffolders_0++) {
> NDR_CHECK(ndr_push_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
> }
> for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (r->cfheader.cFiles); cntr_cffiles_0++) {
> - uint32_t offset = ndr->offset + 4;
> NDR_CHECK(ndr_push_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
> - if (cntr_cffiles_0 > 0) {
> - next_offset += r->cffiles[cntr_cffiles_0 - 1].cbFile;
> - }
> - SIVAL(ndr->data, offset, next_offset);
> }
> #if 0
> NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
> #endif
> - for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (ndr_count_cfdata(r)); cntr_cfdata_0++) {
> - NDR_CHECK(ndr_push_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
> +
> + /* write in the folder header the offset of its first data block */
> + for (i = 0; i < r->cfheader.cFolders; i++) {
> + SIVAL(ndr->data, OFFSET_OF_FOLDER_COFFCABSTART(i), ndr->offset);
> + NDR_CHECK(ndr_push_folder_cfdata(ndr, r->cfdata + processed_cfdata, r->cffolders[i].typeCompress, r->cffolders[i].cCFData));
> + processed_cfdata += r->cffolders[i].cCFData;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here also ?
> }
> NDR_CHECK(ndr_push_trailer_align(ndr, 4));
> }
> @@ -160,6 +278,79 @@ _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags
> return NDR_ERR_SUCCESS;
> }
>
> +
> +/* Pull all CFDATA of a folder.
> + *
> + * This works on a folder level because compression type is set per
> + * folder, and a compression state can be shared between CFDATA of the
> + * same folder.
> + *
> + * This is not a regular NDR func as we pass the compression type and
> + * the number of CFDATA as extra arguments
> + */
> +static enum ndr_err_code ndr_pull_folder_cfdata(struct ndr_pull *ndr,
> + struct CFDATA *r,
> + enum cf_compress_type cab_ctype,
> + size_t num_cfdata)
> +{
> + size_t i;
> + enum ndr_compression_alg ndr_ctype = 0;
> +
> + if (cab_ctype == CF_COMPRESS_MSZIP) {
> + ndr_ctype = NDR_COMPRESSION_MSZIP_CAB;
> + NDR_CHECK(ndr_pull_compression_state_init(ndr, NDR_COMPRESSION_MSZIP_CAB, &ndr->cstate));
> + }
> +
> + for (i = 0; i < num_cfdata; i++, r++) {
> + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->csum));
> + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->cbData));
> + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->cbUncomp));
> +
> + switch (cab_ctype) {
> + case CF_COMPRESS_NONE:
> + /* just copy the data */
> + r->ab = data_blob_talloc(ndr->current_mem_ctx,
> + ndr->data+ndr->offset,
> + r->cbUncomp);
> + ndr->offset += r->cbUncomp;
> + break;
> +
> + case CF_COMPRESS_LZX:
> + /* just copy the data */
> + r->ab = data_blob_talloc(ndr->current_mem_ctx,
> + ndr->data+ndr->offset,
> + r->cbData);
> + ndr->offset += r->cbData;
> +
> + break;
> +
> + case CF_COMPRESS_MSZIP: {
> + struct ndr_pull *pull_sub, *pull_compress;
> +
> + /* decompress via subcontext */
> + NDR_CHECK(ndr_pull_subcontext_start(ndr, &pull_sub, 0, r->cbData));
> + pull_sub->cstate = ndr->cstate;
> + NDR_CHECK(ndr_pull_compression_start(pull_sub, &pull_compress,
> + ndr_ctype, r->cbUncomp, r->cbData));
> + ndr_set_flags(&pull_compress->flags, LIBNDR_FLAG_REMAINING);
> + NDR_CHECK(ndr_pull_DATA_BLOB(pull_compress, NDR_SCALARS, &r->ab));
> + NDR_CHECK(ndr_pull_compression_end(pull_sub, pull_compress, ndr_ctype, r->cbUncomp));
> + NDR_CHECK(ndr_pull_subcontext_end(ndr, pull_sub, 0, r->cbData));
> +
> + break;
> + }
> + default:
> + return NDR_ERR_BAD_SWITCH;
> + }
> + }
> +
> + ndr_pull_compression_state_free(ndr->cstate);
> + ndr->cstate = NULL;
> +
> + return NDR_ERR_SUCCESS;
> +}
> +
> _PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags, struct cab_file *r)
> {
> uint32_t size_cffolders_0 = 0;
> @@ -169,7 +360,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags
> uint32_t cntr_cffiles_0;
> TALLOC_CTX *_mem_save_cffiles_0 = NULL;
> uint32_t size_cfdata_0 = 0;
> - uint32_t cntr_cfdata_0;
> + uint32_t processed_cfdata = 0;
> TALLOC_CTX *_mem_save_cfdata_0 = NULL;
> {
> uint32_t _flags_save_STRUCT = ndr->flags;
> @@ -203,8 +394,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags
> NDR_PULL_ALLOC_N(ndr, r->cfdata, size_cfdata_0);
> _mem_save_cfdata_0 = NDR_PULL_GET_MEM_CTX(ndr);
> NDR_PULL_SET_MEM_CTX(ndr, r->cfdata, 0);
> - for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (size_cfdata_0); cntr_cfdata_0++) {
> - NDR_CHECK(ndr_pull_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
> + for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
> + NDR_CHECK(ndr_pull_folder_cfdata(ndr,
> + r->cfdata + processed_cfdata,
> + r->cffolders[cntr_cffolders_0].typeCompress,
> + r->cffolders[cntr_cffolders_0].cCFData));
> + processed_cfdata += r->cffolders[cntr_cffolders_0].cCFData;
> }
> NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cfdata_0, 0);
> NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
> diff --git a/librpc/ndr/ndr_compression.c b/librpc/ndr/ndr_compression.c
> index 5a821d5..54a6262 100644
> --- a/librpc/ndr/ndr_compression.c
> +++ b/librpc/ndr/ndr_compression.c
> @@ -47,6 +47,251 @@ static void ndr_zlib_free(voidpf opaque, voidpf address)
> talloc_free(address);
> }
>
> +static enum ndr_err_code ndr_pull_compression_mszip_cab_chunk(struct ndr_pull *ndrpull,
> + struct ndr_push *ndrpush,
> + struct ndr_compression_state *state,
> + ssize_t decompressed_len,
> + ssize_t compressed_len)
> +{
> + DATA_BLOB comp_chunk;
> + uint32_t comp_chunk_offset;
> + uint32_t comp_chunk_size;
> + DATA_BLOB plain_chunk;
> + uint32_t plain_chunk_offset;
> + uint32_t plain_chunk_size;
> + z_stream *z = state->mszip.z;
> + int z_ret;
> +
> + plain_chunk_size = decompressed_len;
> +
> + if (plain_chunk_size > 0x00008000) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "Bad MSZIP CAB plain chunk size %08X > 0x00008000 (PULL)",
> + plain_chunk_size);
> + }
> +
> +
> + comp_chunk_size = compressed_len;
> +
> + DEBUG(9,("MSZIP CAB plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
> + plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size));
> +
> + comp_chunk_offset = ndrpull->offset;
> + NDR_CHECK(ndr_pull_advance(ndrpull, comp_chunk_size));
> + comp_chunk.length = comp_chunk_size;
> + comp_chunk.data = ndrpull->data + comp_chunk_offset;
> +
> + plain_chunk_offset = ndrpush->offset;
> + NDR_CHECK(ndr_push_zero(ndrpush, plain_chunk_size));
> + plain_chunk.length = plain_chunk_size;
> + plain_chunk.data = ndrpush->data + plain_chunk_offset;
> +
> + if (comp_chunk.length < 2) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "Bad MSZIP CAB comp chunk size %u < 2 (PULL)",
> + (unsigned int)comp_chunk.length);
> + }
> + /* CK = Chris Kirmse, official Microsoft purloiner */
> + if (comp_chunk.data[0] != 'C' ||
> + comp_chunk.data[1] != 'K') {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "Bad MSZIP CAB invalid prefix [%c%c] != [CK]",
> + comp_chunk.data[0], comp_chunk.data[1]);
> + }
> +
> + /*
> + * This is a MSZIP block. It is actually using the deflate
> + * algorithm which can be decompressed by zlib. zlib will try
> + * to decompress as much as it can in each run. If we provide
> + * all the input and enough room for the uncompressed output,
> + * one call is enough. It will loop over all the sub-blocks
> + * that make up a deflate block.
> + *
> + * See corresponding push function for more info.
> + */
> +
> + z->next_in = comp_chunk.data + 2;
> + z->avail_in = comp_chunk.length - 2;
> + z->next_out = plain_chunk.data;
> + z->avail_out = plain_chunk.length;
> +
> + /*
> + * Each MSZIP CDATA contains a complete deflate stream
> + * i.e. the stream starts and ends in the CFDATA but the
> + * _dictionnary_ is shared between all CFDATA of a CFFOLDER.
> + *
> + * When decompressing, the initial dictionnary of the first
> + * CDATA is empty. All other CFDATA use the previous CFDATA
> + * uncompressed output as dictionnary.
> + */
> +
> + if (state->mszip.dict_size) {
> + z_ret = inflateSetDictionary(z, state->mszip.dict, state->mszip.dict_size);
> + if (z_ret != Z_OK) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib inflateSetDictionary error %s (%d) %s (PULL)",
> + zError(z_ret), z_ret, z->msg);
> + }
> + }
> +
> + z_ret = inflate(z, Z_FINISH);
> + if (z_ret == Z_OK) {
> + /*
> + * Z_OK here means there was no error but the stream
> + * hasn't been fully decompressed because there was
> + * not enough room for the output, which should not
> + * happen
> + */
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib inflate error not enough space for ouput (PULL)");
> + }
> + if (z_ret != Z_STREAM_END) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib inflate error %s (%d) %s (PULL)", zError(z_ret), z_ret, z->msg);
> + }
> +
> + if (z->total_out < plain_chunk.length) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib uncompressed output is smaller than expected (%lu < %zu) (PULL)",
> + z->total_out, plain_chunk.length);
> + }
> +
> + /*
> + * Keep a copy of the output to set as dictionnary for the
> + * next decompression call.
> + *
> + * The input pointer seems to be still valid between calls, so
> + * we can just store that instead of copying the memory over
> + * the dict temp buffer.
> + */
> + state->mszip.dict = plain_chunk.data;
> + state->mszip.dict_size = plain_chunk.length;
> +
> + z_ret = inflateReset(z);
> + if (z_ret != Z_OK) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib inflateReset error %s (%d) %s (PULL)",
> + zError(z_ret), z_ret, z->msg);
> + }
> +
> + return NDR_ERR_SUCCESS;
> +}
> +
> +static enum ndr_err_code ndr_push_compression_mszip_cab_chunk(struct ndr_push *ndrpush,
> + struct ndr_pull *ndrpull,
> + struct ndr_compression_state *state)
> +{
> + DATA_BLOB comp_chunk;
> + uint32_t comp_chunk_size;
> + DATA_BLOB plain_chunk;
> + uint32_t plain_chunk_size;
> + uint32_t plain_chunk_offset;
> + uint32_t max_plain_size = 0x00008000;
> + /*
> + * The maximum compressed size of each MSZIP block is 32k + 12 bytes
> + * header size.
> + */
> + uint32_t max_comp_size = 0x00008000 + 12;
> + int z_ret;
> + z_stream *z;
> +
> + plain_chunk_size = MIN(max_plain_size, ndrpull->data_size - ndrpull->offset);
> + plain_chunk_offset = ndrpull->offset;
> + NDR_CHECK(ndr_pull_advance(ndrpull, plain_chunk_size));
> +
> + plain_chunk.data = ndrpull->data + plain_chunk_offset;
> + plain_chunk.length = plain_chunk_size;
> +
> + NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size));
> +
> + comp_chunk.data = ndrpush->data + ndrpush->offset;
> + comp_chunk.length = max_comp_size;
> +
> + /* CK = Chris Kirmse, official Microsoft purloiner */
> + comp_chunk.data[0] = 'C';
> + comp_chunk.data[1] = 'K';
> +
> + z = state->mszip.z;
> + z->next_in = plain_chunk.data;
> + z->avail_in = plain_chunk.length;
> + z->total_in = 0;
> +
> + z->next_out = comp_chunk.data + 2;
> + z->avail_out = comp_chunk.length;
> + z->total_out = 0;
> +
> + /*
> + * See pull function for explanations of the MSZIP format.
> + *
> + * The CFDATA block contains a full deflate stream. Each stream
> + * uses the uncompressed input of the previous CFDATA in the
> + * same CFFOLDER as a dictionnary for the compression.
> + */
> +
> + if (state->mszip.dict_size) {
> + z_ret = deflateSetDictionary(z, state->mszip.dict, state->mszip.dict_size);
> + if (z_ret != Z_OK) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib deflateSetDictionary error %s (%d) %s (PUSH)",
> + zError(z_ret), z_ret, z->msg);
> + }
> + }
> +
> + /*
> + * Z_FINISH should make deflate process all of the input in
> + * one call. If the stream is not finished there was an error
> + * e.g. not enough room to store the compressed output.
> + */
> + z_ret = deflate(z, Z_FINISH);
> + if (z_ret != Z_STREAM_END) {
> + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
> + "zlib deflate error %s (%d) %s (PUSH)",
> + zError(z_ret), z_ret, z->msg);
> + }
> +
> + if (z->avail_in) {
> + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
> + "MSZIP not all avail_in[%u] bytes consumed (PUSH)",
> + z->avail_in);
> + }
> +
> + comp_chunk_size = 2 + z->total_out;
> +
> + z_ret = deflateReset(z);
> + if (z_ret != Z_OK) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib deflateReset error %s (%d) %s (PUSH)",
> + zError(z_ret), z_ret, z->msg);
> + }
> +
> + if (plain_chunk.length > talloc_array_length(state->mszip.dict)) {
> + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
> + "zlib dict buffer is too big (PUSH)");
> + }
> +
> + /*
> + * Keep a copy of the input to set as dictionnary for the next
> + * compression call.
> + *
> + * Ideally we would just store the input pointer and length
> + * without copying but the memory gets invalidated between the
> + * calls, so we just copy to a dedicated buffer we now is
> + * still going to been valid for the lifetime of the
> + * compressions state object.
> + */
> + memcpy(state->mszip.dict, plain_chunk.data, plain_chunk.length);
> + state->mszip.dict_size = plain_chunk.length;
> +
> + DEBUG(9,("MSZIP comp plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
> + (unsigned int)plain_chunk.length,
> + (unsigned int)plain_chunk.length,
> + comp_chunk_size, comp_chunk_size));
> +
> + ndrpush->offset += comp_chunk_size;
> + return NDR_ERR_SUCCESS;
> +}
> +
> +
> static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpull,
> struct ndr_push *ndrpush,
> z_stream *z,
> @@ -411,6 +656,12 @@ enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr,
> NDR_ERR_HAVE_NO_MEMORY(ndrpush);
>
> switch (compression_alg) {
> + case NDR_COMPRESSION_MSZIP_CAB:
> + NDR_CHECK(ndr_pull_compression_mszip_cab_chunk(subndr, ndrpush,
> + subndr->cstate,
> + decompressed_len,
> + compressed_len));
> + break;
> case NDR_COMPRESSION_MSZIP:
> ZERO_STRUCT(z);
> while (!last) {
> @@ -470,6 +721,7 @@ enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr,
> struct ndr_push *uncomndr;
>
> switch (compression_alg) {
> + case NDR_COMPRESSION_MSZIP_CAB:
> case NDR_COMPRESSION_MSZIP:
> case NDR_COMPRESSION_XPRESS:
> break;
> @@ -507,6 +759,10 @@ enum ndr_err_code ndr_push_compression_end(struct ndr_push *subndr,
> ndrpull->offset = 0;
>
> switch (compression_alg) {
> + case NDR_COMPRESSION_MSZIP_CAB:
> + NDR_CHECK(ndr_push_compression_mszip_cab_chunk(subndr, ndrpull, subndr->cstate));
> + break;
> +
> case NDR_COMPRESSION_MSZIP:
> ZERO_STRUCT(z);
> while (!last) {
> diff --git a/source4/torture/ndr/cabinet.c b/source4/torture/ndr/cabinet.c
> index 790f7c3..f197534 100644
> --- a/source4/torture/ndr/cabinet.c
> +++ b/source4/torture/ndr/cabinet.c
> @@ -4233,10 +4233,9 @@ static bool cab_file_MSZIP_check(struct torture_context *tctx,
>
> blob = data_blob(NULL, r->cfdata[0].cbUncomp);
> memset(blob.data, 'A', blob.length);
> -#if 0
> - /* once we have MSZIP compression working we can enable this test */
> +
> torture_assert_data_blob_equal(tctx, r->cfdata[0].ab, blob, "ab");
> -#endif
> +
> return true;
> }
>
> --
> 2.9.4
>
>
> From 9784f4e411eed188d0c3daf91bde90843f2bc6b3 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd at samba.org>
> Date: Tue, 23 May 2017 15:50:55 +0200
> Subject: [PATCH 13/13] s4-torture: point out why we cannot validate MSZIP
> compressed files
>
> Guenther
>
> Signed-off-by: Guenther Deschner <gd at samba.org>
> ---
> source4/torture/ndr/cabinet.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/source4/torture/ndr/cabinet.c b/source4/torture/ndr/cabinet.c
> index f197534..8cdf4cb 100644
> --- a/source4/torture/ndr/cabinet.c
> +++ b/source4/torture/ndr/cabinet.c
> @@ -4318,5 +4318,12 @@ struct torture_suite *ndr_cabinet_suite(TALLOC_CTX *ctx)
>
> torture_suite_add_ndr_pull_validate_test(suite, cab_file, cab_file_plain_data, cab_file_plain_check);
>
> + /*
> + * we cannot validate, as libz' compression routines currently create a
> + * slightly different result
> + */
> +
> + /* torture_suite_add_ndr_pull_validate_test(suite, cab_file, cab_file_MSZIP_data, cab_file_MSZIP_check); */
> +
> return suite;
> }
> --
> 2.9.4
>
More information about the samba-technical
mailing list