List:Commits« Previous MessageNext Message »
From:kroki Date:July 2 2006 10:35am
Subject:bk commit into 5.0 tree (kroki:1.2168) BUG#20570
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of tomash. When tomash does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2168 06/07/02 14:35:45 kroki@stripped +7 -0
  Bug#20570: CURRENT_USER() in a VIEW with SQL SECURITY DEFINER returns
             invoker name
  
  The bug was fixed similar to how context switch is handled in
  Item_func_sp::execute_impl(): we store pointer to current
  Name_resolution_context in Item_func_current_user class, and use
  its Security_context in Item_func_current_user::fix_fields().

  sql/sql_yacc.yy
    1.470 06/07/02 14:35:39 kroki@stripped +5 -2
    Pass current Name_resolution_context to Item_func_current_user.

  sql/item_strfunc.h
    1.107 06/07/02 14:35:39 kroki@stripped +27 -8
    Move implementation of CURRENT_USER() out of Item_func_user to
    to new Item_func_current_user class.  For both classes calculate
    user name in fix_fields() method.
    For Item_func_current_user add context field to store
    Name_resolution_context in effect.

  sql/item_strfunc.cc
    1.267 06/07/02 14:35:39 kroki@stripped +37 -28
    Add implementations for Item_func_user::init(),
    Item_func_user::fix_fields() and
    Item_func_current_user::fix_fields() methods.  The latter uses
    Security_context from current Name_resolution_context, if one is
    defined.

  sql/item_create.h
    1.44 06/07/02 14:35:39 kroki@stripped +0 -1
    Remove prototype for create_func_current_user().

  sql/item_create.cc
    1.60 06/07/02 14:35:39 kroki@stripped +0 -6
    Remove create_func_current_user(), as it is not used for automatic
    function creation.

  mysql-test/t/view_grant.test
    1.14 06/07/02 14:35:38 kroki@stripped +62 -0
    Add test case for bug#20570.

  mysql-test/r/view_grant.result
    1.16 06/07/02 14:35:38 kroki@stripped +53 -0
    Add result for bug#20570.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	kroki
# Host:	moonlight.intranet
# Root:	/home/tomash/src/mysql_ab/mysql-5.0-bug20570

--- 1.59/sql/item_create.cc	2006-04-12 19:30:51 +04:00
+++ 1.60/sql/item_create.cc	2006-07-02 14:35:39 +04:00
@@ -296,12 +296,6 @@
   return new Item_func_pow(a,b);
 }
 
-Item *create_func_current_user()
-{
-  current_thd->lex->safe_to_cache_query= 0;
-  return new Item_func_user(TRUE);
-}
-
 Item *create_func_radians(Item *a)
 {
   return new Item_func_units((char*) "radians",a,M_PI/180,0.0);

--- 1.43/sql/item_create.h	2005-08-25 17:34:13 +04:00
+++ 1.44/sql/item_create.h	2006-07-02 14:35:39 +04:00
@@ -73,7 +73,6 @@
 Item *create_func_period_diff(Item* a, Item *b);
 Item *create_func_pi(void);
 Item *create_func_pow(Item* a, Item *b);
-Item *create_func_current_user(void);
 Item *create_func_radians(Item *a);
 Item *create_func_release_lock(Item* a);
 Item *create_func_repeat(Item* a, Item *b);

--- 1.266/sql/item_strfunc.cc	2006-05-12 11:15:11 +04:00
+++ 1.267/sql/item_strfunc.cc	2006-07-02 14:35:39 +04:00
@@ -1650,42 +1650,51 @@
   return str;
 }
 
-// TODO: make USER() replicate properly (currently it is replicated to "")
 
-String *Item_func_user::val_str(String *str)
+/*
+  TODO: make USER() replicate properly (currently it is replicated to "")
+*/
+bool Item_func_user::init(const char *user, const char *host)
 {
   DBUG_ASSERT(fixed == 1);
-  THD          *thd=current_thd;
-  CHARSET_INFO *cs= system_charset_info;
-  const char   *host, *user;
-  uint		res_length;
 
-  if (is_current)
-  {
-    user= thd->security_ctx->priv_user;
-    host= thd->security_ctx->priv_host;
-  }
-  else
+  // For system threads (e.g. replication SQL thread) user may be empty
+  if (user)
   {
-    user= thd->main_security_ctx.user;
-    host= thd->main_security_ctx.host_or_ip;
-  }
+    CHARSET_INFO *cs= str_value.charset();
+    uint res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
 
-  // For system threads (e.g. replication SQL thread) user may be empty
-  if (!user)
-    return &my_empty_string;
-  res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
+    if (str_value.alloc(res_length))
+    {
+      null_value=1;
+      return TRUE;
+    }
 
-  if (str->alloc(res_length))
-  {
-    null_value=1;
-    return 0;
+    res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length,
+                                  "%s@%s", user, host);
+    str_value.length(res_length);
+    str_value.mark_as_const();
   }
-  res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",
-			        user, host);
-  str->length(res_length);
-  str->set_charset(cs);
-  return str;
+  return FALSE;
+}
+
+
+bool Item_func_user::fix_fields(THD *thd, Item **ref)
+{
+  return (Item_func_sysconst::fix_fields(thd, ref) ||
+          init(thd->main_security_ctx.user,
+               thd->main_security_ctx.host_or_ip));
+}
+
+
+bool Item_func_current_user::fix_fields(THD *thd, Item **ref)
+{
+  if (Item_func_sysconst::fix_fields(thd, ref))
+    return TRUE;
+
+  Security_context *ctx= (context->security_ctx
+                          ? context->security_ctx : thd->security_ctx);
+  return init(ctx->priv_user, ctx->priv_host);
 }
 
 

--- 1.106/sql/item_strfunc.h	2006-05-18 21:33:57 +04:00
+++ 1.107/sql/item_strfunc.h	2006-07-02 14:35:39 +04:00
@@ -385,21 +385,40 @@
 
 class Item_func_user :public Item_func_sysconst
 {
-  bool is_current;
+protected:
+  bool init (const char *user, const char *host);
 
 public:
-  Item_func_user(bool is_current_arg)
-    :Item_func_sysconst(), is_current(is_current_arg) {}
-  String *val_str(String *);
+  Item_func_user()
+  {
+    str_value.set("", 0, system_charset_info);
+  }
+  String *val_str(String *)
+  {
+    DBUG_ASSERT(fixed == 1);
+    return (null_value ? 0 : &str_value);
+  }
+  bool fix_fields(THD *thd, Item **ref);
   void fix_length_and_dec()
   {
     max_length= ((USERNAME_LENGTH + HOSTNAME_LENGTH + 1) *
                  system_charset_info->mbmaxlen);
   }
-  const char *func_name() const
-    { return is_current ? "current_user" : "user"; }
-  const char *fully_qualified_func_name() const
-    { return is_current ? "current_user()" : "user()"; }
+  const char *func_name() const { return "user"; }
+  const char *fully_qualified_func_name() const { return "user()"; }
+};
+
+
+class Item_func_current_user :public Item_func_user
+{
+  Name_resolution_context *context;
+
+public:
+  Item_func_current_user(Name_resolution_context *context_arg)
+    : context(context_arg) {}
+  bool fix_fields(THD *thd, Item **ref);
+  const char *func_name() const { return "current_user"; }
+  const char *fully_qualified_func_name() const { return "current_user()"; }
 };
 
 

--- 1.469/sql/sql_yacc.yy	2006-05-15 00:51:02 +04:00
+++ 1.470/sql/sql_yacc.yy	2006-07-02 14:35:39 +04:00
@@ -4413,7 +4413,10 @@
 	    Lex->safe_to_cache_query=0;
 	  }
 	| CURRENT_USER optional_braces
-          { $$= create_func_current_user(); }
+          {
+            $$= new Item_func_current_user(Lex->current_context());
+            Lex->safe_to_cache_query= 0;
+          }
 	| DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
 	  { $$= new Item_date_add_interval($3,$5,$6,0); }
 	| DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
@@ -4764,7 +4767,7 @@
 	| UNIX_TIMESTAMP '(' expr ')'
 	  { $$= new Item_func_unix_timestamp($3); }
 	| USER '(' ')'
-	  { $$= new Item_func_user(FALSE); Lex->safe_to_cache_query=0; }
+	  { $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
 	| UTC_DATE_SYM optional_braces
 	  { $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;}
 	| UTC_TIME_SYM optional_braces

--- 1.15/mysql-test/r/view_grant.result	2006-05-26 12:57:52 +04:00
+++ 1.16/mysql-test/r/view_grant.result	2006-07-02 14:35:38 +04:00
@@ -618,3 +618,56 @@
 DROP VIEW v;
 DROP TABLE t1;
 USE test;
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+DROP VIEW IF EXISTS v3;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP PROCEDURE IF EXISTS p1;
+CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu;
+CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER
+RETURN CURRENT_USER();
+CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu;
+CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER
+SET cu= CURRENT_USER();
+CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER
+BEGIN
+DECLARE cu VARCHAR(77);
+CALL p1(cu);
+RETURN cu;
+END|
+CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu;
+CREATE USER mysqltest_u1@localhost;
+GRANT ALL ON test.* TO mysqltest_u1@localhost;
+
+The following tests should all return 1.
+
+SELECT CURRENT_USER() = 'mysqltest_u1@localhost';
+CURRENT_USER() = 'mysqltest_u1@localhost'
+1
+SELECT f1() = 'mysqltest_u1@localhost';
+f1() = 'mysqltest_u1@localhost'
+1
+CALL p1(@cu);
+SELECT @cu = 'mysqltest_u1@localhost';
+@cu = 'mysqltest_u1@localhost'
+1
+SELECT f2() = 'mysqltest_u1@localhost';
+f2() = 'mysqltest_u1@localhost'
+1
+SELECT cu = 'root@localhost' FROM v1;
+cu = 'root@localhost'
+1
+SELECT cu = 'root@localhost' FROM v2;
+cu = 'root@localhost'
+1
+SELECT cu = 'root@localhost' FROM v3;
+cu = 'root@localhost'
+1
+DROP VIEW v3;
+DROP FUNCTION f2;
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+DROP VIEW v2;
+DROP VIEW v1;
+DROP USER mysqltest_u1@localhost;

--- 1.13/mysql-test/t/view_grant.test	2006-05-26 12:57:52 +04:00
+++ 1.14/mysql-test/t/view_grant.test	2006-07-02 14:35:38 +04:00
@@ -807,3 +807,65 @@
 DROP VIEW v;
 DROP TABLE t1;
 USE test;
+
+
+#
+# BUG#20570: CURRENT_USER() in a VIEW with SQL SECURITY DEFINER
+# returns invoker name
+#
+--disable_warnings
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+DROP VIEW IF EXISTS v3;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu;
+
+CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER
+  RETURN CURRENT_USER();
+CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu;
+
+CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER
+  SET cu= CURRENT_USER();
+delimiter |;
+CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER
+BEGIN
+  DECLARE cu VARCHAR(77);
+  CALL p1(cu);
+  RETURN cu;
+END|
+delimiter ;|
+CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu;
+
+CREATE USER mysqltest_u1@localhost;
+GRANT ALL ON test.* TO mysqltest_u1@localhost;
+
+connect (conn1, localhost, mysqltest_u1,,);
+
+--echo
+--echo The following tests should all return 1.
+--echo
+SELECT CURRENT_USER() = 'mysqltest_u1@localhost';
+SELECT f1() = 'mysqltest_u1@localhost';
+CALL p1(@cu);
+SELECT @cu = 'mysqltest_u1@localhost';
+SELECT f2() = 'mysqltest_u1@localhost';
+SELECT cu = 'root@localhost' FROM v1;
+SELECT cu = 'root@localhost' FROM v2;
+SELECT cu = 'root@localhost' FROM v3;
+
+disconnect conn1;
+connection default;
+
+DROP VIEW v3;
+DROP FUNCTION f2;
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+DROP VIEW v2;
+DROP VIEW v1;
+DROP USER mysqltest_u1@localhost;
+
+# End of 5.0 tests.
Thread
bk commit into 5.0 tree (kroki:1.2168) BUG#20570kroki2 Jul