From b57ef6d3cdbb9235cafb7f7081a592c2ceebd1bd Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 25 Mar 2010 15:49:01 +0400 Subject: BUG#51877 - HANDLER interface causes invalid memory read Invalid memory read if HANDLER ... READ NEXT is executed after failed (e.g. empty table) HANDLER ... READ FIRST. The problem was that we attempted to perform READ NEXT, whereas there is no pivot available from failed READ FIRST. With this fix READ NEXT after failed READ FIRST equals to READ FIRST. This bug affects MyISAM tables only. mysql-test/r/gis-rtree.result: Restore a test case for BUG51357. mysql-test/r/handler_myisam.result: A test case for BUG#51877. mysql-test/t/gis-rtree.test: Restore a test case for BUG51357. mysql-test/t/handler_myisam.test: A test case for BUG#51877. storage/myisam/mi_rnext.c: "search first" failed. This means we have no pivot for "search next", or in other words MI_INFO::lastkey is likely uninitialized. Normally SQL layer would never request "search next" if "search first" failed. But HANDLER may do anything. As mi_rnext() without preceeding mi_rkey()/mi_rfirst() equals to mi_rfirst(), we must restore original state as if failing mi_rfirst() was not called. --- storage/myisam/mi_rnext.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'storage/myisam/mi_rnext.c') diff --git a/storage/myisam/mi_rnext.c b/storage/myisam/mi_rnext.c index 7ce66d41e0f..b9bbda3cacb 100644 --- a/storage/myisam/mi_rnext.c +++ b/storage/myisam/mi_rnext.c @@ -28,6 +28,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) { int error,changed; uint flag; + uint update_mask= HA_STATE_NEXT_FOUND; DBUG_ENTER("mi_rnext"); if ((inx = _mi_check_index(info,inx)) < 0) @@ -55,6 +56,20 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) info->s->state.key_root[inx]); break; } + /* + "search first" failed. This means we have no pivot for + "search next", or in other words MI_INFO::lastkey is + likely uninitialized. + + Normally SQL layer would never request "search next" if + "search first" failed. But HANDLER may do anything. + + As mi_rnext() without preceeding mi_rkey()/mi_rfirst() + equals to mi_rfirst(), we must restore original state + as if failing mi_rfirst() was not called. + */ + if (error) + update_mask|= HA_STATE_PREV_FOUND; } else { @@ -100,7 +115,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) } /* Don't clear if database-changed */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - info->update|= HA_STATE_NEXT_FOUND; + info->update|= update_mask; if (error) { -- cgit v1.2.1