mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-04-05 20:31:00 +08:00
Fix buffer overruns and NULL pointer deferences
This commit is contained in:
parent
64dd48a752
commit
1d289a65b3
@ -111,20 +111,21 @@ mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int
|
||||
* @off: Pointer for returning an offset to the row
|
||||
* @len: Pointer for returning the length of the row
|
||||
*
|
||||
* Returns: 0 on success. 1 on failure.
|
||||
* Returns: 0 on success. -1 on failure.
|
||||
*/
|
||||
int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len)
|
||||
{
|
||||
unsigned int pg = pg_row >> 8;
|
||||
unsigned int row = pg_row & 0xff;
|
||||
int result = 0;
|
||||
|
||||
if (mdb_read_alt_pg(mdb, pg) != mdb->fmt->pg_size)
|
||||
return 1;
|
||||
return -1;
|
||||
mdb_swap_pgbuf(mdb);
|
||||
mdb_find_row(mdb, row, off, len);
|
||||
result = mdb_find_row(mdb, row, off, len);
|
||||
mdb_swap_pgbuf(mdb);
|
||||
*buf = mdb->alt_pg_buf;
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len)
|
||||
@ -138,6 +139,11 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len)
|
||||
next_start = (row == 0) ? mdb->fmt->pg_size :
|
||||
mdb_get_int16(mdb->pg_buf, rco + row*2) & OFFSET_MASK;
|
||||
*len = next_start - (*start & OFFSET_MASK);
|
||||
|
||||
if ((*start & OFFSET_MASK) >= mdb->fmt->pg_size ||
|
||||
next_start > mdb->fmt->pg_size)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -277,7 +283,7 @@ int mdb_read_row(MdbTableDef *table, unsigned int row)
|
||||
return 0;
|
||||
|
||||
if (mdb_find_row(mdb, row, &row_start, &row_size)) {
|
||||
fprintf(stderr, "warning: mdb_find_row failed.");
|
||||
fprintf(stderr, "warning: mdb_find_row failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -298,6 +304,8 @@ int mdb_read_row(MdbTableDef *table, unsigned int row)
|
||||
|
||||
num_fields = mdb_crack_row(table, row_start, row_start + row_size - 1,
|
||||
fields);
|
||||
if (num_fields < 0)
|
||||
return 0;
|
||||
if (!mdb_test_sargs(table, fields, num_fields)) return 0;
|
||||
|
||||
#if MDB_DEBUG
|
||||
|
@ -99,6 +99,11 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
|
||||
mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n",
|
||||
pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz);
|
||||
|
||||
if (!table->usage_map || !table->free_usage_map) {
|
||||
mdb_free_tabledef(table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table->first_data_pg = mdb_get_int16(pg_buf, fmt->tab_first_dpg_offset);
|
||||
|
||||
if (entry->props)
|
||||
|
@ -112,17 +112,22 @@ mdb_is_col_indexed(MdbTableDef *table, int colnum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
mdb_crack_row4(MdbHandle *mdb, int row_start, int row_end, unsigned int bitmask_sz, unsigned int row_var_cols, unsigned int *var_col_offsets)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (bitmask_sz + 3 + row_var_cols*2 + 2 > row_end)
|
||||
return 0;
|
||||
|
||||
for (i=0; i<row_var_cols+1; i++) {
|
||||
var_col_offsets[i] = mdb_get_int16(mdb->pg_buf,
|
||||
row_end - bitmask_sz - 3 - (i*2));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static void
|
||||
static int
|
||||
mdb_crack_row3(MdbHandle *mdb, int row_start, int row_end, unsigned int bitmask_sz, unsigned int row_var_cols, unsigned int *var_col_offsets)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -136,6 +141,9 @@ mdb_crack_row3(MdbHandle *mdb, int row_start, int row_end, unsigned int bitmask_
|
||||
if ((col_ptr-row_start-row_var_cols)/256 < num_jumps)
|
||||
num_jumps--;
|
||||
|
||||
if (bitmask_sz + num_jumps + 1 > row_end)
|
||||
return 0;
|
||||
|
||||
jumps_used = 0;
|
||||
for (i=0; i<row_var_cols+1; i++) {
|
||||
while ((jumps_used < num_jumps)
|
||||
@ -144,6 +152,8 @@ mdb_crack_row3(MdbHandle *mdb, int row_start, int row_end, unsigned int bitmask_
|
||||
}
|
||||
var_col_offsets[i] = mdb->pg_buf[col_ptr-i]+(jumps_used*256);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* mdb_crack_row:
|
||||
@ -164,7 +174,7 @@ mdb_crack_row3(MdbHandle *mdb, int row_start, int row_end, unsigned int bitmask_
|
||||
* This routine is mostly used internally by mdb_fetch_row() but may have some
|
||||
* applicability for advanced application programs.
|
||||
*
|
||||
* Return value: number of fields present.
|
||||
* Return value: number of fields present, or -1 if the buffer is invalid.
|
||||
*/
|
||||
int
|
||||
mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields)
|
||||
@ -194,6 +204,11 @@ mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields)
|
||||
}
|
||||
|
||||
bitmask_sz = (row_cols + 7) / 8;
|
||||
if (bitmask_sz >= row_end) {
|
||||
fprintf(stderr, "warning: Invalid page buffer detected in mdb_crack_row.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nullmask = (unsigned char*)pg_buf + row_end - bitmask_sz + 1;
|
||||
|
||||
/* read table of variable column locations */
|
||||
@ -202,13 +217,18 @@ mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields)
|
||||
mdb_get_byte(pg_buf, row_end - bitmask_sz) :
|
||||
mdb_get_int16(pg_buf, row_end - bitmask_sz - 1);
|
||||
var_col_offsets = (unsigned int *)g_malloc((row_var_cols+1)*sizeof(int));
|
||||
int success = 0;
|
||||
if (IS_JET3(mdb)) {
|
||||
mdb_crack_row3(mdb, row_start, row_end, bitmask_sz,
|
||||
row_var_cols, var_col_offsets);
|
||||
success = mdb_crack_row3(mdb, row_start, row_end, bitmask_sz,
|
||||
row_var_cols, var_col_offsets);
|
||||
} else {
|
||||
mdb_crack_row4(mdb, row_start, row_end, bitmask_sz,
|
||||
row_var_cols, var_col_offsets);
|
||||
success = mdb_crack_row4(mdb, row_start, row_end, bitmask_sz,
|
||||
row_var_cols, var_col_offsets);
|
||||
}
|
||||
if (!success) {
|
||||
fprintf(stderr, "warning: Invalid page buffer detected in mdb_crack_row.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fixed_cols_found = 0;
|
||||
@ -687,6 +707,10 @@ unsigned int num_fields;
|
||||
}
|
||||
}
|
||||
num_fields = mdb_crack_row(table, row_start, row_end, fields);
|
||||
if (num_fields == -1) {
|
||||
fprintf(stderr, "Invalid row buffer, update will not occur\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mdb_get_option(MDB_DEBUG_WRITE)) {
|
||||
for (i=0;i<num_fields;i++) {
|
||||
|
Loading…
Reference in New Issue
Block a user