Commit 93866bec77bee6479d8103175562c4fe472c3529

Alexei Podtelezhnikov 2021-09-21T23:14:42

[builds/windows] Revert back to `CreateFileA` only. Calling `CreateFileW` without making sure that the patname is really `wchar_t` is a bad idea and can lead to unpredictable overreads. For Windows CE, we impelemnt the missing API. Fixes #1098 and !76 again. * builds/windows/ftsystem.c (FT_Stream_Open): Call `CreateFileA`. [_WIN32_WCE] (CreateFileA, FileSizeEx): Implement missing interfaces.

diff --git a/builds/windows/ftsystem.c b/builds/windows/ftsystem.c
index 69ef494..bab7b31 100644
--- a/builds/windows/ftsystem.c
+++ b/builds/windows/ftsystem.c
@@ -196,6 +196,61 @@
   }
 
 
+#ifdef _WIN32_WCE
+
+  FT_LOCAL_DEF( HANDLE )
+  CreateFileA( LPCSTR                lpFileName,
+               DWORD                 dwDesiredAccess,
+               DWORD                 dwShareMode,
+               LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+               DWORD                 dwCreationDisposition,
+               DWORD                 dwFlagsAndAttributes,
+               HANDLE                hTemplateFile )
+  {
+    int            len;
+    LPWSTR         lpFileNameW;
+
+
+    /* allocate memory space for converted path name */
+    len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
+                               lpFileName, -1, NULL, 0 );
+
+    lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
+
+    if ( !len || !lpFileNameW )
+    {
+      FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
+      return INVALID_HANDLE_VALUE;
+    }
+
+    /* now it is safe to do the translation */
+    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
+                         lpFileName, -1, lpFileNameW, len );
+
+    /* open the file */
+    return CreateFileW( lpFileNameW, dwDesiredAccess, dwShareMode,
+                        lpSecurityAttributes, dwCreationDisposition,
+                        dwFlagsAndAttributes, hTemplateFile );
+  }
+
+
+  FT_LOCAL_DEF( BOOL )
+  GetFileSizeEx( HANDLE         hFile,
+                 PLARGE_INTEGER lpFileSize )
+  {
+    lpFileSize->u.LowPart = GetFileSize( hFile,
+                                         (DWORD *)&lpFileSize->u.HighPart );
+
+    if ( lpFileSize->u.LowPart == INVALID_FILE_SIZE &&
+         GetLastError() != NO_ERROR                 )
+      return FALSE;
+    else
+      return TRUE;
+  }
+
+#endif /* _WIN32_WCE */
+
+
   /* documentation is in ftobjs.h */
 
   FT_BASE_DEF( FT_Error )
@@ -211,36 +266,16 @@
       return FT_THROW( Invalid_Stream_Handle );
 
     /* open the file */
-    file = CreateFile( (LPCTSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
-                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
+    file = CreateFileA( (LPCSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
+                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
     if ( file == INVALID_HANDLE_VALUE )
     {
-      /* fall back on the alernative interface */
-#ifdef UNICODE
-      file = CreateFileA( (LPCSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
-                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
-#else
-      file = CreateFileW( (LPCWSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
-                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
-#endif
-
-      if ( file == INVALID_HANDLE_VALUE )
-      {
-        FT_ERROR(( "FT_Stream_Open:" ));
-        FT_ERROR(( " could not open `%s'\n", filepathname ));
-        return FT_THROW( Cannot_Open_Resource );
-      }
+      FT_ERROR(( "FT_Stream_Open:" ));
+      FT_ERROR(( " could not open `%s'\n", filepathname ));
+      return FT_THROW( Cannot_Open_Resource );
     }
 
-#if defined _WIN32_WCE || defined _WIN32_WINDOWS || \
-    (defined _WIN32_WINNT && _WIN32_WINNT <= 0x0400)
-    /* Use GetFileSize() for legacy Windows */
-    size.u.LowPart = GetFileSize( file, (DWORD *)&size.u.HighPart );
-    if ( size.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR )
-#else
-    /* Use GetFileSizeEx() for modern Windows */
     if ( GetFileSizeEx( file, &size ) == FALSE )
-#endif
     {
       FT_ERROR(( "FT_Stream_Open:" ));
       FT_ERROR(( " could not retrieve size of file `%s'\n", filepathname ));