diff --git a/include/my_sys.h b/include/my_sys.h
index 8f0040055d615be29ba5618994065498bda4230a..4934df3c4e52223b0d6e39fdd4abd8f57dee0b5a 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -620,7 +620,7 @@ extern my_string my_path(my_string to,const char *progname,
 			 const char *own_pathname_part);
 extern my_string my_load_path(my_string to, const char *path,
 			      const char *own_path_prefix);
-extern int wild_compare(const char *str,const char *wildstr);
+extern int wild_compare(const char *str,const char *wildstr,pbool str_is_pattern);
 extern my_string my_strcasestr(const char *src,const char *suffix);
 extern int my_strcasecmp(const char *s,const char *t);
 extern int my_strsortcmp(const char *s,const char *t);
diff --git a/mysys/mf_wcomp.c b/mysys/mf_wcomp.c
index bdcfb0501d8dd9eb192a07d5bc2de4736009a6a2..1a01388a3dbfe2eb618eccd699103341041257cc 100644
--- a/mysys/mf_wcomp.c
+++ b/mysys/mf_wcomp.c
@@ -23,11 +23,12 @@
 
 char wild_many='*';
 char wild_one='?';
-char wild_prefix=0;
+char wild_prefix=0; /* QQ this can potentially cause a SIGSEGV */
 
-int wild_compare(register const char *str, register const char *wildstr)
+int wild_compare(register const char *str, register const char *wildstr,
+                 pbool str_is_pattern)
 {
-  reg3 int flag;
+  char cmp;
   DBUG_ENTER("wild_compare");
 
   while (*wildstr)
@@ -35,33 +36,55 @@ int wild_compare(register const char *str, register const char *wildstr)
     while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
     {
       if (*wildstr == wild_prefix && wildstr[1])
+      {
 	wildstr++;
-      if (*wildstr++ != *str++) DBUG_RETURN(1);
+        if (str_is_pattern && *str++ != wild_prefix)
+          DBUG_RETURN(1);
+      }
+      if (*wildstr++ != *str++)
+        DBUG_RETURN(1);
     }
-    if (! *wildstr ) DBUG_RETURN (*str != 0);
+    if (! *wildstr )
+      DBUG_RETURN(*str != 0);
     if (*wildstr++ == wild_one)
     {
-      if (! *str++) DBUG_RETURN (1);	/* One char; skipp */
+      if (! *str || (str_is_pattern && *str == wild_many))
+        DBUG_RETURN(1);                     /* One char; skip */
+      if (*str++ == wild_prefix && str_is_pattern && *str)
+        str++;
     }
     else
     {						/* Found '*' */
-      if (!*wildstr) DBUG_RETURN(0);		/* '*' as last char: OK */
-      flag=(*wildstr != wild_many && *wildstr != wild_one);
-      do
+      while (str_is_pattern && *str == wild_many)
+        str++;
+      for (; *wildstr ==  wild_many || *wildstr == wild_one; wildstr++)
+        if (*wildstr == wild_many)
+        {
+          while (str_is_pattern && *str == wild_many)
+            str++;
+        }
+        else
+        {
+          if (str_is_pattern && *str == wild_prefix && str[1])
+            str+=2;
+          else if (! *str++)
+            DBUG_RETURN (1);
+        }
+      if (!*wildstr)
+        DBUG_RETURN(0);		/* '*' as last char: OK */
+      if ((cmp= *wildstr) == wild_prefix && wildstr[1] && !str_is_pattern)
+        cmp=wildstr[1];
+      for (;;str++)
       {
-	if (flag)
-	{
-	  char cmp;
-	  if ((cmp= *wildstr) == wild_prefix && wildstr[1])
-	    cmp=wildstr[1];
-	  while (*str && *str != cmp)
-	    str++;
-	  if (!*str) DBUG_RETURN (1);
-	}
-	if (wild_compare(str,wildstr) == 0) DBUG_RETURN (0);
-      } while (*str++ && wildstr[0] != wild_many);
-      DBUG_RETURN(1);
+        while (*str && *str != cmp)
+          str++;
+        if (!*str)
+          DBUG_RETURN (1);
+	if (wild_compare(str,wildstr,str_is_pattern) == 0)
+          DBUG_RETURN (0);
+      }
+      /* We will never come here */
     }
   }
-  DBUG_RETURN (*str != '\0');
+  DBUG_RETURN (*str != 0);
 } /* wild_compare */
diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c
index e9e12c7275502b6643241ad97dcf278d1c2ae8df..067e4b7acc5fcd805658305ad8cc3a182b779cb3 100644
--- a/mysys/mf_wfile.c
+++ b/mysys/mf_wfile.c
@@ -106,7 +106,7 @@ int wf_test(register WF_PACK *wf_pack, register const char *name)
 
   not_pos=wf_pack->not_pos;
   for (i=0 ; i < not_pos; i++)
-    if (wild_compare(name,wf_pack->wild[i]) == 0)
+    if (wild_compare(name,wf_pack->wild[i],0) == 0)
       goto found;
   if (i)
     DBUG_RETURN(1);			/* No-match */
@@ -115,7 +115,7 @@ int wf_test(register WF_PACK *wf_pack, register const char *name)
 /* Test that it isn't in not-list */
 
   for (i=not_pos ; i < wf_pack->wilds; i++)
-    if (wild_compare(name,wf_pack->wild[i]) == 0)
+    if (wild_compare(name,wf_pack->wild[i],0) == 0)
       DBUG_RETURN(1);
   DBUG_RETURN(0);
 } /* wf_test */
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 6d2f662b7dfbaaf9d91b7f9cdd27fe619e06ee0f..9b676442995455ffbe634e1177f90a6affd1b1d0 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -834,7 +834,7 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
 */
 
 ulong acl_get(const char *host, const char *ip, const char *bin_ip,
-	     const char *user, const char *db)
+	     const char *user, const char *db, my_bool db_is_pattern)
 {
   ulong host_access,db_access;
   uint i,key_length;
@@ -868,7 +868,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip,
     {
       if (compare_hostname(&acl_db->host,host,ip))
       {
-	if (!acl_db->db || !wild_compare(db,acl_db->db))
+	if (!acl_db->db || !wild_compare(db,acl_db->db,db_is_pattern))
 	{
 	  db_access=acl_db->access;
 	  if (acl_db->host.hostname)
@@ -890,7 +890,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip,
     ACL_HOST *acl_host=dynamic_element(&acl_hosts,i,ACL_HOST*);
     if (compare_hostname(&acl_host->host,host,ip))
     {
-      if (!acl_host->db || !wild_compare(db,acl_host->db))
+      if (!acl_host->db || !wild_compare(db,acl_host->db,0))
       {
 	host_access=acl_host->access;		// Fully specified. Take it
 	break;
@@ -1222,7 +1222,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
   }
   return (!host->hostname ||
 	  (hostname && !wild_case_compare(hostname,host->hostname)) ||
-	  (ip && !wild_compare(ip,host->hostname)));
+	  (ip && !wild_compare(ip,host->hostname,0)));
 }
 
 
@@ -1300,7 +1300,7 @@ static bool test_if_create_new_users(THD *thd)
     tl.db=	   (char*) "mysql";
     tl.real_name=  (char*) "user";
     db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
-		      thd->priv_user, tl.db);
+		      thd->priv_user, tl.db, 0);
     if (!(db_access & INSERT_ACL))
     {
       if (check_grant(thd,INSERT_ACL,&tl,0,1))
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index bf269e5a7e3060e9bbfaf03f2ebcb5e9a181996d..7d8dcfd2079048cd22ee5622328f3f915e082366 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -85,7 +85,7 @@ my_bool  acl_init(THD *thd, bool dont_read_acl_tables);
 void acl_reload(THD *thd);
 void acl_free(bool end=0);
 ulong acl_get(const char *host, const char *ip, const char *bin_ip,
-	      const char *user, const char *db);
+	      const char *user, const char *db, my_bool db_is_pattern);
 ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
 		  const char *password,const char *scramble,
                   char **priv_user, char *priv_host,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6bf0b0bd2ba0c50dfb8d05011a250c1b88e75b92..c4cad8a8786de420837e3bd4d904324c7c39e875 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -149,7 +149,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
     if (wild)
     {
       strxmov(name,entry->table_cache_key,".",entry->real_name,NullS);
-      if (wild_compare(name,wild))
+      if (wild_compare(name,wild,0))
 	continue;
     }
 
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 865b2e1328f60f2ab663b47fbbd4cd67146887e3..2ee725e74326cc374f9575831b506afb74524fed 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -410,7 +410,7 @@ bool mysql_change_db(THD *thd,const char *name)
     db_access=DB_ACLS;
   else
     db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
-			thd->priv_user,dbname) |
+			thd->priv_user,dbname,0) |
 		thd->master_access);
   if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
   {
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 7e68db0dcd247cebc9f521316c0cc27c0f10bded..7ddbf79c6fe7dc90280b39945c8a6fb86ed35e12 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2672,7 +2672,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
     if (!(thd->master_access & SELECT_ACL) &&
 	(db && (!thd->db || strcmp(db,thd->db))))
       db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
-			thd->priv_user, db); /* purecov: inspected */
+			thd->priv_user, db, 0); /* purecov: inspected */
     *save_priv=thd->master_access | db_access;
     DBUG_RETURN(FALSE);
   }
@@ -2692,7 +2692,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
 
   if (db && (!thd->db || strcmp(db,thd->db)))
     db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
-		      thd->priv_user, db); /* purecov: inspected */
+		      thd->priv_user, db, 0); /* purecov: inspected */
   else
     db_access=thd->db_access;
   // Remove SHOW attribute and access rights we already have
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index a4ef735c7154fb3b651188e5717c4774c00f73de..26163ed9bef205fb37769585232225ef2a76c88b 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -78,7 +78,7 @@ mysqld_show_dbs(THD *thd,const char *wild)
   {
     if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
 	acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
-		thd->priv_user, file_name) ||
+		thd->priv_user, file_name, 0) ||
 	(grant_option && !check_grant_db(thd, file_name)))
     {
       thd->packet.length(0);
@@ -214,7 +214,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
 #endif
       {
         if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
-            (wild && wild_compare(file->name,wild)))
+            (wild && wild_compare(file->name,wild, 0)))
           continue;
       }
     }
@@ -232,7 +232,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
 	  if (wild_case_compare(file->name,wild))
 	    continue;
 	}
-	else if (wild_compare(file->name,wild))
+	else if (wild_compare(file->name,wild, 0))
 	  continue;
       }
     }