From 06e21ffedfac81edfa79137959141a9d78b6f858 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Tue, 18 May 2021 14:49:50 -0400 Subject: [PATCH] [gzip] Use exact type for `ft_gzip_alloc` and `ft_gzip_free`. While a function pointer may be cast to another function pointer type, it is required to cast the function pointer back to the original function pointer type before calling it. If a parameter is a pointer the exact pointer type is required. Using a pointer to a different underlying type is technically undefined behavior. The wrapper functions `ft_gzip_alloc` and `ft_gzip_free` took `FT_Memory` (a `FT_MemoryRec_*`) instead of `voidpf` (`void*`), so when gzip calls these callbacks through `alloc_func` or `free_func` it invokes undefined behavior. On most platforms this works out as expected, but newer undefined behavior detectors and targets like wasm can detect this and will produce an error. * src/gzip/ftgzip.c (ft_gzip_alloc, ft_gzip_free): Update signatures to exactly match `alloc_func` and `free_func`, respectively. Internally, cast the `void*` opaque pointer to `FT_Memory`. --- ChangeLog | 20 ++++++++++++++++++++ src/gzip/ftgzip.c | 30 +++++++++++++++++------------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ec6870fc..d3583a41b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2021-05-19 Ben Wagner + + [gzip] Use exact type for `ft_gzip_alloc` and `ft_gzip_free`. + + While a function pointer may be cast to another function pointer + type, it is required to cast the function pointer back to the + original function pointer type before calling it. If a parameter is + a pointer the exact pointer type is required. Using a pointer to a + different underlying type is technically undefined behavior. The + wrapper functions `ft_gzip_alloc` and `ft_gzip_free` took + `FT_Memory` (a `FT_MemoryRec_*`) instead of `voidpf` (`void*`), so + when gzip calls these callbacks through `alloc_func` or `free_func` + it invokes undefined behavior. On most platforms this works out as + expected, but newer undefined behavior detectors and targets like + wasm can detect this and will produce an error. + + * src/gzip/ftgzip.c (ft_gzip_alloc, ft_gzip_free): Update signatures + to exactly match `alloc_func` and `free_func`, respectively. + Internally, cast the `void*` opaque pointer to `FT_Memory`. + 2021-05-18 Alexei Podtelezhnikov Prioritize the anti-aliasing renderer module. diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c index 0dc0a6177..788a37b31 100644 --- a/src/gzip/ftgzip.c +++ b/src/gzip/ftgzip.c @@ -121,13 +121,14 @@ 'malloc/free' */ static voidpf - ft_gzip_alloc( FT_Memory memory, - uInt items, - uInt size ) + ft_gzip_alloc( voidpf opaque, + uInt items, + uInt size ) { - FT_ULong sz = (FT_ULong)size * items; + FT_Memory memory = (FT_Memory)opaque; + FT_ULong sz = (FT_ULong)size * items; FT_Error error; - FT_Pointer p = NULL; + FT_Pointer p = NULL; /* allocate and zero out */ @@ -137,9 +138,12 @@ static void - ft_gzip_free( FT_Memory memory, - voidpf address ) + ft_gzip_free( voidpf opaque, + voidpf address ) { + FT_Memory memory = (FT_Memory)opaque; + + FT_MEM_FREE( address ); } @@ -151,14 +155,14 @@ unsigned items, unsigned size ) { - return ft_gzip_alloc( (FT_Memory)opaque, items, size ); + return ft_gzip_alloc( opaque, items, size ); } local void zcfree( voidpf opaque, voidpf ptr ) { - ft_gzip_free( (FT_Memory)opaque, ptr ); + ft_gzip_free( opaque, ptr ); } #endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */ @@ -305,8 +309,8 @@ } /* initialize zlib -- there is no zlib header in the compressed stream */ - zstream->zalloc = (alloc_func)ft_gzip_alloc; - zstream->zfree = (free_func) ft_gzip_free; + zstream->zalloc = ft_gzip_alloc; + zstream->zfree = ft_gzip_free; zstream->opaque = stream->memory; zstream->avail_in = 0; @@ -742,8 +746,8 @@ stream.next_out = output; stream.avail_out = (uInt)*output_len; - stream.zalloc = (alloc_func)ft_gzip_alloc; - stream.zfree = (free_func) ft_gzip_free; + stream.zalloc = ft_gzip_alloc; + stream.zfree = ft_gzip_free; stream.opaque = memory; /* This is a temporary fix and will be removed once the internal