8000 Fix LZF decompression logic. (#2065) · phpredis/phpredis@0719c1e · GitHub
[go: up one dir, main page]

Skip to content

Commit 0719c1e

Browse files
Fix LZF decompression logic. (#2065)
* Fix LZF decompression logic. Rework how we decompress LZF data. Previously it was possible to encounter a double-free, if the error was not E2BIG. * .
1 parent 56633e1 commit 0719c1e

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

library.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3030,27 +3030,22 @@ redis_uncompress(RedisSock *redis_sock, char **dst, size_t *dstlen, const char *
30303030
case REDIS_COMPRESSION_LZF:
30313031
#ifdef HAVE_REDIS_LZF
30323032
{
3033-
char *data;
3034-
int i;
3033+
char *data = NULL;
30353034
uint32_t res;
3035+
int i;
30363036

30373037
if (len == 0)
30383038
break;
30393039

3040-
/* start from two-times bigger buffer and
3041-
* increase it exponentially if needed */
3040+
/* Grow our buffer until we succeed or get a non E2BIG error */
30423041
errno = E2BIG;
30433042
for (i = 2; errno == E2BIG; i *= 2) {
3044-
data = emalloc(i * len);
3045-
if ((res = lzf_decompress(src, len, data, i * len)) == 0) {
3046-
/* errno != E2BIG will brake for loop */
3047-
efree(data);
3048-
continue;
3043+
data = erealloc(data, len * i);
3044+
if ((res = lzf_decompress(src, len, data, len * i)) > 0) {
3045+
*dst = data;
3046+
*dstlen = res;
3047+
return 1;
30493048
}
3050-
3051-
*dst = data;
3052-
*dstlen = res;
3053-
return 1;
30543049
}
30553050

30563051
efree(data);

tests/RedisTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4730,6 +4730,14 @@ public function testCompressionLZF()
47304730
if (!defined('Redis::COMPRESSION_LZF')) {
47314731
$this->markTestSkipped();
47324732
}
4733+
4734+
/* Don't crash on improperly compressed LZF data */
4735+
$payload = 'not-actually-lzf-compressed';
4736+
$this->redis->set('badlzf', $payload);
4737+
$this->redis->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_LZF);
4738+
$this->assertEquals($payload, $this->redis->get('badlzf'));
4739+
$this->redis->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_NONE);
4740+
47334741
$this->checkCompression(Redis::COMPRESSION_LZF, 0);
47344742
}
47354743

0 commit comments

Comments
 (0)
0