diff options
author | Ben Wagner <bungeman@chromium.org> | 2023-01-12 22:43:08 -0500 |
---|---|---|
committer | Werner Lemberg <wl@gnu.org> | 2023-01-17 08:54:11 +0100 |
commit | 0d4f887c790dc639902cb9ac89f9d099062530cb (patch) | |
tree | 3100d40251f67ca15b366dd6750f76d97a98bacd | |
parent | 13983b058e840b144238e8c3f352a7e31ce53b86 (diff) | |
download | freetype2-0d4f887c790dc639902cb9ac89f9d099062530cb.tar.gz |
[base] Always close user-provided stream.
The `FT_Open_Face` documentation states
> If `FT_OPEN_STREAM` is set in `args->flags`, the stream in `args->stream`
> is automatically closed before this function returns any error (including
> `FT_Err_Invalid_Argument`).
However, if the user provides a stream in `args.stream` with
`FT_OPEN_STREAM` set and a `close` function, but then for some reason passes
NULL for `aface` and a non-negative `face_index`, the error
`Invalid_Argument` is returned but the `close` callback will not be called
on the user-provided stream. This may cause resource leaks if the caller is
depending on the `close` callback to free resources.
The difficulty is that a user may fill out a `FT_StreamRec` and pass its
address as `args.stream`, but the stream isn't really 'live' until
`FT_Stream_New` is called on it (and `memory` is set). In particular, it
cannot really be cleaned up properly in `ft_open_face_internal` until the
stream pointer has been copied into the `stream` local variable.
* src/base/ftobj.c (ft_open_face_internal): Ensure that user-provided
`args.stream.close` is called even with early errors.
-rw-r--r-- | src/base/ftobjs.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 7dcc7db58..cd20f374f 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -2544,7 +2544,7 @@ /* test for valid `library' delayed to `FT_Stream_New' */ - if ( ( !aface && face_index >= 0 ) || !args ) + if ( !args ) return FT_THROW( Invalid_Argument ); external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && @@ -2555,6 +2555,14 @@ if ( error ) goto Fail3; + /* Do this error check after `FT_Stream_New` to ensure that the */ + /* 'close' callback is called. */ + if ( !aface && face_index >= 0 ) + { + error = FT_THROW( Invalid_Argument ); + goto Fail3; + } + memory = library->memory; /* If the font driver is specified in the `args' structure, use */ |