mariadb/mysys/my_compress.c
Marko Mäkelä 4faef6e240 Cleanup: Remove IF_VALGRIND
The purpose of the compress() wrapper my_compress_buffer() was twofold:
silence Valgrind warnings about uninitialized memory access before
zlib 1.2.4, and have PERFORMANCE_SCHEMA instrumentation of some zlib
related memory allocation. Because of PERFORMANCE_SCHEMA, we cannot
trivially replace my_compress_buffer() with compress().

az_open(): Remove a crc32() call. Any CRC of the empty string is 0.
2022-04-25 09:40:40 +03:00

186 lines
4.9 KiB
C

/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
/* Written by Sinisa Milivojevic <sinisa@mysql.com> */
#include <mysys_priv.h>
#ifdef HAVE_COMPRESS
#include <my_sys.h>
#ifndef SCO
#include <m_string.h>
#endif
#include <zlib.h>
/*
This replaces the packet with a compressed packet
SYNOPSIS
my_compress()
packet Data to compress. This is is replaced with the compressed data.
len Length of data to compress at 'packet'
complen out: 0 if packet was not compressed
RETURN
1 error. 'len' is not changed'
0 ok. In this case 'len' contains the size of the compressed packet
*/
my_bool my_compress(uchar *packet, size_t *len, size_t *complen)
{
DBUG_ENTER("my_compress");
if (*len < MIN_COMPRESS_LENGTH)
{
*complen=0;
DBUG_PRINT("note",("Packet too short: Not compressed"));
}
else
{
uchar *compbuf=my_compress_alloc(packet,len,complen);
if (!compbuf)
DBUG_RETURN(*complen ? 0 : 1);
memcpy(packet,compbuf,*len);
my_free(compbuf);
}
DBUG_RETURN(0);
}
void *my_az_allocator(void *dummy __attribute__((unused)), unsigned int items,
unsigned int size)
{
return my_malloc(key_memory_my_compress_alloc, (size_t)items*(size_t)size,
MYF(0));
}
void my_az_free(void *dummy __attribute__((unused)), void *address)
{
my_free(address);
}
/*
This works like zlib compress(), but using custom memory allocators to work
better with my_malloc leak detection and Valgrind.
*/
int my_compress_buffer(uchar *dest, size_t *destLen,
const uchar *source, size_t sourceLen)
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
stream.next_out = (Bytef*)dest;
stream.avail_out = (uInt)*destLen;
if ((size_t)stream.avail_out != *destLen)
return Z_BUF_ERROR;
stream.zalloc = (alloc_func)my_az_allocator;
stream.zfree = (free_func)my_az_free;
stream.opaque = (voidpf)0;
err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
if (err != Z_OK) return err;
err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
deflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = deflateEnd(&stream);
return err;
}
uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen)
{
uchar *compbuf;
int res;
*complen= *len * 120 / 100 + 12;
if (!(compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc,
*complen, MYF(MY_WME))))
return 0;
res= my_compress_buffer(compbuf, complen, packet, *len);
if (res != Z_OK)
{
my_free(compbuf);
return 0;
}
if (*complen >= *len)
{
*complen= 0;
my_free(compbuf);
DBUG_PRINT("note",("Packet got longer on compression; Not compressed"));
return 0;
}
/* Store length of compressed packet in *len */
swap_variables(size_t, *len, *complen);
return compbuf;
}
/*
Uncompress packet
SYNOPSIS
my_uncompress()
packet Compressed data. This is is replaced with the original data.
len Length of compressed data
complen Length of the packet buffer (must be enough for the original
data)
RETURN
1 error
0 ok. In this case 'complen' contains the updated size of the
real data.
*/
my_bool my_uncompress(uchar *packet, size_t len, size_t *complen)
{
uLongf tmp_complen;
DBUG_ENTER("my_uncompress");
if (*complen) /* If compressed */
{
uchar *compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc,
*complen,MYF(MY_WME));
int error;
if (!compbuf)
DBUG_RETURN(1); /* Not enough memory */
tmp_complen= (uLongf) *complen;
error= uncompress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet,
(uLong) len);
*complen= tmp_complen;
if (error != Z_OK)
{ /* Probably wrong packet */
DBUG_PRINT("error",("Can't uncompress packet, error: %d",error));
my_free(compbuf);
DBUG_RETURN(1);
}
memcpy(packet, compbuf, *complen);
my_free(compbuf);
}
else
*complen= len;
DBUG_RETURN(0);
}
#endif /* HAVE_COMPRESS */