From 2fbe8cc9b3f6f443ccccfaa485b05966aacc65d9 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Mar 2012 12:13:28 +0100 Subject: Fix port leaks in zlib zip,unzip,gzip,gunzip,compress and uncompress did not close the port when given invalid data argument. Fixed by putting close in "try-after". A closed port could in same cases get stuck in limbo due to data in io-queue. Fixed by adding a flush callback. --- erts/emulator/drivers/common/zlib_drv.c | 10 ++++- erts/preloaded/ebin/zlib.beam | Bin 12432 -> 12804 bytes erts/preloaded/src/zlib.erl | 72 +++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 25 deletions(-) (limited to 'erts') diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c index da4a17db1a..a4b02b845e 100644 --- a/erts/emulator/drivers/common/zlib_drv.c +++ b/erts/emulator/drivers/common/zlib_drv.c @@ -64,6 +64,7 @@ static int zlib_init(void); static ErlDrvData zlib_start(ErlDrvPort port, char* buf); static void zlib_stop(ErlDrvData e); +static void zlib_flush(ErlDrvData e); static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static void zlib_outputv(ErlDrvData drv_data, ErlIOVec *ev); @@ -82,7 +83,7 @@ ErlDrvEntry zlib_driver_entry = { NULL, /* timeout */ zlib_outputv, NULL, /* read_async */ - NULL, /* flush */ + zlib_flush, NULL, /* call */ NULL, /* event */ ERL_DRV_EXTENDED_MARKER, @@ -410,6 +411,13 @@ static void zlib_stop(ErlDrvData e) driver_free(d); } +static void zlib_flush(ErlDrvData drv_data) +{ + ZLibData* d = (ZLibData*) drv_data; + + driver_deq(d->port, driver_sizeq(d->port)); +} + static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam index bf88a51502..7a1f896d36 100644 Binary files a/erts/preloaded/ebin/zlib.beam and b/erts/preloaded/ebin/zlib.beam differ diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl index 210532edac..71b730016d 100644 --- a/erts/preloaded/src/zlib.erl +++ b/erts/preloaded/src/zlib.erl @@ -349,10 +349,14 @@ getQSize(Z) -> Compressed :: binary(). compress(Data) -> Z = open(), - deflateInit(Z, default), - Bs = deflate(Z, Data, finish), - deflateEnd(Z), - close(Z), + Bs = try + deflateInit(Z, default), + B = deflate(Z, Data, finish), + deflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec uncompress(Data) -> Decompressed when @@ -364,10 +368,14 @@ uncompress(Data) -> if Size >= 8 -> Z = open(), - inflateInit(Z), - Bs = inflate(Z, Data), - inflateEnd(Z), - close(Z), + Bs = try + inflateInit(Z), + B = inflate(Z, Data), + inflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs); true -> erlang:error(data_error) @@ -383,10 +391,14 @@ uncompress(Data) -> Compressed :: binary(). zip(Data) -> Z = open(), - deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default), - Bs = deflate(Z, Data, finish), - deflateEnd(Z), - close(Z), + Bs = try + deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default), + B = deflate(Z, Data, finish), + deflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec unzip(Data) -> Decompressed when @@ -394,10 +406,14 @@ zip(Data) -> Decompressed :: binary(). unzip(Data) -> Z = open(), - inflateInit(Z, -?MAX_WBITS), - Bs = inflate(Z, Data), - inflateEnd(Z), - close(Z), + Bs = try + inflateInit(Z, -?MAX_WBITS), + B = inflate(Z, Data), + inflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec gzip(Data) -> Compressed when @@ -405,10 +421,14 @@ unzip(Data) -> Compressed :: binary(). gzip(Data) -> Z = open(), - deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default), - Bs = deflate(Z, Data, finish), - deflateEnd(Z), - close(Z), + Bs = try + deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default), + B = deflate(Z, Data, finish), + deflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec gunzip(Data) -> Decompressed when @@ -416,10 +436,14 @@ gzip(Data) -> Decompressed :: binary(). gunzip(Data) -> Z = open(), - inflateInit(Z, 16+?MAX_WBITS), - Bs = inflate(Z, Data), - inflateEnd(Z), - close(Z), + Bs = try + inflateInit(Z, 16+?MAX_WBITS), + B = inflate(Z, Data), + inflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec collect(zstream()) -> iolist(). -- cgit v1.2.3