Fix some issues with mdb_memo_to_string

This commit is contained in:
whydoubt
2005-03-12 03:33:17 +00:00
parent 3153f5dd1e
commit 07c9d00283
4 changed files with 41 additions and 29 deletions

View File

@@ -1,3 +1,8 @@
Fri Mar 11 21:32:19 CST 2005 Jeff Smith <whydoubt@yahoo.com>
* HACKING:
* src/libmdb/data.c:
* src/libmdb/iconv.c: Fix some issues with mdb_memo_to_string
Sun Mar 6 22:09:09 CST 2005 Jeff Smith <whydoubt@yahoo.com> Sun Mar 6 22:09:09 CST 2005 Jeff Smith <whydoubt@yahoo.com>
* src/libmdb/table.c: Fix memory leak * src/libmdb/table.c: Fix memory leak
* include/mdbtools.h: * include/mdbtools.h:

10
HACKING
View File

@@ -199,16 +199,16 @@ Each memo column (or other long binary data) in a row
+------+---------+-------------+------------------------------------------+ +------+---------+-------------+------------------------------------------+
| data | length | name | description | | data | length | name | description |
+------+---------+-------------+------------------------------------------+ +------+---------+-------------+------------------------------------------+
| ???? | 2 bytes | memo_len | Total length of the memo | | ???? | 3 bytes | memo_len | Total length of the memo |
| ???? | 2 bytes | bitmask | See values | | ???? | 1 bytes | bitmask | See values |
| ???? | 4 bytes | lval_dp | Data pointer to LVAL page (if needed) | | ???? | 4 bytes | lval_dp | Data pointer to LVAL page (if needed) |
| 0x00 | 4 bytes | unknown | | | 0x00 | 4 bytes | unknown | |
+------+---------+-------------+------------------------------------------+ +------+---------+-------------+------------------------------------------+
Values for the bitmask: Values for the bitmask:
0x8000= the memo is in a string at the end of this header (memo_len bytes) 0x80 = the memo is in a string at the end of this header (memo_len bytes)
0x4000= the memo is in a unique LVAL page in a record type 1 0x40 = the memo is in a unique LVAL page in a record type 1
0x0000= the memo is in n LVAL pages in a record type 2 0x00 = the memo is in n LVAL pages in a record type 2
If the memo is in a LVAL page, we use row_id of lval_dp to find the row. If the memo is in a LVAL page, we use row_id of lval_dp to find the row.
offset_start of memo = (int16*) LVAL_page[offset_num_rows + (row_id * 2) + 2] offset_start of memo = (int16*) LVAL_page[offset_num_rows + (row_id * 2) + 2]

View File

@@ -605,8 +605,7 @@ int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
} }
static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size) static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
{ {
guint16 memo_len; guint32 memo_len;
guint16 memo_flags;
guint32 row_start, pg_row; guint32 row_start, pg_row;
guint32 len; guint32 len;
char *buf; char *buf;
@@ -618,21 +617,22 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
} }
#if MDB_DEBUG #if MDB_DEBUG
buffer_dump(mdb->pg_buf, start, start + MDB_MEMO_OVERHEAD); buffer_dump(mdb->pg_buf, start, start + MDB_MEMO_OVERHEAD - 1);
#endif #endif
/* The 16 bit integer at offset 0 is the length of the memo field. /* The 32 bit integer at offset 0 is the length of the memo field
* with some flags in the high bits.
* The 32 bit integer at offset 4 contains page and row information. * The 32 bit integer at offset 4 contains page and row information.
*/ */
memo_len = mdb_pg_get_int16(mdb, start); memo_len = mdb_pg_get_int32(mdb, start);
memo_flags = mdb_pg_get_int16(mdb, start+2);
if (memo_flags & 0x8000) { if (memo_len & 0x80000000) {
/* inline memo field */ /* inline memo field */
mdb_unicode2ascii(mdb, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], mdb_unicode2ascii(mdb, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
size - MDB_MEMO_OVERHEAD, text, MDB_BIND_SIZE); size - MDB_MEMO_OVERHEAD, text, MDB_BIND_SIZE);
return text; return text;
} else if (memo_flags & 0x4000) { } else if (memo_len & 0x40000000) {
/* single-page memo field */
pg_row = mdb_get_int32(mdb->pg_buf, start+4); pg_row = mdb_get_int32(mdb->pg_buf, start+4);
#if MDB_DEBUG #if MDB_DEBUG
printf("Reading LVAL page %06x\n", pg_row >> 8); printf("Reading LVAL page %06x\n", pg_row >> 8);
@@ -644,20 +644,24 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
#if MDB_DEBUG #if MDB_DEBUG
printf("row num %d start %d len %d\n", printf("row num %d start %d len %d\n",
pg_row & 0xff, row_start, len); pg_row & 0xff, row_start, len);
buffer_dump(mdb->pg_buf, row_start, row_start + len); buffer_dump(buf, row_start, row_start + len - 1);
#endif #endif
mdb_unicode2ascii(mdb, buf + row_start, len, text, MDB_BIND_SIZE); mdb_unicode2ascii(mdb, buf + row_start, len, text, MDB_BIND_SIZE);
return text; return text;
} else { /* if (memo_flags == 0x0000) { */ } else {
/* multi-page memo field */
int tmpoff = 0;
char *tmp; char *tmp;
memo_len &= 0x3fffffff;
tmp = (char *) g_malloc(memo_len);
pg_row = mdb_get_int32(mdb->pg_buf, start+4); pg_row = mdb_get_int32(mdb->pg_buf, start+4);
do {
#if MDB_DEBUG #if MDB_DEBUG
printf("Reading LVAL page %06x\n", pg_row >> 8); printf("Reading LVAL page %06x\n", pg_row >> 8);
#endif #endif
tmp = (char *) g_malloc(MDB_BIND_SIZE);
tmp[0] = '\0';
do {
if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) {
g_free(tmp);
strcpy(text, ""); strcpy(text, "");
return text; return text;
} }
@@ -665,14 +669,16 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
printf("row num %d start %d len %d\n", printf("row num %d start %d len %d\n",
pg_row & 0xff, row_start, len); pg_row & 0xff, row_start, len);
#endif #endif
strncat(tmp, buf + row_start + 4, if (tmpoff + len - 4 > memo_len) {
strlen(tmp) + len - 4 > MDB_BIND_SIZE ? break;
MDB_BIND_SIZE - strlen(tmp) : len - 4); }
memcpy(tmp + tmpoff, buf + row_start + 4, len - 4);
/* find next lval page */ tmpoff += len - 4;
pg_row = mdb_get_int32(mdb->pg_buf, row_start); } while (( pg_row = mdb_get_int32(buf, row_start) ));
} while ((pg_row >> 8)); if (tmpoff < memo_len) {
mdb_unicode2ascii(mdb, tmp, strlen(tmp), text, MDB_BIND_SIZE); fprintf(stderr, "Warning: incorrect memo length\n");
}
mdb_unicode2ascii(mdb, tmp, tmpoff, text, MDB_BIND_SIZE);
g_free(tmp); g_free(tmp);
return text; return text;
/* /*

View File

@@ -18,6 +18,7 @@
*/ */
#include "mdbtools.h" #include "mdbtools.h"
#include "errno.h"
#ifdef DMALLOC #ifdef DMALLOC
#include "dmalloc.h" #include "dmalloc.h"
@@ -69,7 +70,7 @@ mdb_unicode2ascii(MdbHandle *mdb, unsigned char *src, unsigned int slen, unsigne
//printf("1 len_in %d len_out %d\n",len_in, len_out); //printf("1 len_in %d len_out %d\n",len_in, len_out);
while (1) { while (1) {
iconv(mdb->iconv_in, &in_ptr, &len_in, &out_ptr, &len_out); iconv(mdb->iconv_in, &in_ptr, &len_in, &out_ptr, &len_out);
if (!len_in) break; if ((!len_in) || (errno == E2BIG)) break;
/* Don't bail if impossible conversion is encountered */ /* Don't bail if impossible conversion is encountered */
in_ptr += (IS_JET4(mdb)) ? 2 : 1; in_ptr += (IS_JET4(mdb)) ? 2 : 1;
len_in -= (IS_JET4(mdb)) ? 2 : 1; len_in -= (IS_JET4(mdb)) ? 2 : 1;