diff -up freetype2/ChangeLog.21 freetype2/ChangeLog.21 --- freetype2/ChangeLog.21 Mon Mar 12 01:23:08 2007 +++ freetype2/ChangeLog.21 Thu Jun 14 11:46:25 2007 @@ -6391,7 +6391,7 @@ * include/freetype/internal/fnttypes.h (WinFNT_HeaderRec): Increase size of `reserved2' to avoid memory overwrites. -2003-01-08 Huw Dawies +2003-01-08 Huw Davies * src/winfonts/winfnt.c (winfnt_header_fields): Read 16 bytes into `reserved2', not `reserved'. Only in freetype2/objs: debug_st diff -up freetype2/src/winfonts/winfnt.c freetype2/src/winfonts/winfnt.c --- freetype2/src/winfonts/winfnt.c Mon Jun 11 10:18:34 2007 +++ freetype2/src/winfonts/winfnt.c Thu Jun 14 11:50:57 2007 @@ -6,6 +6,8 @@ /* */ /* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* Copyright 2003 Huw D M Davies for Codeweavers */ +/* Copyright 2007 Dmitry Timoshkov for Codeweavers */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -62,6 +64,81 @@ FT_FRAME_END }; + static const FT_Frame_Field winpe32_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE32_HeaderRec + + FT_FRAME_START( 248 ), + FT_FRAME_ULONG_LE ( magic ), /* PE00 */ + FT_FRAME_USHORT_LE ( machine ), /* 0x014c - i386 */ + FT_FRAME_USHORT_LE ( number_of_sections ), + FT_FRAME_SKIP_BYTES( 12 ), + FT_FRAME_USHORT_LE ( size_of_optional_header ), + FT_FRAME_SKIP_BYTES( 2 ), + FT_FRAME_USHORT_LE ( magic32 ), /* 0x10b */ + FT_FRAME_SKIP_BYTES( 110 ), + FT_FRAME_ULONG_LE ( rsrc_virtual_address ), + FT_FRAME_ULONG_LE ( rsrc_size ), + FT_FRAME_SKIP_BYTES( 104 ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe32_section_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE32_SectionRec + + FT_FRAME_START( 40 ), + FT_FRAME_BYTES ( name, 8 ), + FT_FRAME_SKIP_BYTES( 4 ), + FT_FRAME_ULONG_LE ( virtual_address ), + FT_FRAME_ULONG_LE ( size_of_raw_data ), + FT_FRAME_ULONG_LE ( pointer_to_raw_data ), + FT_FRAME_SKIP_BYTES( 16 ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe_rsrc_dir_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE_RsrcDirRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG_LE ( characteristics ), + FT_FRAME_ULONG_LE ( time_date_stamp ), + FT_FRAME_USHORT_LE ( major_version ), + FT_FRAME_USHORT_LE ( minor_version ), + FT_FRAME_USHORT_LE ( number_of_named_entries ), + FT_FRAME_USHORT_LE ( number_of_id_entries ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe_rsrc_dir_entry_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE_RsrcDirEntryRec + + FT_FRAME_START( 8 ), + FT_FRAME_ULONG_LE ( name ), + FT_FRAME_ULONG_LE ( offset ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe_rsrc_data_entry_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE_RsrcDataEntryRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG_LE ( offset_to_data ), + FT_FRAME_ULONG_LE ( size ), + FT_FRAME_ULONG_LE ( code_page ), + FT_FRAME_ULONG_LE ( reserved ), + FT_FRAME_END + + }; + static const FT_Frame_Field winfnt_header_fields[] = { #undef FT_STRUCTURE @@ -213,6 +290,7 @@ /* yes, now look for an NE header in the file */ WinNE_HeaderRec ne_header; + FT_TRACE2(( "MZ signature found\n" )); if ( FT_STREAM_SEEK( mz_header.lfanew ) || FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) ) @@ -228,6 +306,7 @@ FT_UShort font_count = 0; FT_ULong font_offset = 0; + FT_TRACE2(( "NE signature found\n" )); if ( FT_STREAM_SEEK( res_offset ) || FT_FRAME_ENTER( ne_header.rname_tab_offset - @@ -293,13 +372,179 @@ face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift; face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift; - face->font->size_shift = size_shift; stream->cursor += 8; FT_FRAME_EXIT(); error = fnt_font_load( face->font, stream ); + } + else if ( ne_header.magic == WINFNT_PE_MAGIC ) + { + WinPE32_HeaderRec pe32_header; + WinPE32_SectionRec pe32_section; + WinPE_RsrcDirRec root_dir, name_dir, lang_dir; + WinPE_RsrcDirEntryRec dir_entry1, dir_entry2, dir_entry3; + WinPE_RsrcDataEntryRec data_entry; + FT_Long root_dir_offset, name_dir_offset, lang_dir_offset; + FT_UShort i, j, k; + + FT_TRACE2(( "PE signature found\n" )); + + if ( FT_STREAM_SEEK( mz_header.lfanew ) || + FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) ) + goto Exit; + + FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, " + "size_of_optional_header %02x\n" + "magic32 %02x, rsrc_virtual_address %04lx, " + "rsrc_size %04lx\n", + pe32_header.magic, pe32_header.machine, + pe32_header.number_of_sections, + pe32_header.size_of_optional_header, + pe32_header.magic32, pe32_header.rsrc_virtual_address, + pe32_header.rsrc_size )); + + if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ || + pe32_header.machine != 0x014c /* i386 */ || + pe32_header.size_of_optional_header != 0xe0 /* FIXME */ || + pe32_header.magic32 != 0x10b ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + face->root.num_faces = 0; + + for ( i = 0; i < pe32_header.number_of_sections; i++ ) + { + if ( FT_STREAM_READ_FIELDS( winpe32_section_fields, &pe32_section ) ) + goto Exit; + + FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n", + pe32_section.name, pe32_section.virtual_address, + pe32_section.size_of_raw_data, + pe32_section.pointer_to_raw_data )); + + if ( pe32_header.rsrc_virtual_address == pe32_section.virtual_address ) + goto Found_rsrc_section; + } + + error = FNT_Err_Invalid_File_Format; + goto Exit; + +Found_rsrc_section: + FT_TRACE2(( "found resources section %.8s\n", pe32_section.name )); + + if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) ) + goto Exit; + + root_dir_offset = pe32_section.pointer_to_raw_data; + + for ( i = 0; i < root_dir.number_of_named_entries + + root_dir.number_of_id_entries; i++ ) + { + if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields, &dir_entry1 ) ) + goto Exit; + + if ( !(dir_entry1.offset & 0x80000000 ) /* DataIsDirectory */ ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + dir_entry1.offset &= ~0x80000000; + + name_dir_offset = pe32_section.pointer_to_raw_data + + dir_entry1.offset; + + if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data + + dir_entry1.offset ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) ) + goto Exit; + + for ( j = 0; j < name_dir.number_of_named_entries + + name_dir.number_of_id_entries; j++ ) + { + if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields, + &dir_entry2 ) ) + goto Exit; + + if ( !(dir_entry2.offset & 0x80000000 ) /* DataIsDirectory */ ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + dir_entry2.offset &= ~0x80000000; + + lang_dir_offset = pe32_section.pointer_to_raw_data + + dir_entry2.offset; + + if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data + + dir_entry2.offset ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) ) + goto Exit; + + for ( k = 0; k < lang_dir.number_of_named_entries + + lang_dir.number_of_id_entries; k++ ) + { + if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields, + &dir_entry3 ) ) + goto Exit; + + if ( dir_entry2.offset & 0x80000000 /* DataIsDirectory */ ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + if ( dir_entry1.name == 8 /* RT_FONT */ ) + { + if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields, + &data_entry ) ) + goto Exit; + + FT_TRACE2(( "found font #%lu, offset %04lx, size %04lx, cp %lu\n", + dir_entry2.name, + pe32_section.pointer_to_raw_data + + data_entry.offset_to_data - + pe32_section.virtual_address, + data_entry.size, data_entry.code_page )); + + if ( face_index == face->root.num_faces ) + { + if ( FT_NEW( face->font ) ) + goto Exit; + + face->font->offset = pe32_section.pointer_to_raw_data + data_entry.offset_to_data - pe32_section.virtual_address; + face->font->fnt_size = data_entry.size; + + error = fnt_font_load( face->font, stream ); + if (error) + FT_TRACE2(( "font #%lu load error %d\n", + dir_entry2.name, error )); + else + FT_TRACE2(( "font #%lu successfully loaded\n", + dir_entry2.name )); + } + + face->root.num_faces++; + } + } + } + } + } + + if ( face_index >= face->root.num_faces ) + { + error = FNT_Err_Bad_Argument; + goto Exit; } } diff -up freetype2/src/winfonts/winfnt.h freetype2/src/winfonts/winfnt.h --- freetype2/src/winfonts/winfnt.h Thu Apr 01 20:35:58 2004 +++ freetype2/src/winfonts/winfnt.h Thu Jun 14 11:01:44 2007 @@ -46,6 +46,65 @@ FT_BEGIN_HEADER } WinNE_HeaderRec; + typedef struct WinPE32_HeaderRec_ + { + FT_ULong magic; + FT_UShort machine; + FT_UShort number_of_sections; + /* skipped content */ + FT_UShort size_of_optional_header; + /* skipped content */ + FT_UShort magic32; + /* skipped content */ + FT_ULong rsrc_virtual_address; + FT_ULong rsrc_size; + /* skipped content */ + + } WinPE32_HeaderRec; + + + typedef struct WinPE32_SectionRec_ + { + FT_Byte name[8]; + /* skipped content */ + FT_ULong virtual_address; + FT_ULong size_of_raw_data; + FT_ULong pointer_to_raw_data; + /* skipped content */ + + } WinPE32_SectionRec; + + + typedef struct WinPE_RsrcDirRec_ + { + FT_ULong characteristics; + FT_ULong time_date_stamp; + FT_UShort major_version; + FT_UShort minor_version; + FT_UShort number_of_named_entries; + FT_UShort number_of_id_entries; + + } WinPE_RsrcDirRec; + + + typedef struct WinPE_RsrcDirEntryRec_ + { + FT_ULong name; + FT_ULong offset; + + } WinPE_RsrcDirEntryRec; + + + typedef struct WinPE_RsrcDataEntryRec_ + { + FT_ULong offset_to_data; + FT_ULong size; + FT_ULong code_page; + FT_ULong reserved; + + } WinPE_RsrcDataEntryRec; + + typedef struct WinNameInfoRec_ { FT_UShort offset; @@ -68,12 +127,12 @@ FT_BEGIN_HEADER #define WINFNT_MZ_MAGIC 0x5A4D #define WINFNT_NE_MAGIC 0x454E +#define WINFNT_PE_MAGIC 0x4550 typedef struct FNT_FontRec_ { FT_ULong offset; - FT_Int size_shift; FT_WinFNT_HeaderRec header;