Пример #1
0
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
    seed = FUZZ_seed(&src, &size);

    /* Allocate all buffers and contexts if not already allocated */
    if (!buf) {
      buf = malloc(kBufSize);
      FUZZ_ASSERT(buf);
    }

    if (!dstream) {
        dstream = ZSTD_createDStream();
        FUZZ_ASSERT(dstream);
        FUZZ_ASSERT(!ZSTD_isError(ZSTD_initDStream(dstream)));
    } else {
        FUZZ_ASSERT(!ZSTD_isError(ZSTD_resetDStream(dstream)));
    }

    while (size > 0) {
        ZSTD_inBuffer in = makeInBuffer(&src, &size);
        while (in.pos != in.size) {
            ZSTD_outBuffer out = makeOutBuffer();
            size_t const rc = ZSTD_decompressStream(dstream, &out, &in);
            if (ZSTD_isError(rc)) goto error;
            if (rc == 0) FUZZ_ASSERT(!ZSTD_isError(ZSTD_resetDStream(dstream)));
        }
    }

error:
#ifndef STATEFUL_FUZZING
    ZSTD_freeDStream(dstream); dstream = NULL;
#endif
    return 0;
}
Пример #2
0
		ByteArray DecompressFile(const FilePath& path)
		{
			BinaryReader reader(path);

			if (!reader)
			{
				return ByteArray();
			}

			const size_t inputBufferSize = ZSTD_DStreamInSize();
			const auto pInputBuffer = std::make_unique<Byte[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_DStreamOutSize();
			const auto pOutputBuffer = std::make_unique<Byte[]>(outputBufferSize);

			ZSTD_DStream* const dStream = ZSTD_createDStream();

			if (!dStream)
			{
				return ByteArray();
			}

			const size_t initResult = ZSTD_initDStream(dStream);

			if (ZSTD_isError(initResult))
			{
				ZSTD_freeDStream(dStream);
				return ByteArray();
			}

			size_t toRead = initResult;

			Array<Byte> buffer;

			while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead)))
			{
				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_decompressStream(dStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						ZSTD_freeDStream(dStream);
						return ByteArray();
					}

					buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos);
				}
			}

			ZSTD_freeDStream(dStream);

			return ByteArray(std::move(buffer));
		}
Пример #3
0
int testStreamingAPI(void)
{
    size_t const outBuffSize = ZSTD_DStreamOutSize();
    char* const outBuff = malloc(outBuffSize);
    ZSTD_DStream* const stream = ZSTD_createDStream();
    ZSTD_inBuffer input = { COMPRESSED, COMPRESSED_SIZE, 0 };
    size_t outputPos = 0;
    int needsInit = 1;

    if (outBuff == NULL) {
        DISPLAY("ERROR: Could not allocate memory\n");
        return 1;
    }
    if (stream == NULL) {
        DISPLAY("ERROR: Could not create dstream\n");
        return 1;
    }

    while (1) {
        ZSTD_outBuffer output = {outBuff, outBuffSize, 0};
        if (needsInit) {
            size_t const ret = ZSTD_initDStream(stream);
            if (ZSTD_isError(ret)) {
                DISPLAY("ERROR: %s\n", ZSTD_getErrorName(ret));
                return 1;
            }
        }
        {
            size_t const ret = ZSTD_decompressStream(stream, &output, &input);
            if (ZSTD_isError(ret)) {
                DISPLAY("ERROR: %s\n", ZSTD_getErrorName(ret));
                return 1;
            }

            if (ret == 0) {
                needsInit = 1;
            }
        }

        if (memcmp(outBuff, EXPECTED + outputPos, output.pos) != 0) {
            DISPLAY("ERROR: Wrong decoded output produced\n");
            return 1;
        }
        outputPos += output.pos;
        if (input.pos == input.size && output.pos < output.size) {
            break;
        }
    }

    free(outBuff);
    ZSTD_freeDStream(stream);
    DISPLAY("Streaming API OK\n");
    return 0;
}
Пример #4
0
static PyObject *py_zstd_uncompress(PyObject* self, PyObject *args) {

    PyObject *result;
    const char *source;
    uint32_t source_size;
    uint32_t dest_size;
    uint32_t header_size;
    size_t cSize;

#if PY_MAJOR_VERSION >= 3
    if (!PyArg_ParseTuple(args, "y#", &source, &source_size))
        return NULL;
#else
    if (!PyArg_ParseTuple(args, "s#", &source, &source_size))
        return NULL;
#endif

    header_size = sizeof(dest_size);

    memcpy(&dest_size, source, header_size);
    result = PyBytes_FromStringAndSize(NULL, dest_size);

    source += header_size;

    if (result != NULL && dest_size > 0) {
        char *dest = PyBytes_AS_STRING(result);

        cSize = ZSTD_decompress(dest, dest_size, source, source_size - header_size);
        if (ZSTD_isError(cSize))
            PyErr_Format(ZstdError, "Decompression error: %s", ZSTD_getErrorName(cSize));
    }

    return result;
}
Пример #5
0
int testSimpleAPI(void)
{
    size_t const size = strlen(EXPECTED);
    char* const output = malloc(size);

    if (!output) {
        DISPLAY("ERROR: Not enough memory!\n");
        return 1;
    }

    {
        size_t const ret = ZSTD_decompress(output, size, COMPRESSED, COMPRESSED_SIZE);
        if (ZSTD_isError(ret)) {
            if (ret == ZSTD_error_prefix_unknown) {
                DISPLAY("ERROR: Invalid frame magic number, was this compiled "
                        "without legacy support?\n");
            } else {
                DISPLAY("ERROR: %s\n", ZSTD_getErrorName(ret));
            }
            return 1;
        }
        if (ret != size) {
            DISPLAY("ERROR: Wrong decoded size\n");
        }
    }
    if (memcmp(EXPECTED, output, size) != 0) {
        DISPLAY("ERROR: Wrong decoded output produced\n");
        return 1;
    }

    free(output);
    DISPLAY("Simple API OK\n");
    return 0;
}
Пример #6
0
void CompressionCodecZSTD::doDecompressData(const char * source, UInt32 source_size, char * dest, UInt32 uncompressed_size) const
{
    size_t res = ZSTD_decompress(dest, uncompressed_size, source, source_size);

    if (ZSTD_isError(res))
        throw Exception("Cannot ZSTD_decompress: " + std::string(ZSTD_getErrorName(res)), ErrorCodes::CANNOT_DECOMPRESS);
}
Пример #7
0
void zstdThrowIfError(size_t rc) {
  if (!ZSTD_isError(rc)) {
    return;
  }
  throw std::runtime_error(
      to<std::string>("ZSTD returned an error: ", ZSTD_getErrorName(rc)));
}
Пример #8
0
/* *** Initialization *** */

#define MIN(a,b)    ( ((a)<(b)) ? (a) : (b) )
#define BLOCKSIZE   (128 * 1024)   /* a bit too "magic", should come from reference */
size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, ZSTD_parameters params)
{
    size_t neededInBuffSize;

    ZSTD_validateParams(&params);
    neededInBuffSize = (size_t)1 << params.windowLog;

    /* allocate buffers */
    if (zbc->inBuffSize < neededInBuffSize)
    {
        zbc->inBuffSize = neededInBuffSize;
        free(zbc->inBuff);   /* should not be necessary */
        zbc->inBuff = (char*)malloc(neededInBuffSize);
        if (zbc->inBuff == NULL) return ERROR(memory_allocation);
    }
    zbc->blockSize = MIN(BLOCKSIZE, zbc->inBuffSize);
    if (zbc->outBuffSize < ZSTD_compressBound(zbc->blockSize)+1)
    {
        zbc->outBuffSize = ZSTD_compressBound(zbc->blockSize)+1;
        free(zbc->outBuff);   /* should not be necessary */
        zbc->outBuff = (char*)malloc(zbc->outBuffSize);
        if (zbc->outBuff == NULL) return ERROR(memory_allocation);
    }

    zbc->outBuffContentSize = ZSTD_compressBegin_advanced(zbc->zc, params);
    if (ZSTD_isError(zbc->outBuffContentSize)) return zbc->outBuffContentSize;

    zbc->inToCompress = 0;
    zbc->inBuffPos = 0;
    zbc->inBuffTarget = zbc->blockSize;
    zbc->outBuffFlushedSize = 0;
    zbc->stage = ZBUFFcs_flush;   /* starts by flushing the header */
    return 0;   /* ready to go */
}
Пример #9
0
static void write_zstd(int f, int fd, const char *arg)
{
    ZSTD_inBuffer  zin;
    ZSTD_outBuffer zout;
    size_t const inbufsz  = ZSTD_CStreamInSize();
    zin.src = malloc(inbufsz);
    zout.size = ZSTD_CStreamOutSize();
    zout.dst = malloc(zout.size);

    if (!zin.src || !zout.dst)
        goto zstd_w_no_stream;

    ZSTD_CStream* const stream = ZSTD_createCStream();
    if (!stream)
        goto zstd_w_no_stream;
    if (ZSTD_isError(ZSTD_initCStream(stream, 3)))
        goto zstd_w_error;

    size_t s;
    while ((s = read(fd, (void*)zin.src, inbufsz)) > 0)
    {
        zin.size = s;
        zin.pos = 0;
        while (zin.pos < zin.size)
        {
            zout.pos = 0;
            size_t w = ZSTD_compressStream(stream, &zout, &zin);
            if (ZSTD_isError(w))
                goto zstd_w_error;
            if (write(f, zout.dst, zout.pos) != (ssize_t)zout.pos)
                goto zstd_w_error;
        }
    }

    zout.pos = 0;
    ZSTD_endStream(stream, &zout);
    // no way to handle an error here
    write(f, zout.dst, zout.pos);

zstd_w_error:
    ZSTD_freeCStream(stream);
zstd_w_no_stream:
    free((void*)zin.src);
    free(zout.dst);
    close(f);
    close(fd);
}
Пример #10
0
/* ZSTDMT_flushNextJob() :
 * output : will be updated with amount of data flushed .
 * blockToFlush : if >0, the function will block and wait if there is no data available to flush .
 * @return : amount of data remaining within internal buffer, 1 if unknown but > 0, 0 if no more, or an error code */
static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsigned blockToFlush)
{
    unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask;
    if (zcs->doneJobID == zcs->nextJobID) return 0;   /* all flushed ! */
    PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
    while (zcs->jobs[wJobID].jobCompleted==0) {
        DEBUGLOG(5, "waiting for jobCompleted signal from job %u", zcs->doneJobID);
        if (!blockToFlush) { pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; }  /* nothing ready to be flushed => skip */
        pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);  /* block when nothing available to flush */
    }
    pthread_mutex_unlock(&zcs->jobCompleted_mutex);
    /* compression job completed : output can be flushed */
    {   ZSTDMT_jobDescription job = zcs->jobs[wJobID];
        if (!job.jobScanned) {
            if (ZSTD_isError(job.cSize)) {
                DEBUGLOG(5, "compression error detected ");
                ZSTDMT_waitForAllJobsCompleted(zcs);
                ZSTDMT_releaseAllJobResources(zcs);
                return job.cSize;
            }
            ZSTDMT_releaseCCtx(zcs->cctxPool, job.cctx);
            zcs->jobs[wJobID].cctx = NULL;
            DEBUGLOG(5, "zcs->params.fParams.checksumFlag : %u ", zcs->params.fParams.checksumFlag);
            if (zcs->params.fParams.checksumFlag) {
                XXH64_update(&zcs->xxhState, (const char*)job.srcStart + job.dictSize, job.srcSize);
                if (zcs->frameEnded && (zcs->doneJobID+1 == zcs->nextJobID)) {  /* write checksum at end of last section */
                    U32 const checksum = (U32)XXH64_digest(&zcs->xxhState);
                    DEBUGLOG(4, "writing checksum : %08X \n", checksum);
                    MEM_writeLE32((char*)job.dstBuff.start + job.cSize, checksum);
                    job.cSize += 4;
                    zcs->jobs[wJobID].cSize += 4;
            }   }
            ZSTDMT_releaseBuffer(zcs->buffPool, job.src);
            zcs->jobs[wJobID].srcStart = NULL;
            zcs->jobs[wJobID].src = g_nullBuffer;
            zcs->jobs[wJobID].jobScanned = 1;
        }
        {   size_t const toWrite = MIN(job.cSize - job.dstFlushed, output->size - output->pos);
            DEBUGLOG(4, "Flushing %u bytes from job %u ", (U32)toWrite, zcs->doneJobID);
            memcpy((char*)output->dst + output->pos, (const char*)job.dstBuff.start + job.dstFlushed, toWrite);
            output->pos += toWrite;
            job.dstFlushed += toWrite;
        }
        if (job.dstFlushed == job.cSize) {   /* output buffer fully flushed => move to next one */
            ZSTDMT_releaseBuffer(zcs->buffPool, job.dstBuff);
            zcs->jobs[wJobID].dstBuff = g_nullBuffer;
            zcs->jobs[wJobID].jobCompleted = 0;
            zcs->doneJobID++;
        } else {
            zcs->jobs[wJobID].dstFlushed = job.dstFlushed;
        }
        /* return value : how many bytes left in buffer ; fake it to 1 if unknown but >0 */
        if (job.cSize > job.dstFlushed) return (job.cSize - job.dstFlushed);
        if (zcs->doneJobID < zcs->nextJobID) return 1;   /* still some buffer to flush */
        zcs->allJobsCompleted = zcs->frameEnded;   /* frame completed and entirely flushed */
        return 0;   /* everything flushed */
}   }
Пример #11
0
UInt32 CompressionCodecZSTD::doCompressData(const char * source, UInt32 source_size, char * dest) const
{
    size_t compressed_size = ZSTD_compress(dest, ZSTD_compressBound(source_size), source, source_size, level);

    if (ZSTD_isError(compressed_size))
        throw Exception("Cannot compress block with ZSTD: " + std::string(ZSTD_getErrorName(compressed_size)), ErrorCodes::CANNOT_COMPRESS);

    return compressed_size;
}
Пример #12
0
static int decompress_zstd(const char *inbuf, char *outbuf, u64 compress_len,
			   u64 decompress_len)
{
#if !BTRFSRESTORE_ZSTD
	error("btrfs not compiled with zstd support");
	return -1;
#else
	ZSTD_DStream *strm;
	size_t zret;
	int ret = 0;
	ZSTD_inBuffer in = {inbuf, compress_len, 0};
	ZSTD_outBuffer out = {outbuf, decompress_len, 0};

	strm = ZSTD_createDStream();
	if (!strm) {
		error("zstd create failed");
		return -1;
	}

	zret = ZSTD_initDStream(strm);
	if (ZSTD_isError(zret)) {
		error("zstd init failed: %s", ZSTD_getErrorName(zret));
		ret = -1;
		goto out;
	}

	zret = ZSTD_decompressStream(strm, &out, &in);
	if (ZSTD_isError(zret)) {
		error("zstd decompress failed %s\n", ZSTD_getErrorName(zret));
		ret = -1;
		goto out;
	}
	if (zret != 0) {
		error("zstd frame incomplete");
		ret = -1;
		goto out;
	}

out:
	ZSTD_freeDStream(strm);
	return ret;
#endif
}
Пример #13
0
static PyObject* ZstdCompressionWriter_exit(ZstdCompressionWriter* self, PyObject* args) {
	PyObject* exc_type;
	PyObject* exc_value;
	PyObject* exc_tb;
	size_t zresult;

	ZSTD_outBuffer output;
	PyObject* res;

	if (!PyArg_ParseTuple(args, "OOO:__exit__", &exc_type, &exc_value, &exc_tb)) {
		return NULL;
	}

	self->entered = 0;

	if (exc_type == Py_None && exc_value == Py_None && exc_tb == Py_None) {
		ZSTD_inBuffer inBuffer;

		inBuffer.src = NULL;
		inBuffer.size = 0;
		inBuffer.pos = 0;

		output.dst = PyMem_Malloc(self->outSize);
		if (!output.dst) {
			return PyErr_NoMemory();
		}
		output.size = self->outSize;
		output.pos = 0;

		while (1) {
			zresult = ZSTD_compress_generic(self->compressor->cctx, &output, &inBuffer, ZSTD_e_end);
			if (ZSTD_isError(zresult)) {
				PyErr_Format(ZstdError, "error ending compression stream: %s",
					ZSTD_getErrorName(zresult));
				PyMem_Free(output.dst);
				return NULL;
			}

			if (output.pos) {
#if PY_MAJOR_VERSION >= 3
				res = PyObject_CallMethod(self->writer, "write", "y#",
#else
				res = PyObject_CallMethod(self->writer, "write", "s#",
#endif
					output.dst, output.pos);
				Py_XDECREF(res);
			}

			if (!zresult) {
				break;
			}

			output.pos = 0;
		}
Пример #14
0
static void compressFile_orDie(const char* fname, const char* outName, int cLevel, unsigned frameSize)
{
    FILE* const fin  = fopen_orDie(fname, "rb");
    FILE* const fout = fopen_orDie(outName, "wb");
    size_t const buffInSize = ZSTD_CStreamInSize();    /* can always read one full block */
    void*  const buffIn  = malloc_orDie(buffInSize);
    size_t const buffOutSize = ZSTD_CStreamOutSize();  /* can always flush a full block */
    void*  const buffOut = malloc_orDie(buffOutSize);

    ZSTD_seekable_CStream* const cstream = ZSTD_seekable_createCStream();
    if (cstream==NULL) { fprintf(stderr, "ZSTD_seekable_createCStream() error \n"); exit(10); }
    size_t const initResult = ZSTD_seekable_initCStream(cstream, cLevel, 1, frameSize);
    if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_seekable_initCStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }

    size_t read, toRead = buffInSize;
    while( (read = fread_orDie(buffIn, toRead, fin)) ) {
        ZSTD_inBuffer input = { buffIn, read, 0 };
        while (input.pos < input.size) {
            ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
            toRead = ZSTD_seekable_compressStream(cstream, &output , &input);   /* toRead is guaranteed to be <= ZSTD_CStreamInSize() */
            if (ZSTD_isError(toRead)) { fprintf(stderr, "ZSTD_seekable_compressStream() error : %s \n", ZSTD_getErrorName(toRead)); exit(12); }
            if (toRead > buffInSize) toRead = buffInSize;   /* Safely handle case when `buffInSize` is manually changed to a value < ZSTD_CStreamInSize()*/
            fwrite_orDie(buffOut, output.pos, fout);
        }
    }

    while (1) {
        ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
        size_t const remainingToFlush = ZSTD_seekable_endStream(cstream, &output);   /* close stream */
        if (ZSTD_isError(remainingToFlush)) { fprintf(stderr, "ZSTD_seekable_endStream() error : %s \n", ZSTD_getErrorName(remainingToFlush)); exit(13); }
        fwrite_orDie(buffOut, output.pos, fout);
        if (!remainingToFlush) break;
    }

    ZSTD_seekable_freeCStream(cstream);
    fclose_orDie(fout);
    fclose_orDie(fin);
    free(buffIn);
    free(buffOut);
}
Пример #15
0
/* ZSTDMT_compressChunk() : POOL_function type */
void ZSTDMT_compressChunk(void* jobDescription)
{
    ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
    const void* const src = (const char*)job->srcStart + job->dictSize;
    buffer_t const dstBuff = job->dstBuff;
    DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u",
                 job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
    if (job->cdict) {  /* should only happen for first segment */
        size_t const initError = ZSTD_compressBegin_usingCDict_advanced(job->cctx, job->cdict, job->params.fParams, job->fullFrameSize);
        if (job->cdict) DEBUGLOG(3, "using CDict ");
        if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
    } else {  /* srcStart points at reloaded section */
        if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0;  /* ensure no srcSize control */
        {   size_t const dictModeError = ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceRawDict, 1);  /* Force loading dictionary in "content-only" mode (no header analysis) */
            size_t const initError = ZSTD_compressBegin_advanced(job->cctx, job->srcStart, job->dictSize, job->params, job->fullFrameSize);
            if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
            ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceWindow, 1);
    }   }
    if (!job->firstChunk) {  /* flush and overwrite frame header when it's not first segment */
        size_t const hSize = ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, 0);
        if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
        ZSTD_invalidateRepCodes(job->cctx);
    }

    DEBUGLOG(4, "Compressing : ");
    DEBUG_PRINTHEX(4, job->srcStart, 12);
    job->cSize = (job->lastChunk) ?
                 ZSTD_compressEnd     (job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
                 ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
    DEBUGLOG(3, "compressed %u bytes into %u bytes   (first:%u) (last:%u)",
                (unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
    DEBUGLOG(5, "dstBuff.size : %u ; => %s", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));

_endJob:
    PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
    job->jobCompleted = 1;
    job->jobScanned = 0;
    pthread_cond_signal(job->jobCompleted_cond);
    pthread_mutex_unlock(job->jobCompleted_mutex);
}
Пример #16
0
size_t ZSTD_seekable_endStream(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output)
{
    if (!zcs->writingSeekTable && zcs->frameDSize) {
        const size_t endFrame = ZSTD_seekable_endFrame(zcs, output);
        if (ZSTD_isError(endFrame)) return endFrame;
        /* return an accurate size hint */
        if (endFrame) return endFrame + ZSTD_seekable_seekTableSize(&zcs->framelog);
    }

    zcs->writingSeekTable = 1;

    return ZSTD_seekable_writeSeekTable(&zcs->framelog, output);
}
Пример #17
0
static int zstd_uncompress(void *dest, void *src, int size, int outsize,
			   int *error)
{
	const size_t res = ZSTD_decompress(dest, outsize, src, size);

	if (ZSTD_isError(res)) {
		fprintf(stderr, "\t%d %d\n", outsize, size);

		*error = (int)ZSTD_getErrorCode(res);
		return -1;
	}

	return (int)res;
}
Пример #18
0
size_t ZSTD_seekable_compressStream(ZSTD_seekable_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{
    const BYTE* const inBase = (const BYTE*) input->src + input->pos;
    size_t inLen = input->size - input->pos;

    inLen = MIN(inLen, (size_t)(zcs->maxFrameSize - zcs->frameDSize));

    /* if we haven't finished flushing the last frame, don't start writing a new one */
    if (inLen > 0) {
        ZSTD_inBuffer inTmp = { inBase, inLen, 0 };
        size_t const prevOutPos = output->pos;

        size_t const ret = ZSTD_compressStream(zcs->cstream, output, &inTmp);

        if (zcs->framelog.checksumFlag) {
            XXH64_update(&zcs->xxhState, inBase, inTmp.pos);
        }

        zcs->frameCSize += output->pos - prevOutPos;
        zcs->frameDSize += inTmp.pos;

        input->pos += inTmp.pos;

        if (ZSTD_isError(ret)) return ret;
    }

    if (zcs->maxFrameSize == zcs->frameDSize) {
        /* log the frame and start over */
        size_t const ret = ZSTD_seekable_endFrame(zcs, output);
        if (ZSTD_isError(ret)) return ret;

        /* get the client ready for the next frame */
        return (size_t)zcs->maxFrameSize;
    }

    return (size_t)(zcs->maxFrameSize - zcs->frameDSize);
}
Пример #19
0
ZSTD_frameLog* ZSTD_seekable_createFrameLog(int checksumFlag)
{
    ZSTD_frameLog* fl = malloc(sizeof(ZSTD_frameLog));
    if (fl == NULL) return NULL;

    if (ZSTD_isError(ZSTD_seekable_frameLog_allocVec(fl))) {
        free(fl);
        return NULL;
    }

    fl->checksumFlag = checksumFlag;
    fl->seekTablePos = 0;
    fl->seekTableIndex = 0;
    fl->size = 0;

    return fl;
}
Пример #20
0
static PyObject *py_zstd_compress(PyObject* self, PyObject *args) {

    PyObject *result;
    const char *source;
    uint32_t source_size;
    char *dest;
    uint32_t dest_size;
    uint32_t header_size;
    size_t cSize;
    uint32_t level = 0;

#if PY_MAJOR_VERSION >= 3
    if (!PyArg_ParseTuple(args, "y#|i", &source, &source_size, &level))
        return NULL;
#else
    if (!PyArg_ParseTuple(args, "s#|i", &source, &source_size, &level))
        return NULL;
#endif

    if (level <= 0) level=1;
    if (level > 20) level=20;

    header_size = sizeof(source_size);

    dest_size = ZSTD_compressBound(source_size);
    result = PyBytes_FromStringAndSize(NULL, header_size + dest_size);
    if (result == NULL) {
        return NULL;
    }
    dest = PyBytes_AS_STRING(result);

    memcpy(dest, &source_size, header_size);

    dest += header_size;

    if (source_size > 0) {
        // Low level == old version
        cSize = ZSTD_compress(dest, dest_size, source, source_size, level);
        if (ZSTD_isError(cSize))
            PyErr_Format(ZstdError, "Compression error: %s", ZSTD_getErrorName(cSize));
        Py_SIZE(result) = cSize + sizeof(source_size);
    }
    return result;
}
Пример #21
0
		ByteArray Compress(const ByteArrayView view, const int32 compressionLevel)
		{
			const size_t bufferSize = ZSTD_compressBound(view.size());

			Array<Byte> buffer(bufferSize);

			const size_t result = ZSTD_compress(buffer.data(), buffer.size(), view.data(), view.size(), compressionLevel);

			if (ZSTD_isError(result))
			{
				return ByteArray();
			}

			buffer.resize(result);

			buffer.shrink_to_fit();

			return ByteArray(std::move(buffer));
		}
Пример #22
0
static PyObject* ZstdCompressionWriter_enter(ZstdCompressionWriter* self) {
	size_t zresult;

	if (self->entered) {
		PyErr_SetString(ZstdError, "cannot __enter__ multiple times");
		return NULL;
	}

	zresult = ZSTD_CCtx_setPledgedSrcSize(self->compressor->cctx, self->sourceSize);
	if (ZSTD_isError(zresult)) {
		PyErr_Format(ZstdError, "error setting source size: %s",
			ZSTD_getErrorName(zresult));
		return NULL;
	}

	self->entered = 1;

	Py_INCREF(self);
	return (PyObject*)self;
}
Пример #23
0
static int zstd_compress(void *strm, void *dest, void *src, int size,
			 int block_size, int *error)
{
	const size_t res = ZSTD_compressCCtx((ZSTD_CCtx*)strm, dest, block_size,
					     src, size, compression_level);

	if (ZSTD_isError(res)) {
		/* FIXME:
		 * zstd does not expose stable error codes. The error enum may
		 * change between versions. Until upstream zstd stablizes the
		 * error codes, we have no way of knowing why the error occurs.
		 * zstd shouldn't fail to compress any input unless there isn't
		 * enough output space. We assume that is the cause and return
		 * the special error code for not enough output space.
		 */
		return 0;
	}

	return (int)res;
}
Пример #24
0
ZSTD_seekable_CStream* ZSTD_seekable_createCStream()
{
    ZSTD_seekable_CStream* zcs = malloc(sizeof(ZSTD_seekable_CStream));

    if (zcs == NULL) return NULL;

    memset(zcs, 0, sizeof(*zcs));

    zcs->cstream = ZSTD_createCStream();
    if (zcs->cstream == NULL) goto failed1;

    if (ZSTD_isError(ZSTD_seekable_frameLog_allocVec(&zcs->framelog))) goto failed2;

    return zcs;

failed2:
    ZSTD_freeCStream(zcs->cstream);
failed1:
    free(zcs);
    return NULL;
}
Пример #25
0
  static ezResult CompressZStd(ezArrayPtr<const ezUInt8> pUncompressedData, ezDynamicArray<ezUInt8>& out_Data)
  {
    size_t uiSizeBound = ZSTD_compressBound(pUncompressedData.GetCount());
    if(uiSizeBound > std::numeric_limits<ezUInt32>::max())
    {
      ezLog::Error("Can't compress since the output container can't hold enough elements ({0})", static_cast<ezUInt64>(uiSizeBound));
      return EZ_FAILURE;
    }

    out_Data.SetCountUninitialized(static_cast<ezUInt32>(uiSizeBound));

    size_t const cSize = ZSTD_compress(out_Data.GetData(), uiSizeBound, pUncompressedData.GetPtr(), pUncompressedData.GetCount(), 1);
    if (ZSTD_isError(cSize))
    {
      ezLog::Error("Compression failed with error: '{0}'.", ZSTD_getErrorName(cSize));
      return EZ_FAILURE;
    }

    out_Data.SetCount(static_cast<ezUInt32>(cSize));

    return EZ_SUCCESS;
  }
Пример #26
0
std::unique_ptr<IOBuf> ZSTDCodec::doUncompress(const IOBuf* data,
                                               uint64_t uncompressedLength) {
  size_t rc;
  auto out = IOBuf::createCombined(uncompressedLength);

  CHECK_GE(out->capacity(), uncompressedLength);
  CHECK_EQ(out->length(), 0);

  rc = ZSTD_decompress(
      out->writableTail(), out->capacity(), data->data(), data->length());

  if (ZSTD_isError(rc)) {
    throw std::runtime_error(to<std::string>(
          "ZSTD decompression returned an error: ",
          ZSTD_getErrorName(rc)));
  }

  out->append(rc);
  CHECK_EQ(out->length(), rc);

  return out;
}
Пример #27
0
static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdict)
{
    size_t fSize;
    void* const fBuff = loadFile_orDie(fname, &fSize);
    size_t const cBuffSize = ZSTD_compressBound(fSize);
    void* const cBuff = malloc_orDie(cBuffSize);

    ZSTD_CCtx* const cctx = ZSTD_createCCtx();
    size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict);
    if (ZSTD_isError(cSize)) {
        fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize));
        exit(7);
    }

    saveFile_orDie(oname, cBuff, cSize);

    /* success */
    printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname);

    ZSTD_freeCCtx(cctx);
    free(fBuff);
    free(cBuff);
}
Пример #28
0
static ssize_t
zstd_filter_read(struct archive_read_filter *self, const void **p)
{
	struct private_data *state;
	size_t decompressed;
	ssize_t avail_in;
	ZSTD_outBuffer out;
	ZSTD_inBuffer in;

	state = (struct private_data *)self->data;

	out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };

	/* Try to fill the output buffer. */
	while (out.pos < out.size && !state->eof) {
		if (!state->in_frame) {
			const size_t ret = ZSTD_initDStream(state->dstream);
			if (ZSTD_isError(ret)) {
				archive_set_error(&self->archive->archive,
				    ARCHIVE_ERRNO_MISC,
				    "Error initializing zstd decompressor: %s",
				    ZSTD_getErrorName(ret));
				return (ARCHIVE_FATAL);
			}
		}
		in.src = __archive_read_filter_ahead(self->upstream, 1,
		    &avail_in);
		if (avail_in < 0) {
			return avail_in;
		}
		if (in.src == NULL && avail_in == 0) {
			if (!state->in_frame) {
				/* end of stream */
				state->eof = 1;
				break;
			} else {
				archive_set_error(&self->archive->archive,
				    ARCHIVE_ERRNO_MISC,
				    "Truncated zstd input");
				return (ARCHIVE_FATAL);
			}
		}
		in.size = avail_in;
		in.pos = 0;

		{
			const size_t ret =
			    ZSTD_decompressStream(state->dstream, &out, &in);

			if (ZSTD_isError(ret)) {
				archive_set_error(&self->archive->archive,
				    ARCHIVE_ERRNO_MISC,
				    "Zstd decompression failed: %s",
				    ZSTD_getErrorName(ret));
				return (ARCHIVE_FATAL);
			}

			/* Decompressor made some progress */
			__archive_read_filter_consume(self->upstream, in.pos);

			/* ret guaranteed to be > 0 if frame isn't done yet */
			state->in_frame = (ret != 0);
		}
	}

	decompressed = out.pos;
	state->total_out += decompressed;
	if (decompressed == 0)
		*p = NULL;
	else
		*p = state->out_block;
	return (decompressed);
}
Пример #29
0
/*
* Finish off an encoded strip by flushing it.
*/
static int
LERCPostEncode(TIFF* tif)
{
        lerc_status lerc_ret;
        static const char module[] = "LERCPostEncode";
        LERCState *sp = EncoderState(tif);
        unsigned int numBytes = 0;
        unsigned int numBytesWritten = 0;
        TIFFDirectory *td = &tif->tif_dir;
        int use_mask = 0;
        unsigned dst_nbands = td->td_samplesperpixel;

        if( sp->uncompressed_offset != sp->uncompressed_size )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected number of bytes in the buffer");
            return 0;
        }

        /* Extract alpha mask (if containing only 0 and 255 values, */
        /* and compact array of regular bands */
        if( td->td_planarconfig == PLANARCONFIG_CONTIG &&
            td->td_extrasamples > 0 &&
            td->td_sampleinfo[td->td_extrasamples-1] == EXTRASAMPLE_UNASSALPHA &&
            GetLercDataType(tif) == 1 )
        {
            unsigned dst_stride = (td->td_samplesperpixel - 1) *
                                            (td->td_bitspersample / 8);
            unsigned src_stride = td->td_samplesperpixel *
                                            (td->td_bitspersample / 8);
            unsigned i = 0;
            unsigned nb_pixels = sp->segment_width * sp->segment_height;

            use_mask = 1;
            for( i = 0 ; i < nb_pixels; i++)
            {
                int v = sp->uncompressed_buffer[
                            i * src_stride + td->td_samplesperpixel - 1];
                if( v != 0 && v != 255 )
                {
                    use_mask = 0;
                    break;
                }
            }

            if( use_mask )
            {
                dst_nbands --;
                /* First pixels must use memmove due to overlapping areas */
                for( i = 0 ;i < dst_nbands && i < nb_pixels; i++)
                {
                    memmove( sp->uncompressed_buffer + i * dst_stride,
                            sp->uncompressed_buffer + i * src_stride,
                            dst_stride );
                    sp->mask_buffer[i] = sp->uncompressed_buffer[
                        i * src_stride + td->td_samplesperpixel - 1];
                }
                for(; i < nb_pixels; i++)
                {
                    memcpy( sp->uncompressed_buffer + i * dst_stride,
                            sp->uncompressed_buffer + i * src_stride,
                            dst_stride );
                    sp->mask_buffer[i] = sp->uncompressed_buffer[
                        i * src_stride + td->td_samplesperpixel - 1];
                }
            }
        }

#if 0
        lerc_ret = lerc_computeCompressedSize(
            sp->uncompressed_buffer,
            sp->lerc_version,
            GetLercDataType(tif),
            td->td_planarconfig == PLANARCONFIG_CONTIG ?
                dst_nbands : 1,
            sp->segment_width,
            sp->segment_height,
            1,
            use_mask ? sp->mask_buffer : NULL,
            sp->maxzerror,
            &numBytes);
        if( lerc_ret != 0 )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "lerc_computeCompressedSize() failed");
            return 0;
        }
#else
        numBytes = sp->uncompressed_alloc;
#endif

        if( sp->compressed_size < numBytes )
        {
            _TIFFfree(sp->compressed_buffer);
            sp->compressed_buffer = _TIFFmalloc(numBytes);
            if( !sp->compressed_buffer )
            {
                sp->compressed_size = 0;
                return 0;
            }
            sp->compressed_size = numBytes;
        }

        lerc_ret = lerc_encodeForVersion(
            sp->uncompressed_buffer,
            sp->lerc_version,
            GetLercDataType(tif),
            td->td_planarconfig == PLANARCONFIG_CONTIG ?
                dst_nbands : 1,
            sp->segment_width,
            sp->segment_height,
            1,
            use_mask ? sp->mask_buffer : NULL,
            sp->maxzerror,
            sp->compressed_buffer,
            sp->compressed_size,
            &numBytesWritten);
        if( lerc_ret != 0 )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "lerc_encode() failed");
            return 0;
        }
        assert( numBytesWritten < numBytes );

        if( sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE )
        {
            z_stream strm;
            int zlib_ret;

            memset(&strm, 0, sizeof(strm));
            strm.zalloc = NULL;
            strm.zfree = NULL;
            strm.opaque = NULL;
            zlib_ret = deflateInit(&strm, sp->zipquality);
            if( zlib_ret != Z_OK )
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "deflateInit() failed");
                return 0;
            }

            strm.avail_in = numBytesWritten;
            strm.next_in = sp->compressed_buffer;
            strm.avail_out = sp->uncompressed_alloc;
            strm.next_out = sp->uncompressed_buffer;
            zlib_ret = deflate(&strm, Z_FINISH);
            if( zlib_ret != Z_STREAM_END )
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "deflate() failed");
                deflateEnd(&strm);
                return 0;
            }
            {
                int ret;
                uint8* tif_rawdata_backup = tif->tif_rawdata;
                tif->tif_rawdata = sp->uncompressed_buffer;
                tif->tif_rawcc = sp->uncompressed_alloc - strm.avail_out;
                ret = TIFFFlushData1(tif);
                tif->tif_rawdata = tif_rawdata_backup;
                if( !ret )
                {
                    deflateEnd(&strm);
                    return 0;
                }
            }
            deflateEnd(&strm);
        }
        else if( sp->additional_compression == LERC_ADD_COMPRESSION_ZSTD )
        {
#ifdef ZSTD_SUPPORT
            size_t zstd_ret = ZSTD_compress( sp->uncompressed_buffer,
                                             sp->uncompressed_alloc,
                                             sp->compressed_buffer,
                                             numBytesWritten,
                                             sp->zstd_compress_level );
            if( ZSTD_isError(zstd_ret) ) {
                TIFFErrorExt(tif->tif_clientdata, module,
                            "Error in ZSTD_compress(): %s",
                            ZSTD_getErrorName(zstd_ret));
                return 0;
            }

            {
                int ret;
                uint8* tif_rawdata_backup = tif->tif_rawdata;
                tif->tif_rawdata = sp->uncompressed_buffer;
                tif->tif_rawcc = zstd_ret;
                ret = TIFFFlushData1(tif);
                tif->tif_rawdata = tif_rawdata_backup;
                if( !ret )
                {
                    return 0;
                }
            }
#else
            TIFFErrorExt(tif->tif_clientdata, module, "ZSTD support missing");
            return 0;
#endif
        }
        else if( sp->additional_compression != LERC_ADD_COMPRESSION_NONE )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unhandled additional compression");
            return 0;
        }
        else
        {
            int ret;
            uint8* tif_rawdata_backup = tif->tif_rawdata;
            tif->tif_rawdata = sp->compressed_buffer;
            tif->tif_rawcc = numBytesWritten;
            ret = TIFFFlushData1(tif);
            tif->tif_rawdata = tif_rawdata_backup;
            if( !ret )
                return 0;
        }

        return 1;
}
Пример #30
0
/*
* Setup state for decoding a strip.
*/
static int
LERCPreDecode(TIFF* tif, uint16 s)
{
        static const char module[] = "LERCPreDecode";
        lerc_status lerc_ret;
        TIFFDirectory *td = &tif->tif_dir;
        LERCState* sp = DecoderState(tif);
        int lerc_data_type;
        unsigned int infoArray[8];
        unsigned nomask_bands = td->td_samplesperpixel;
        int ndims;
        int use_mask = 0;
        uint8* lerc_data = tif->tif_rawcp;
        unsigned int lerc_data_size = (unsigned int)tif->tif_rawcc;

        (void) s;
        assert(sp != NULL);

        lerc_data_type = GetLercDataType(tif);
        if( lerc_data_type < 0 )
            return 0;

        if( !SetupUncompressedBuffer(tif, sp, module) )
            return 0;

        if( sp->additional_compression != LERC_ADD_COMPRESSION_NONE )
        {
            if( sp->compressed_size < sp->uncompressed_alloc )
            {
                _TIFFfree(sp->compressed_buffer);
                sp->compressed_buffer = _TIFFmalloc(sp->uncompressed_alloc);
                if( !sp->compressed_buffer )
                {
                    sp->compressed_size = 0;
                    return 0;
                }
                sp->compressed_size = sp->uncompressed_alloc;
            }
        }

        if( sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE )
        {
            z_stream strm;
            int zlib_ret;

            memset(&strm, 0, sizeof(strm));
            strm.zalloc = NULL;
            strm.zfree = NULL;
            strm.opaque = NULL;
            zlib_ret = inflateInit(&strm);
            if( zlib_ret != Z_OK )
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "inflateInit() failed");
                inflateEnd(&strm);
                return 0;
            }

            strm.avail_in = (uInt)tif->tif_rawcc;
            strm.next_in = tif->tif_rawcp;
            strm.avail_out = sp->compressed_size;
            strm.next_out = sp->compressed_buffer;
            zlib_ret = inflate(&strm, Z_FINISH);
            if( zlib_ret != Z_STREAM_END && zlib_ret != Z_OK )
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "inflate() failed");
                inflateEnd(&strm);
                return 0;
            }
            lerc_data = sp->compressed_buffer;
            lerc_data_size = sp->compressed_size - strm.avail_out;
            inflateEnd(&strm);
        }
        else if( sp->additional_compression == LERC_ADD_COMPRESSION_ZSTD )
        {
#ifdef ZSTD_SUPPORT
            size_t zstd_ret;

            zstd_ret = ZSTD_decompress(sp->compressed_buffer,
                                       sp->compressed_size,
                                       tif->tif_rawcp,
                                       tif->tif_rawcc);
            if( ZSTD_isError(zstd_ret) ) {
                TIFFErrorExt(tif->tif_clientdata, module,
                            "Error in ZSTD_decompress(): %s",
                            ZSTD_getErrorName(zstd_ret));
                return 0;
            }

            lerc_data = sp->compressed_buffer;
            lerc_data_size = (unsigned int)zstd_ret;
#else
            TIFFErrorExt(tif->tif_clientdata, module, "ZSTD support missing");
            return 0;
#endif
        }
        else if( sp->additional_compression != LERC_ADD_COMPRESSION_NONE )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unhandled additional compression");
            return 0;
        }

        lerc_ret = lerc_getBlobInfo(
            lerc_data,
            lerc_data_size,
            infoArray,
            NULL,
            8,
            0);
        if( lerc_ret != 0 )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "lerc_getBlobInfo() failed");
            return 0;
        }

        /* If the configuration is compatible of a LERC mask, and that the */
        /* LERC info has dim == samplesperpixel - 1, then there is a LERC */
        /* mask. */
        if( td->td_planarconfig == PLANARCONFIG_CONTIG &&
            td->td_extrasamples > 0 &&
            td->td_sampleinfo[td->td_extrasamples-1] == EXTRASAMPLE_UNASSALPHA &&
            GetLercDataType(tif) == 1 &&
            infoArray[2] == td->td_samplesperpixel - 1U )
        {
            use_mask = 1;
            nomask_bands --;
        }

        ndims = td->td_planarconfig == PLANARCONFIG_CONTIG ?
                                                nomask_bands : 1;

        /* Info returned in infoArray is { version, dataType, nDim, nCols,
            nRows, nBands, nValidPixels, blobSize } */
        if( infoArray[0] != (unsigned)sp->lerc_version )
        {
            TIFFWarningExt(tif->tif_clientdata, module,
                         "Unexpected version number: %d. Expected: %d",
                         infoArray[0], sp->lerc_version);
        }
        if( infoArray[1] != (unsigned)lerc_data_type )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected dataType: %d. Expected: %d",
                         infoArray[1], lerc_data_type);
            return 0;
        }
        if( infoArray[2] != (unsigned)ndims )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected nDim: %d. Expected: %d",
                         infoArray[2], ndims);
            return 0;
        }
        if( infoArray[3] != sp->segment_width )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected nCols: %d. Expected: %du",
                         infoArray[3], sp->segment_width);
            return 0;
        }
        if( infoArray[4] != sp->segment_height )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected nRows: %d. Expected: %u",
                         infoArray[4], sp->segment_height);
            return 0;
        }
        if( infoArray[5] != 1 )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected nBands: %d. Expected: %d",
                         infoArray[5], 1);
            return 0;
        }
        if( infoArray[7] != lerc_data_size )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Unexpected blobSize: %d. Expected: %u",
                         infoArray[7],
                         lerc_data_size);
            return 0;
        }

        lerc_ret = lerc_decode(
            lerc_data,
            lerc_data_size,
            use_mask ? sp->mask_buffer : NULL,
            ndims,
            sp->segment_width,
            sp->segment_height,
            1,
            lerc_data_type,
            sp->uncompressed_buffer);
        if( lerc_ret != 0 )
        {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "lerc_decode() failed");
            return 0;
        }

        /* Interleave alpha mask with other samples. */
        if( use_mask )
        {
            unsigned src_stride =
                (td->td_samplesperpixel - 1) * (td->td_bitspersample / 8);
            unsigned dst_stride =
                td->td_samplesperpixel * (td->td_bitspersample / 8);
            unsigned i = sp->segment_width * sp->segment_height;
            /* Operate from end to begin to be able to move in place */
            while( i > 0 && i > nomask_bands )
            {
                i --;
                sp->uncompressed_buffer[
                    i * dst_stride + td->td_samplesperpixel - 1] =
                        255 * sp->mask_buffer[i];
                memcpy( sp->uncompressed_buffer + i * dst_stride,
                        sp->uncompressed_buffer + i * src_stride,
                        src_stride );
            }
            /* First pixels must use memmove due to overlapping areas */
            while( i > 0  )
            {
                i --;
                sp->uncompressed_buffer[
                    i * dst_stride + td->td_samplesperpixel - 1] =
                        255 * sp->mask_buffer[i];
                memmove( sp->uncompressed_buffer + i * dst_stride,
                        sp->uncompressed_buffer + i * src_stride,
                        src_stride );
            }
        }

        return 1;
}