summaryrefslogtreecommitdiffstats
path: root/libmsi/string.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-11-29 14:17:39 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2012-12-06 20:30:30 +0100
commitc401fd3d4d2c9ac0ec6599315477eff9479b8474 (patch)
treeca52af56942ecb044a0d124afa713ae1269b1ca7 /libmsi/string.c
parentb4520f9ebf388a13d51461e20f3c60ac89ac277d (diff)
downloadmsitools-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.c42
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;
}