From 8db072748fc9beb11fa34fe3efc3e31f17499409 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 9 Nov 2012 20:15:23 +0100 Subject: [PATCH 1/6] add a test case for MySQL Bug #13889741: HANDLE_FATAL_SIGNAL IN _DB_ENTER_ | HANDLE_FATAL_SIGNAL IN STRNLEN --- mysql-test/r/information_schema.result | 2 ++ mysql-test/t/information_schema.test | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 608ada570fb..2d26850808a 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1673,4 +1673,6 @@ SELECT length(CAST(b AS CHAR)) FROM ubig; length(CAST(b AS CHAR)) 20 DROP TABLE ubig; +select 1 from information_schema.tables where table_schema=repeat('a', 2000); +1 End of 5.1 tests. diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index e78b180caf7..a6b07f379ec 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1438,6 +1438,10 @@ SELECT length(CAST(b AS CHAR)) FROM ubig; DROP TABLE ubig; +# +# Bug #13889741: HANDLE_FATAL_SIGNAL IN _DB_ENTER_ | HANDLE_FATAL_SIGNAL IN STRNLEN +# +select 1 from information_schema.tables where table_schema=repeat('a', 2000); --echo End of 5.1 tests. From 353130204dead31c311cfc2877278640df84a5ee Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 10 Nov 2012 20:36:18 +0100 Subject: [PATCH 2/6] MDEV-3849 - 1 bytes stack overwrite in normalize_dirname(). Take into account that length of strings passed down to this function can be up to FN_REFLEN+1 bytes. including terminating zero. The overwrite was caused by incomplete fix to MySQL Bug # 44834 --- mysys/mf_pack.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 86fd61537e7..e6b576b6d96 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -35,7 +35,7 @@ void pack_dirname(char * to, const char *from) int cwd_err; size_t d_length,length,UNINIT_VAR(buff_length); char * start; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("pack_dirname"); (void) intern_filename(to,from); /* Change to intern name */ @@ -132,7 +132,7 @@ size_t cleanup_dirname(register char *to, const char *from) reg3 char * from_ptr; reg4 char * start; char parent[5], /* for "FN_PARENTDIR" */ - buff[FN_REFLEN+1],*end_parentdir; + buff[FN_REFLEN + 1],*end_parentdir; #ifdef BACKSLASH_MBTAIL CHARSET_INFO *fs= fs_character_set(); #endif @@ -245,7 +245,7 @@ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ #ifdef USE_SYMDIR void symdirget(char *dir) { - char buff[FN_REFLEN+1]; + char buff[FN_REFLEN + 1]; char *pos=strend(dir); if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK)) { @@ -295,7 +295,7 @@ void symdirget(char *dir) size_t normalize_dirname(char *to, const char *from) { size_t length; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("normalize_dirname"); /* @@ -423,7 +423,7 @@ static char * NEAR_F expand_tilde(char * *path) size_t unpack_filename(char * to, const char *from) { size_t length, n_length, buff_length; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("unpack_filename"); length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */ @@ -459,7 +459,7 @@ size_t system_filename(char * to, const char *from) int libchar_found; size_t length; char * to_pos,from_pos,pos; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("system_filename"); libchar_found=0; @@ -516,7 +516,7 @@ size_t system_filename(char * to, const char *from) char *intern_filename(char *to, const char *from) { size_t length, to_length; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; if (from == to) { /* Dirname may destroy from */ strmov(buff,from); From e679dfcafc630e2dbe506d0001322055d7684e03 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 12 Nov 2012 19:56:51 +0100 Subject: [PATCH 3/6] followup fixes for MySQL Bug #13889741: HANDLE_FATAL_SIGNAL IN _DB_ENTER_ | HANDLE_FATAL_SIGNAL IN STRNLEN --- mysql-test/r/information_schema.result | 4 ++++ mysql-test/t/information_schema.test | 7 +++++++ sql/sql_acl.cc | 20 ++++++++++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 2d26850808a..cacb18ba728 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1675,4 +1675,8 @@ length(CAST(b AS CHAR)) DROP TABLE ubig; select 1 from information_schema.tables where table_schema=repeat('a', 2000); 1 +grant usage on *.* to mysqltest_1@localhost; +select 1 from information_schema.tables where table_schema=repeat('a', 2000); +1 +drop user mysqltest_1@localhost; End of 5.1 tests. diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index a6b07f379ec..ae733443479 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1442,6 +1442,13 @@ DROP TABLE ubig; # Bug #13889741: HANDLE_FATAL_SIGNAL IN _DB_ENTER_ | HANDLE_FATAL_SIGNAL IN STRNLEN # select 1 from information_schema.tables where table_schema=repeat('a', 2000); +grant usage on *.* to mysqltest_1@localhost; +connect (con1, localhost, mysqltest_1,,); +connection con1; +select 1 from information_schema.tables where table_schema=repeat('a', 2000); +connection default; +disconnect con1; +drop user mysqltest_1@localhost; --echo End of 5.1 tests. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 89b70032642..020aa042722 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1353,14 +1353,20 @@ ulong acl_get(const char *host, const char *ip, acl_entry *entry; DBUG_ENTER("acl_get"); - VOID(pthread_mutex_lock(&acl_cache->lock)); - end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db); + tmp_db= strmov(strmov(key, ip ? ip : "") + 1, user) + 1; + end= strnmov(tmp_db, db, key + sizeof(key) - tmp_db); + + if (end >= key + sizeof(key)) // db name was truncated + DBUG_RETURN(0); // no privileges for an invalid db name + if (lower_case_table_names) { my_casedn_str(files_charset_info, tmp_db); db=tmp_db; } key_length= (size_t) (end-key); + + VOID(pthread_mutex_lock(&acl_cache->lock)); if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search((uchar*) key, key_length))) { @@ -4331,11 +4337,17 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash) bool check_grant_db(THD *thd,const char *db) { Security_context *sctx= thd->security_ctx; - char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2]; + char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2], *end; uint len; bool error= TRUE; - len= (uint) (strmov(strmov(helping, sctx->priv_user) + 1, db) - helping) + 1; + end= strmov(helping, sctx->priv_user) + 1; + end= strnmov(end, db, helping + sizeof(helping) - end); + + if (end >= helping + sizeof(helping)) // db name was truncated + return 1; // no privileges for an invalid db name + + len= (uint) (end - helping) + 1; rw_rdlock(&LOCK_grant); From 632dc05ded27eeb0976e7a67310749ab4635614b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 17 Nov 2012 19:04:13 +0100 Subject: [PATCH 4/6] MDEV-3850 too early pthread_mutex_unlock in TC_LOG_MMAP::log_xid --- sql/log.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 4c21ac4c571..eb248c63b19 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5710,12 +5710,9 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) pthread_mutex_unlock(&LOCK_active); pthread_mutex_lock(&p->lock); p->waiters++; - for (;;) + while (p->state == DIRTY && syncing) { - int not_dirty = p->state != DIRTY; pthread_mutex_unlock(&p->lock); - if (not_dirty || !syncing) - break; pthread_cond_wait(&p->cond, &LOCK_sync); pthread_mutex_lock(&p->lock); } From 9e7d870b360b165ac7960814a2fa5bf6011eab1a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 19 Nov 2012 11:18:40 +0100 Subject: [PATCH 5/6] potential crash in the feedback plugin --- plugin/feedback/url_http.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc index 71b67a52807..b0028292707 100644 --- a/plugin/feedback/url_http.cc +++ b/plugin/feedback/url_http.cc @@ -258,18 +258,21 @@ int Url_http::send(const char* data, size_t data_length) Extract the first string between

...

tags and put it as a server reply into the error log. */ + len= 0; for (;;) { - size_t i= vio_read(vio, (uchar*)buf + len, sizeof(buf) - len - 1); + size_t i= sizeof(buf) - len - 1; + if (i) + i= vio_read(vio, (uchar*)buf + len, i); if ((int)i <= 0) break; len+= i; } - if (len && len < sizeof(buf)) + if (len) { char *from; - buf[len+1]= 0; // safety + buf[len]= 0; // safety if ((from= strstr(buf, "

"))) { From 47c5018f592b61b5e000842bdf5862ff458de488 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2012 13:28:53 +0100 Subject: [PATCH 6/6] MDEV-3861: assertions in TC_LOG_MMAP. Fix some problems in the TC_LOG_MMAP commit processing, which could lead to assertions in some cases. Problems are mostly reproducible in MariaDB 10.0 with asynchroneous commit checkpoints, but most of the problems were present in earlier versions also. --- sql/log.cc | 19 ++++++++++--------- sql/log.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index eb248c63b19..e44f8ff3067 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5550,8 +5550,9 @@ int TC_LOG_MMAP::open(const char *opt_name) syncing= 0; active=pages; + DBUG_ASSERT(npages >= 2); pool=pages+1; - pool_last=pages+npages-1; + pool_last_ptr= &((pages+npages-1)->next); return 0; @@ -5582,8 +5583,8 @@ void TC_LOG_MMAP::get_active_from_pool() do { best_p= p= &pool; - if ((*p)->waiters == 0) // can the first page be used ? - break; // yes - take it. + if ((*p)->waiters == 0 && (*p)->free > 0) // can the first page be used ? + break; // yes - take it. best_free=0; // no - trying second strategy for (p=&(*p)->next; *p; p=&(*p)->next) @@ -5600,10 +5601,10 @@ void TC_LOG_MMAP::get_active_from_pool() safe_mutex_assert_owner(&LOCK_active); active=*best_p; - if ((*best_p)->next) // unlink the page from the pool - *best_p=(*best_p)->next; - else - pool_last=*best_p; + /* Unlink the page from the pool. */ + if (!(*best_p)->next) + pool_last_ptr= best_p; + *best_p=(*best_p)->next; pthread_mutex_unlock(&LOCK_pool); pthread_mutex_lock(&active->lock); @@ -5764,8 +5765,8 @@ int TC_LOG_MMAP::sync() /* page is synced. let's move it to the pool */ pthread_mutex_lock(&LOCK_pool); - pool_last->next=syncing; - pool_last=syncing; + (*pool_last_ptr)=syncing; + pool_last_ptr=&(syncing->next); syncing->next=0; syncing->state= err ? ERROR : POOL; pthread_cond_signal(&COND_pool); // in case somebody's waiting diff --git a/sql/log.h b/sql/log.h index f42ef514307..9fb233fed86 100644 --- a/sql/log.h +++ b/sql/log.h @@ -81,7 +81,7 @@ class TC_LOG_MMAP: public TC_LOG my_off_t file_length; uint npages, inited; uchar *data; - struct st_page *pages, *syncing, *active, *pool, *pool_last; + struct st_page *pages, *syncing, *active, *pool, **pool_last_ptr; /* note that, e.g. LOCK_active is only used to protect 'active' pointer, to protect the content of the active page