diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index afdec0f4d06b0dadb34f7734f98925b1770d576c..42fa18b17b248236ca4cccfdec3e986ecc8ae8b3 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -95,3 +95,14 @@ Note	1003	select password(_latin1'idkfa ') AS `password('idkfa ')`,old_password(
 select encrypt('1234','_.');
 encrypt('1234','_.')
 #
+#
+# Bug #44767: invalid memory reads in password() and old_password() 
+#             functions
+#
+CREATE TABLE t1(c1 MEDIUMBLOB);
+INSERT INTO t1 VALUES (REPEAT('a', 1024));
+SELECT OLD_PASSWORD(c1), PASSWORD(c1) FROM t1;
+OLD_PASSWORD(c1)	PASSWORD(c1)
+77023ffe214c04ff	*82E58A2C08AAFE72C8EB523069CD8ADB33F78F58
+DROP TABLE t1;
+End of 5.0 tests
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index cc3cdb9564d2cb51b10c6b7bbce9e14e9d6d1e67..6dedeaa0fefee8d8b9dae39ba57d5219eda68538 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -56,3 +56,15 @@ explain extended select password('idkfa '), old_password('idkfa');
 select encrypt('1234','_.');
 
 # End of 4.1 tests
+
+--echo #
+--echo # Bug #44767: invalid memory reads in password() and old_password() 
+--echo #             functions
+--echo #
+
+CREATE TABLE t1(c1 MEDIUMBLOB);
+INSERT INTO t1 VALUES (REPEAT('a', 1024));
+SELECT OLD_PASSWORD(c1), PASSWORD(c1) FROM t1;
+DROP TABLE t1;
+
+--echo End of 5.0 tests
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 4941f42773175f6211caa537cdd2bbf020c97006..e3fe67f4324f9886ff9f0600c0ae7e509e4689d2 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1554,16 +1554,17 @@ String *Item_func_password::val_str(String *str)
     return 0;
   if (res->length() == 0)
     return &my_empty_string;
-  make_scrambled_password(tmp_value, res->c_ptr());
+  my_make_scrambled_password(tmp_value, res->ptr(), res->length());
   str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, res->charset());
   return str;
 }
 
-char *Item_func_password::alloc(THD *thd, const char *password)
+char *Item_func_password::alloc(THD *thd, const char *password,
+                                size_t pass_len)
 {
   char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
   if (buff)
-    make_scrambled_password(buff, password);
+    my_make_scrambled_password(buff, password, pass_len);
   return buff;
 }
 
@@ -1577,16 +1578,17 @@ String *Item_func_old_password::val_str(String *str)
     return 0;
   if (res->length() == 0)
     return &my_empty_string;
-  make_scrambled_password_323(tmp_value, res->c_ptr());
+  my_make_scrambled_password_323(tmp_value, res->ptr(), res->length());
   str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, res->charset());
   return str;
 }
 
-char *Item_func_old_password::alloc(THD *thd, const char *password)
+char *Item_func_old_password::alloc(THD *thd, const char *password,
+                                    size_t pass_len)
 {
   char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
   if (buff)
-    make_scrambled_password_323(buff, password);
+    my_make_scrambled_password_323(buff, password, pass_len);
   return buff;
 }
 
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 1c5346ab0743d3983acd67d30b2d14673ac674db..f2cb4d2d32ad0d6e0caf0acd292204137c0399ba 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -281,7 +281,7 @@ class Item_func_password :public Item_str_func
   String *val_str(String *str);
   void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; }
   const char *func_name() const { return "password"; }
-  static char *alloc(THD *thd, const char *password);
+  static char *alloc(THD *thd, const char *password, size_t pass_len);
 };
 
 
@@ -300,7 +300,7 @@ class Item_func_old_password :public Item_str_func
   String *val_str(String *str);
   void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } 
   const char *func_name() const { return "old_password"; }
-  static char *alloc(THD *thd, const char *password);
+  static char *alloc(THD *thd, const char *password, size_t pass_len);
 };
 
 
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 9768668f103f33f2751349e2c4ecd2f739223df0..55bcd30999d84fee54237e8c15f2d2107d25aff4 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1677,6 +1677,12 @@ extern void turn_parser_debug_on();
 SQL_CRYPT *get_crypt_for_frm(void);
 #endif
 
+/* password.c */
+extern "C" void my_make_scrambled_password_323(char *to, const char *password,
+                                               size_t pass_len);
+extern "C" void my_make_scrambled_password(char *to, const char *password,
+                                           size_t pass_len);
+
 #include "sql_view.h"
 
 /* Some inline functions for more speed */
diff --git a/sql/password.c b/sql/password.c
index 57ed3e6ab0f817bfb308028279000a352081a3f3..e12074549a4414c5dea9db8a17459028ab506f4b 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -137,19 +137,38 @@ void hash_password(ulong *result, const char *password, uint password_len)
     Create password to be stored in user database from raw string
     Used for pre-4.1 password handling
   SYNOPSIS
-    make_scrambled_password_323()
+    my_make_scrambled_password_323()
     to        OUT store scrambled password here
     password  IN  user-supplied password
+    pass_len  IN  length of password string
 */
 
-void make_scrambled_password_323(char *to, const char *password)
+void my_make_scrambled_password_323(char *to, const char *password,
+                                    size_t pass_len)
 {
   ulong hash_res[2];
-  hash_password(hash_res, password, (uint) strlen(password));
+  hash_password(hash_res, password, (uint) pass_len);
   sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
 }
 
 
+/*
+  Wrapper around my_make_scrambled_password_323() to maintain client lib ABI
+  compatibility.
+  In server code usage of my_make_scrambled_password_323() is preferred to
+  avoid strlen().
+  SYNOPSIS
+    make_scrambled_password_323()
+    to        OUT store scrambled password here
+    password  IN  NULL-terminated string with user-supplied password
+*/
+
+void make_scrambled_password_323(char *to, const char *password)
+{
+  my_make_scrambled_password_323(to, password, strlen(password));
+}
+
+
 /*
     Scramble string with password.
     Used in pre 4.1 authentication phase.
@@ -383,20 +402,21 @@ my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
     The result of this function is used as return value from PASSWORD() and
     is stored in the database.
   SYNOPSIS
-    make_scrambled_password()
+    my_make_scrambled_password()
     buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
-    password  IN  NULL-terminated password string
+    password  IN  password string
+    pass_len  IN  length of password string
 */
 
-void
-make_scrambled_password(char *to, const char *password)
+void my_make_scrambled_password(char *to, const char *password,
+                                size_t pass_len)
 {
   SHA1_CONTEXT sha1_context;
   uint8 hash_stage2[SHA1_HASH_SIZE];
 
   mysql_sha1_reset(&sha1_context);
   /* stage 1: hash password */
-  mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
+  mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) pass_len);
   mysql_sha1_result(&sha1_context, (uint8 *) to);
   /* stage 2: hash stage1 output */
   mysql_sha1_reset(&sha1_context);
@@ -409,6 +429,23 @@ make_scrambled_password(char *to, const char *password)
 }
   
 
+/*
+  Wrapper around my_make_scrambled_password() to maintain client lib ABI
+  compatibility.
+  In server code usage of my_make_scrambled_password() is preferred to
+  avoid strlen().
+  SYNOPSIS
+    make_scrambled_password()
+    buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
+    password  IN  NULL-terminated password string
+*/
+
+void make_scrambled_password(char *to, const char *password)
+{
+  my_make_scrambled_password(to, password, strlen(password));
+}
+
+
 /*
     Produce an obscure octet sequence from password and random
     string, recieved from the server. This sequence corresponds to the
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 61020a3eed05c9878b8f9a635d43a723af6182e8..b6a215a2306686723164cacd7ff2ea3d487cc479 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -10092,15 +10092,16 @@ text_or_password:
 	| PASSWORD '(' TEXT_STRING ')'
 	  {
 	    $$= $3.length ? YYTHD->variables.old_passwords ?
-	        Item_func_old_password::alloc(YYTHD, $3.str) :
-	        Item_func_password::alloc(YYTHD, $3.str) :
+	        Item_func_old_password::alloc(YYTHD, $3.str, $3.length) :
+	        Item_func_password::alloc(YYTHD, $3.str, $3.length) :
 	      $3.str;
             if ($$ == NULL)
               MYSQL_YYABORT;
 	  }
 	| OLD_PASSWORD '(' TEXT_STRING ')'
 	  {
-	    $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) :
+	    $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str, 
+							  $3.length) :
 	      $3.str;
             if ($$ == NULL)
               MYSQL_YYABORT;
@@ -10545,7 +10546,7 @@ grant_user:
                  (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
                if (buff == NULL)
                  MYSQL_YYABORT;
-               make_scrambled_password_323(buff, $4.str);
+               my_make_scrambled_password_323(buff, $4.str, $4.length);
                $1->password.str= buff;
                $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
              }
@@ -10555,7 +10556,7 @@ grant_user:
                  (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
                if (buff == NULL)
                  MYSQL_YYABORT;
-               make_scrambled_password(buff, $4.str);
+               my_make_scrambled_password(buff, $4.str, $4.length);
                $1->password.str= buff;
                $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
              }