summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--include/freetype/freetype.h6
-rw-r--r--src/base/ftobjs.c9
3 files changed, 32 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index d8ef3e2f0..5a40b09c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2021-07-13 Oleg Oshmyan <chortos@inbox.lv>
+
+ [base] Reject combinations of incompatible `FT_OPEN_XXX` flags.
+
+ The three modes are mutually exclusive, and the documentation of the
+ `FT_OPEN_XXX` constants notes this. However, there was no check to
+ validate this in the code, and the documentation on `FT_Open_Args`
+ claimed that the corresponding bits were checked in a well-defined
+ order, implying it was valid (if useless) to specify more than one.
+ Ironically, this documented order did not agree with the actual
+ code, so it could not be relied upon; hopefully, nobody did this and
+ nobody will be hurt by the new validation.
+
+ Even if multiple mode bits were allowed, they could cause memory
+ leaks: if both `FT_OPEN_STREAM` and `stream` are set along with
+ either `FT_OPEN_MEMORY` or `FT_OPEN_PATHNAME`, then `FT_Stream_New`
+ allocated a new stream but `FT_Open_Face` marked it as an 'external'
+ stream, so the stream object was never released.
+
+ * src/base/ftobjs.c (FT_Stream_New): Reject incompatible
+ `FT_OPEN_XXX` flags.
+
2021-07-12 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
* meson.build: Fix build for other UNIX systems (e.g., FreeBSD).
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index f393e3de5..598abd8c9 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -2113,8 +2113,7 @@ FT_BEGIN_HEADER
* Extra parameters passed to the font driver when opening a new face.
*
* @note:
- * The stream type is determined by the contents of `flags` that are
- * tested in the following order by @FT_Open_Face:
+ * The stream type is determined by the contents of `flags`:
*
* If the @FT_OPEN_MEMORY bit is set, assume that this is a memory file
* of `memory_size` bytes, located at `memory_address`. The data are not
@@ -2127,6 +2126,9 @@ FT_BEGIN_HEADER
* Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this is a
* normal file and use `pathname` to open it.
*
+ * If none of the above bits are set or if multiple are set at the same
+ * time, the flags are invalid and @FT_Open_Face fails.
+ *
* If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to open
* the file with the driver whose handler is in `driver`.
*
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 4a8014542..f7b2b3f18 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -197,6 +197,7 @@
FT_Error error;
FT_Memory memory;
FT_Stream stream = NULL;
+ FT_UInt mode;
*astream = NULL;
@@ -208,13 +209,15 @@
return FT_THROW( Invalid_Argument );
memory = library->memory;
+ mode = args->flags &
+ ( FT_OPEN_MEMORY | FT_OPEN_STREAM | FT_OPEN_PATHNAME );
if ( FT_NEW( stream ) )
goto Exit;
stream->memory = memory;
- if ( args->flags & FT_OPEN_MEMORY )
+ if ( mode == FT_OPEN_MEMORY )
{
/* create a memory-based stream */
FT_Stream_OpenMemory( stream,
@@ -224,13 +227,13 @@
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
- else if ( args->flags & FT_OPEN_PATHNAME )
+ else if ( mode == FT_OPEN_PATHNAME )
{
/* create a normal system stream */
error = FT_Stream_Open( stream, args->pathname );
stream->pathname.pointer = args->pathname;
}
- else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
+ else if ( ( mode == FT_OPEN_STREAM ) && args->stream )
{
/* use an existing, user-provided stream */