From: Eric Pouech eric.pouech@gmail.com
Introduce struct PDB_STRING_TABLE to describe string table's header.
This patch prevents core dumps with PDB:s where string offset are outside of string table.
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- include/wine/mscvpdb.h | 12 ++++++++++ tools/winedump/debug.c | 1 - tools/winedump/msc.c | 5 ++--- tools/winedump/pdb.c | 47 ++++++++++++++++++++++----------------- tools/winedump/winedump.h | 4 +++- 5 files changed, 44 insertions(+), 25 deletions(-)
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index 69dd42f0c09..5e30a6c2beb 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -2610,6 +2610,18 @@ typedef struct _PDB_FPO_DATA unsigned int flags; } PDB_FPO_DATA;
+typedef struct _PDB_STRING_TABLE +{ + unsigned int magic; + unsigned int hash_version; + unsigned int length; +} +PDB_STRING_TABLE; +/* This header is followed by: + * - a series (of bytes hdr.length) of 0-terminated strings + * - a serialized hash table + */ + #include "poppack.h"
/* =================================================== diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c index 9cc17f62e2b..e62e4436e4d 100644 --- a/tools/winedump/debug.c +++ b/tools/winedump/debug.c @@ -31,7 +31,6 @@ #include "windef.h" #include "winbase.h" #include "winedump.h" -#include "wine/mscvpdb.h"
/* * .DBG File Layout: diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 85bbdfc3487..b5708017651 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -30,7 +30,6 @@ #include "winbase.h" #include "winedump.h" #include "cvconst.h" -#include "wine/mscvpdb.h"
#define PSTRING(adr, ofs) \ ((const struct p_string*)((const char*)(adr) + (ofs))) @@ -2017,7 +2016,7 @@ void codeview_dump_linetab(const char* linetab, BOOL pascal_str, const char* pfx } }
-void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimage, DWORD strsize, const char* pfx) +void codeview_dump_linetab2(const char* linetab, DWORD size, const PDB_STRING_TABLE* strimage, const char* pfx) { unsigned i; const struct CV_DebugSSubsectionHeader_t* hdr; @@ -2094,7 +2093,7 @@ void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimag const char* meth[] = {"None", "MD5", "SHA1", "SHA256"}; printf("%s %d] name=%s size=%u method=%s checksum=[", pfx, (unsigned)((const char*)chksms - (const char*)(hdr + 1)), - strimage ? strimage + chksms->strOffset : "--none--", + pdb_get_string_table_entry(strimage, chksms->strOffset), chksms->size, chksms->method < ARRAY_SIZE(meth) ? meth[chksms->method] : "<<unknown>>"); for (i = 0; i < chksms->size; ++i) printf("%02x", chksms->checksum[i]); printf("]\n"); diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index 6774cd11876..9fe358aa86a 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -29,7 +29,6 @@ #include "windef.h" #include "winbase.h" #include "winedump.h" -#include "wine/mscvpdb.h"
struct pdb_reader { @@ -206,21 +205,32 @@ static unsigned get_stream_by_name(struct pdb_reader* reader, const char* name) return -1; }
-static void *read_string_table(struct pdb_reader* reader) +static PDB_STRING_TABLE* read_string_table(struct pdb_reader* reader) { - unsigned stream_idx; - void* ret; + unsigned stream_idx; + PDB_STRING_TABLE* ret; + unsigned stream_size;
stream_idx = get_stream_by_name(reader, "/names"); if (stream_idx == -1) return NULL; ret = reader->read_file(reader, stream_idx); if (!ret) return NULL; - if(*(const UINT *)ret == 0xeffeeffe) return ret; - printf("wrong header %x expecting 0xeffeeffe\n", *(const UINT *)ret); + stream_size = pdb_get_file_size(reader, stream_idx); + if (ret->magic == 0xeffeeffe && sizeof(*ret) + ret->length < stream_size) return ret; + printf("Improper string table header (magic=%x)\n", ret->magic); + dump_data((const unsigned char*)ret, stream_size, " "); free( ret ); return NULL; }
+const char* pdb_get_string_table_entry(const PDB_STRING_TABLE* table, unsigned ofs) +{ + if (!table) return "<<no string table>>"; + if (ofs >= table->length) return "<<invalid string table offset>>"; + /* strings start after header */ + return (char*)(table + 1) + ofs; +} + static void dump_global_symbol(struct pdb_reader* reader, unsigned file) { void* global = NULL; @@ -253,12 +263,11 @@ static void dump_public_symbol(struct pdb_reader* reader, unsigned file)
static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx) { - PDB_SYMBOLS* symbols; - unsigned char* modimage; - const char* file; - char* filesimage; - DWORD filessize = 0; - char tcver[32]; + PDB_SYMBOLS* symbols; + unsigned char* modimage; + const char* file; + PDB_STRING_TABLE* filesimage; + char tcver[32];
sidx->FPO = sidx->unk0 = sidx->unk1 = sidx->unk2 = sidx->unk3 = sidx->segments = sidx->unk4 = sidx->unk5 = sidx->unk6 = sidx->FPO_EXT = sidx->unk7 = -1; @@ -332,7 +341,6 @@ static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx }
if (!(filesimage = read_string_table(reader))) printf("string table not found\n"); - else filessize = *(const DWORD*)(filesimage + 8);
if (symbols->srcmodule_size) { @@ -592,7 +600,7 @@ static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx codeview_dump_linetab((const char*)modimage + symbol_size, TRUE, " "); else if (lineno2_size) /* actually, only one of the 2 lineno should be present */ codeview_dump_linetab2((const char*)modimage + symbol_size, lineno2_size, - filesimage ? filesimage + 12 : NULL, filessize, " "); + filesimage, " "); /* what's that part ??? */ if (0) dump_data(modimage + symbol_size + lineno_size + lineno2_size, @@ -644,7 +652,7 @@ static void pdb_dump_types_hash(struct pdb_reader* reader, const PDB_TYPES* type void* hash = NULL; unsigned i, strmsize; const unsigned* table; - char* strbase; + PDB_STRING_TABLE* strbase; unsigned *collision; hash = reader->read_file(reader, types->hash_file); if (!hash) return; @@ -746,7 +754,7 @@ static void pdb_dump_types_hash(struct pdb_reader* reader, const PDB_TYPES* type is_bit_set(deleted_bitset, count_deleted, i) ? 'D' : '_'); if (is_bit_set(present_bitset, count_present, i)) { - printf(" %s => ", strbase + 12 + *table++); + printf(" %s => ", pdb_get_string_table_entry(strbase, *table++)); pdb_dump_hash_value((const BYTE*)table, types->hash_size); table = (const unsigned*)((const BYTE*)table + types->hash_size); } @@ -855,14 +863,13 @@ static void pdb_dump_fpo(struct pdb_reader* reader, unsigned stream_idx) static void pdb_dump_fpo_ext(struct pdb_reader* reader, unsigned stream_idx) { PDB_FPO_DATA* fpoext; - unsigned i, size, strsize; - char* strbase; + unsigned i, size; + PDB_STRING_TABLE* strbase;
if (stream_idx == (WORD)-1) return; strbase = read_string_table(reader); if (!strbase) return;
- strsize = *(const DWORD*)(strbase + 8); fpoext = reader->read_file(reader, stream_idx); size = pdb_get_file_size(reader, stream_idx); if (fpoext && (size % sizeof(*fpoext)) == 0) @@ -875,7 +882,7 @@ static void pdb_dump_fpo_ext(struct pdb_reader* reader, unsigned stream_idx) printf("\t%08x %08x %8x %8x %8x %6x %8x %08x %s\n", fpoext[i].start, fpoext[i].func_size, fpoext[i].locals_size, fpoext[i].params_size, fpoext[i].maxstack_size, fpoext[i].prolog_size, fpoext[i].savedregs_size, fpoext[i].flags, - fpoext[i].str_offset < strsize ? strbase + 12 + fpoext[i].str_offset : "<out of bounds>"); + pdb_get_string_table_entry(strbase, fpoext[i].str_offset)); } } free(fpoext); diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index c84a98946b3..361f44b62b0 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -45,6 +45,7 @@ #include "../tools.h" #include "windef.h" #include "winbase.h" +#include "wine/mscvpdb.h"
/* Argument type constants */ #define MAX_FUNCTION_ARGS 32 @@ -263,7 +264,8 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, uns BOOL codeview_dump_types_from_offsets(const void* table, const DWORD* offsets, unsigned num_types); BOOL codeview_dump_types_from_block(const void* table, unsigned long len); void codeview_dump_linetab(const char* linetab, BOOL pascal_str, const char* pfx); -void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimage, DWORD strsize, const char* pfx); +void codeview_dump_linetab2(const char* linetab, DWORD size, const PDB_STRING_TABLE*, const char* pfx); +const char* pdb_get_string_table_entry(const PDB_STRING_TABLE* table, unsigned ofs);
void dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr); void dump_codeview(unsigned long ptr, unsigned long len);