There is a case when db_read_bytes() returns early without initializing the data. Mark that case with the return value of -1 and let db_get_task_value() return -1 if the data has been uninitialized or the array index is out of bounds.
* ddb/db_access.c (db_get_task_value) (data_uninitialized): New variable. (db_get_task_value): Check if db_read_bytes() has initialized the data. (db_get_task_value): Check if array index is out of bounds. (db_get_task_value): Return -1 if data is uninitialized. * ddb/db_examine.c (db_read_bytes): New parameter. * i386/i386/db_interface.c (db_read_bytes): New parameter data_length. (db_read_bytes): Return int instead of void. (db_read_bytes): Check if read counter is less then data_length. * i386/i386/db_interface.h (db_read_bytes): Return int instead of void. (db_read_bytes): New parameter data_length. --- ddb/db_access.c | 31 +++++++++++++++++++------------ ddb/db_examine.c | 2 +- i386/i386/db_interface.c | 17 ++++++++++++----- i386/i386/db_interface.h | 3 ++- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/ddb/db_access.c b/ddb/db_access.c index 4df9831..6b410ad 100644 --- a/ddb/db_access.c +++ b/ddb/db_access.c @@ -69,26 +69,33 @@ db_get_task_value(addr, size, is_signed, task) task_t task; { char data[sizeof(db_expr_t)]; + boolean_t data_uninitialized = TRUE; db_expr_t value; int i; - db_read_bytes(addr, size, data, task); + if (db_read_bytes(addr, size, data, sizeof(db_expr_t), task) == 0) + data_uninitialized = FALSE; value = 0; + if (!data_uninitialized) { + if (size > sizeof(db_expr_t)) + return -1; #if BYTE_MSF - for (i = 0; i < size; i++) + for (i = 0; i < size; i++) #else /* BYTE_LSF */ - for (i = size - 1; i >= 0; i--) + for (i = size - 1; i >= 0; i--) #endif - { - value = (value << 8) + (data[i] & 0xFF); - } - - if (size <= sizeof(int)) { - if (is_signed && (value & db_extend[size]) != 0) - value |= db_extend[size]; - } - return (value); + { + value = (value << 8) + (data[i] & 0xFF); + } + + if (size <= sizeof(int)) { + if (is_signed && (value & db_extend[size]) != 0) + value |= db_extend[size]; + } + return (value); + } else + return -1; } void diff --git a/ddb/db_examine.c b/ddb/db_examine.c index a90ffa6..7820396 100644 --- a/ddb/db_examine.c +++ b/ddb/db_examine.c @@ -474,7 +474,7 @@ db_xcdump(addr, size, count, task) if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task)) bcount = next_page_addr - addr; } - db_read_bytes(addr, bcount, data, task); + db_read_bytes(addr, bcount, data, DB_XCDUMP_NC, task); for (i = 0; i < bcount && off != 0; i += size) { if (i % 4 == 0) db_printf(" "); diff --git a/i386/i386/db_interface.c b/i386/i386/db_interface.c index a8ac52a..9d94215 100644 --- a/i386/i386/db_interface.c +++ b/i386/i386/db_interface.c @@ -447,11 +447,12 @@ db_user_to_kernel_address( * Read bytes from kernel address space for debugger. */ -void +int db_read_bytes( vm_offset_t addr, int size, char *data, + int data_length, task_t task) { char *src; @@ -471,20 +472,26 @@ db_read_bytes( addr++; *data++ = *src++; } - return; + return 0; } + int i = 0; while (size > 0) { - if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0) - return; + if ((db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0) && i < data_length) + return -1; + else if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0) + return 0; src = (char *)kern_addr; n = intel_trunc_page(addr+INTEL_PGBYTES) - addr; if (n > size) n = size; size -= n; addr += n; - while (--n >= 0) + while (--n >= 0) { *data++ = *src++; + i++; + } } + return 0; } /* diff --git a/i386/i386/db_interface.h b/i386/i386/db_interface.h index e43771e..3eebe3f 100644 --- a/i386/i386/db_interface.h +++ b/i386/i386/db_interface.h @@ -32,10 +32,11 @@ extern boolean_t kdb_trap ( int code, struct i386_saved_state *regs); -extern void db_read_bytes ( +extern int db_read_bytes ( vm_offset_t addr, int size, char *data, + int data_length, task_t task); extern void db_write_bytes ( -- 1.8.1.4