diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-11-29 14:17:39 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-06 20:30:30 +0100 |
commit | c401fd3d4d2c9ac0ec6599315477eff9479b8474 (patch) | |
tree | ca52af56942ecb044a0d124afa713ae1269b1ca7 /libmsi/string.c | |
parent | b4520f9ebf388a13d51461e20f3c60ac89ac277d (diff) | |
download | msitools-c401fd3d4d2c9ac0ec6599315477eff9479b8474.tar.gz msitools-c401fd3d4d2c9ac0ec6599315477eff9479b8474.tar.xz msitools-c401fd3d4d2c9ac0ec6599315477eff9479b8474.zip |
reading the string pool should be endian-friendly
Diffstat (limited to 'libmsi/string.c')
-rw-r--r-- | libmsi/string.c | 42 |
1 files changed, 19 insertions, 23 deletions
diff --git a/libmsi/string.c b/libmsi/string.c index 6914eb2..fdbce59 100644 --- a/libmsi/string.c +++ b/libmsi/string.c @@ -479,7 +479,7 @@ string_table *msi_load_string_table( IStorage *stg, unsigned *bytes_per_strref ) { string_table *st = NULL; char *data = NULL; - uint16_t *pool = NULL; + uint8_t *pool = NULL; unsigned r, datasize = 0, poolsize = 0, codepage; unsigned i, count, offset, len, n, refs; @@ -490,50 +490,47 @@ string_table *msi_load_string_table( IStorage *stg, unsigned *bytes_per_strref ) if( r != ERROR_SUCCESS) goto end; - if ( (poolsize > 4) && (pool[1] & 0x8000) ) + if ( (poolsize > 4) && (pool[3] & 0x80) ) *bytes_per_strref = LONG_STR_BYTES; else *bytes_per_strref = sizeof(uint16_t); - count = poolsize/4; + /* All data is little-endian. */ if( poolsize > 4 ) - codepage = pool[0] | ( (pool[1] & ~0x8000) << 16 ); + codepage = pool[0] | (pool[1] << 8) | (pool[2] << 16) | ((pool[3] & ~0x80) << 24); else codepage = CP_ACP; + + count = poolsize/4; st = init_stringtable( count, codepage ); if (!st) goto end; offset = 0; - n = 1; i = 1; - while( i<count ) + for (n = 1; i<count ; n++) { /* the string reference count is always the second word */ - refs = pool[i*2+1]; + len = pool[i*4] | (pool[i*4+1] << 8); + refs = pool[i*4+2] | (pool[i*4+3] << 8); + i++; /* empty entries have two zeros, still have a string id */ - if (pool[i*2] == 0 && refs == 0) - { - i++; - n++; + if (len == 0 && refs == 0) continue; - } /* * If a string is over 64k, the previous string entry is made null - * and its the high word of the length is inserted in the null string's - * reference count field. + * and the high word of the length is inserted in the null string's + * reference count field (i.e. mixed endian). + * + * TODO: add testcase */ - if( pool[i*2] == 0) - { - len = (pool[i*2+3] << 16) + pool[i*2+2]; - i += 2; - } - else + if (len == 0) { - len = pool[i*2]; - i += 1; + len = (refs << 16) | pool[i*4] | (pool[i*4+1] << 8); + refs = pool[i*4+2] | (pool[i*4+3] << 8); + i++; } if ( (offset + len) > datasize ) @@ -545,7 +542,6 @@ string_table *msi_load_string_table( IStorage *stg, unsigned *bytes_per_strref ) r = msi_addstring( st, n, data+offset, len, refs, StringPersistent ); if( r != n ) ERR("Failed to add string %d\n", n ); - n++; offset += len; } |