From: Dmitry Shulga Date: March 11 2011 9:10am Subject: bzr commit into mysql-5.5 branch (Dmitry.Shulga:3362) Bug#56976 List-Archive: http://lists.mysql.com/commits/132795 X-Bug: 56976 Message-Id: <201103110912.p2B39eip019574@rcsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============5995465070153345949==" --===============5995465070153345949== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/shulga/projects/mysql/mysql-5.5/ based on revid:marc.alff@stripped 3362 Dmitry Shulga 2011-03-11 [merge] Manual merge from mysql-5.1 for bug#56976. modified: mysql-test/r/variables.result mysql-test/t/variables.test sql/item.cc sql/mysqld.cc sql/mysqld.h sql/sql_prepare.cc sql/sys_vars.cc tests/mysql_client_test.c === modified file 'mysql-test/r/variables.result' --- a/mysql-test/r/variables.result 2011-02-10 07:34:22 +0000 +++ b/mysql-test/r/variables.result 2011-03-11 09:03:21 +0000 @@ -1540,6 +1540,9 @@ ERROR HY000: Cannot drop default keycach SET @@global.key_cache_block_size=0; Warnings: Warning 1292 Truncated incorrect key_cache_block_size value: '0' +select @@max_long_data_size; +@@max_long_data_size +1048576 SET @@global.max_binlog_cache_size=DEFAULT; SET @@global.max_join_size=DEFAULT; SET @@global.key_buffer_size=@kbs; === modified file 'mysql-test/t/variables.test' --- a/mysql-test/t/variables.test 2011-02-10 07:34:22 +0000 +++ b/mysql-test/t/variables.test 2011-03-11 09:03:21 +0000 @@ -1281,6 +1281,11 @@ SET @@global.max_join_size=0; SET @@global.key_buffer_size=0; SET @@global.key_cache_block_size=0; +# +# Bug#56976: added new start-up parameter +# +select @@max_long_data_size; + # cleanup SET @@global.max_binlog_cache_size=DEFAULT; SET @@global.max_join_size=DEFAULT; === modified file 'sql/item.cc' --- a/sql/item.cc 2011-03-04 15:43:28 +0000 +++ b/sql/item.cc 2011-03-11 09:03:21 +0000 @@ -2885,6 +2885,16 @@ bool Item_param::set_longdata(const char (here), and first have to concatenate all pieces together, write query to the binary log and only then perform conversion. */ + if (str_value.length() + length > max_long_data_size) + { + my_message(ER_UNKNOWN_ERROR, + "Parameter of prepared statement which is set through " + "mysql_send_long_data() is longer than " + "'max_long_data_size' bytes", + MYF(0)); + DBUG_RETURN(true); + } + if (str_value.append(str, length, &my_charset_bin)) DBUG_RETURN(TRUE); state= LONG_DATA_VALUE; === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2011-03-10 08:43:55 +0000 +++ b/sql/mysqld.cc 2011-03-11 09:03:21 +0000 @@ -324,6 +324,7 @@ static PSI_rwlock_key key_rwlock_openssl /* the default log output is log tables */ static bool lower_case_table_names_used= 0; +static bool max_long_data_size_used= false; static bool volatile select_thread_in_use, signal_thread_in_use; /* See Bug#56666 and Bug#56760 */; volatile bool ready_to_exit; @@ -478,6 +479,11 @@ ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; ulong max_connections, max_connect_errors; +/* + Maximum length of parameter value which can be set through + mysql_send_long_data() call. +*/ +ulong max_long_data_size; /** Limit of the total number of prepared statements in the server. Is necessary to protect the server against out-of-memory attacks. @@ -7155,6 +7161,11 @@ mysqld_get_one_option(int optid, if (argument == NULL) /* no argument */ log_error_file_ptr= const_cast(""); break; + case OPT_MAX_LONG_DATA_SIZE: + max_long_data_size= atol(argument); + max_long_data_size_used= true; + WARN_DEPRECATED(NULL, 5, 6, "--max_long_data_size", "'--max_allowed_packet'"); + break; } return 0; } @@ -7381,6 +7392,13 @@ static int get_options(int *argc_ptr, ch opt_readonly= read_only; + /* + If max_long_data_size is not specified explicitly use + value of max_allowed_packet. + */ + if (!max_long_data_size_used) + max_long_data_size= global_system_variables.max_allowed_packet; + return 0; } === modified file 'sql/mysqld.h' --- a/sql/mysqld.h 2011-03-10 08:43:55 +0000 +++ b/sql/mysqld.h 2011-03-11 09:03:21 +0000 @@ -126,6 +126,7 @@ extern char *default_storage_engine; extern bool opt_endinfo, using_udf_functions; extern my_bool locked_in_memory; extern bool opt_using_transactions; +extern ulong max_long_data_size; extern ulong current_pid; extern ulong expire_logs_days; extern my_bool relay_log_recovery; @@ -397,7 +398,8 @@ enum options_mysqld OPT_UPDATE_LOG, OPT_WANT_CORE, OPT_ENGINE_CONDITION_PUSHDOWN, - OPT_LOG_ERROR + OPT_LOG_ERROR, + OPT_MAX_LONG_DATA_SIZE }; === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2011-03-01 14:42:37 +0000 +++ b/sql/sql_prepare.cc 2011-03-11 09:03:21 +0000 @@ -2784,6 +2784,34 @@ void mysql_sql_stmt_close(THD *thd) } } + +class Set_longdata_error_handler : public Internal_error_handler +{ +public: + Set_longdata_error_handler(Prepared_statement *statement) + : stmt(statement) + { } + +public: + bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + MYSQL_ERROR::enum_warning_level level, + const char* msg, + MYSQL_ERROR ** cond_hdl) + { + stmt->state= Query_arena::ERROR; + stmt->last_errno= sql_errno; + strncpy(stmt->last_error, msg, MYSQL_ERRMSG_SIZE); + + return TRUE; + } + +private: + Prepared_statement *stmt; +}; + + /** Handle long data in pieces from client. @@ -2840,16 +2868,19 @@ void mysql_stmt_get_longdata(THD *thd, c param= stmt->param_array[param_number]; + Set_longdata_error_handler err_handler(stmt); + /* + Install handler that will catch any errors that can be generated + during execution of Item_param::set_longdata() and propagate + them to Statement::last_error. + */ + thd->push_internal_handler(&err_handler); #ifndef EMBEDDED_LIBRARY - if (param->set_longdata(packet, (ulong) (packet_end - packet))) + param->set_longdata(packet, (ulong) (packet_end - packet)); #else - if (param->set_longdata(thd->extra_data, thd->extra_length)) + param->set_longdata(thd->extra_data, thd->extra_length); #endif - { - stmt->state= Query_arena::ERROR; - stmt->last_errno= ER_OUTOFMEMORY; - sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); - } + thd->pop_internal_handler(); general_log_print(thd, thd->command, NullS); @@ -3389,6 +3420,13 @@ Prepared_statement::execute_loop(String bool error; int reprepare_attempt= 0; + /* Check if we got an error when sending long data */ + if (state == Query_arena::ERROR) + { + my_message(last_errno, last_error, MYF(0)); + return TRUE; + } + if (set_parameters(expanded_query, packet, packet_end)) return TRUE; @@ -3656,12 +3694,6 @@ bool Prepared_statement::execute(String status_var_increment(thd->status_var.com_stmt_execute); - /* Check if we got an error when sending long data */ - if (state == Query_arena::ERROR) - { - my_message(last_errno, last_error, MYF(0)); - return TRUE; - } if (flags & (uint) IS_IN_USE) { my_error(ER_PS_NO_RECURSION, MYF(0)); === modified file 'sql/sys_vars.cc' --- a/sql/sys_vars.cc 2011-02-17 11:53:09 +0000 +++ b/sql/sys_vars.cc 2011-03-11 09:03:21 +0000 @@ -1182,6 +1182,16 @@ static Sys_var_harows Sys_sql_max_join_s NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_max_join_size), DEPRECATED(70000, 0)); +static Sys_var_ulong Sys_max_long_data_size( + "max_long_data_size", + "The maximum BLOB length to send to server from " + "mysql_send_long_data API. Deprecated option; " + "use max_allowed_packet instead.", + READ_ONLY GLOBAL_VAR(max_long_data_size), + CMD_LINE(REQUIRED_ARG, OPT_MAX_LONG_DATA_SIZE), + VALID_RANGE(1024, UINT_MAX32), DEFAULT(1024*1024), + BLOCK_SIZE(1)); + static PolyLock_mutex PLock_prepared_stmt_count(&LOCK_prepared_stmt_count); static Sys_var_ulong Sys_max_prepared_stmt_count( "max_prepared_stmt_count", === modified file 'tests/mysql_client_test.c' --- a/tests/mysql_client_test.c 2011-02-18 14:19:55 +0000 +++ b/tests/mysql_client_test.c 2011-03-11 09:03:21 +0000 @@ -19503,6 +19503,56 @@ static void test_bug57058() /* + Bug #56976: Severe Denial Of Service in prepared statements +*/ +static void test_bug56976() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + int rc; + const char* query = "SELECT LENGTH(?)"; + char *long_buffer; + unsigned long i, packet_len = 256 * 1024L; + unsigned long dos_len = 2 * 1024 * 1024L; + + DBUG_ENTER("test_bug56976"); + myheader("test_bug56976"); + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + memset(bind, 0, sizeof(bind)); + bind[0].buffer_type = MYSQL_TYPE_TINY_BLOB; + + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + + long_buffer= (char*) my_malloc(packet_len, MYF(0)); + DIE_UNLESS(long_buffer); + + memset(long_buffer, 'a', packet_len); + + for (i= 0; i < dos_len / packet_len; i++) + { + rc= mysql_stmt_send_long_data(stmt, 0, long_buffer, packet_len); + check_execute(stmt, rc); + } + + my_free(long_buffer); + rc= mysql_stmt_execute(stmt); + + DIE_UNLESS(rc && mysql_stmt_errno(stmt) == ER_UNKNOWN_ERROR); + + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -19838,6 +19888,7 @@ static struct my_tests_st my_tests[]= { { "test_bug47485", test_bug47485 }, { "test_bug58036", test_bug58036 }, { "test_bug57058", test_bug57058 }, + { "test_bug56976", test_bug56976 }, { 0, 0 } }; --===============5995465070153345949== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.shulga@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.shulga@stripped\ # lra05cu59skbdebp # target_branch: file:///Users/shulga/projects/mysql/mysql-5.5/ # testament_sha1: fe1fed1a6ab02589406e73879d0556209ae414b4 # timestamp: 2011-03-11 15:12:04 +0600 # source_branch: file:///Users/shulga/projects/mysql/mysql-5.1-\ # bug58887/ # base_revision_id: marc.alff@stripped\ # tzul0sqjz3cxj3n2 # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWbxwdoQAEgl/gEiYRAB5//// /+//+r////pgH50n3e96jFnclrbqj1824dOeXfZ6NPNhNu3XNmPdnLXuzmqLd32fO7498J9Ps7sp pDVA+33H0523zQmmUqja7mEO20xtjNte26WiQUDTRBMkANNGmphCj9JtJoTynplP1TPVD1AabUPS AD1BKECYQaJMieptQ0ZQ0AABkNAAAAaaCUJhCEmCVP9TTTVPKaek9R6jBB6CeoyZD1HkQDTaTamE iEQKYjJpNNMNCJpowpiepoPU0ep6IZPUDR6mgAikQTBNAp4Jo00mnoKehqANEGhoHqGTIGmgEkQm QBDETASYJNqaaap6jRtCBkNDQAAengWKCzP2sBQu3/zGNcGlDCedGHbfxdtTNcFFP1bG+ITpLmFu l7yAR0KC8I4ojOULpKR8fePHw/Lb8AV8HHwGIf4JCVOSo2DBgqF9Uuq7z+SPqKl+kV8+0KAS2IyZ DbXYZY69kkt6a+kxNeLvyR6ZRl6TSZXI48MSOWRaTjCXnIdn+Pl/Ddnbmnt0A3MRm9O+saJrd59q nzqzpHa9+IMm5MJF7FTIpR0XReV19VkleyEeqTUIyg6E1Yji+UIE1/lURDXsz68hcMSzNmtc9ydS lHr6+mpx0ZKrFofFk00pV1rgZtUGGvkliczAquxg12YxKukupz3v3/miWLNjv3rYwNFiuys/QLER EECIQtvK0expLFiG0I+6wRw7pRI0MAbCQAhKIBqnLZrycYGqXadJsHmUQx5JfxJrK3COrkts9134 PQ6YdtJDXzQvjEG0QcBAxttttjBsY0222JjbQ2NghsNittj5QS8vj3uDdWzMzMBpLGx2QM33bWOc LPogzZMwS7j8sxNREPboXYsUzXezwwyjnk9myTvkzjRh5vhaNFFS97KqF4aNWhqtSrqsmHLKO7M1 7vdZlsC2ZYsXU0WWbCraVJdltElVutF8aZbN1Z83MQFsM3DLvLSM3inGEJvSc4mXg8mU8KjRMZbP IqxrjmF/HozHVlDJA7M9nNnYZvSop49D/hB3FsG7miBMgyMfvUBwp3e52Gcg32dEtt7pgCdAlz4r RiE0NDQpaLK7Do06Pnw5EonTnufwVCseUb7JtHOqePV7lv9dGsaE1jWeez3yDRWRnvGfDOczyXpf FuUfPqRCtJOo1GynVaSm61EDd+V8X9eWrWYkl8ymVriQMzTJ8BnVNHNs5uTlzZRJWg7ZnWoywrwP J3OOpx550atCl46riRtfnJqRb27STKZUZ9sO00Ddy0dnzFhy9DeRuCp7AgY65sLAuGVLL1kkWf6O CfDseeVXHs1e3eUbcIDumtbL44zqBSyjVMBBlpndDKSJ2ln52rzVX5CaV2VQL5CVOSRiefN5fVfG zejkCBjQurTgYqOuzJbuXjeIfpPbZ7LzuSqYQ6qbOizkZuFWy5tvZ0pFWvPDnqq9GGM3rivZK6Id 17ewTs6uvu9YIj0OXtjCL10D2Dt9onvDIugZBkAtDFCMVmw14QoZLJ1HmRQ22MbZ/r2Rs6dz1m2b Y3LCEau+jrxLp9WpVKNFPHaiBFKJqvY3XD3mAQIvZsZJtCEjtLlSHtXqpt+uL5QRsNu/1Ty3lln4 1aPL7Wwy8kwjHIQtIWG8DhwPvj7RB17r9GHClGkscS3n8Uos/00BblHqcB1iLuFkXX5ejungoZ/N xDUWIQOIH4c7ulKcK7rufzz53OkM9gqxu5Wo5JtKEIGSsRfOV63LnzgTzItTIxIextHEeH1f9hdc M2b34duUIQ2ev7p6tOFfnE+z9OfCjW9qT7x1YteunSblUsE7Ab8KqZDP1LAB3HP47ViR8oHKg5Ag xnzXITQKDwVQ6wa33JJ3Hh0ljBWSuew6tx5JyGys1p1EjorVa0qMLAHN9YUiYhoNA5Yo8CQJ0bnL VoiaLsQmgcOJIkjvy8M7bKXQ3toPyPdGujDFpC+M1cZXJxoozUi1BcRP6pRFoo4i1rOKDRSKR+km qq/JKBpggOj/uDEx5LtViEtQCTA9CO70MbSDda4ERAjTBnO3tbbYxtttxrPBy7+RzPe2+onWJA+u AJaJaCLwgpyyGkeK8LgyHTApw0NqzUXwPUFLJDyds0Ka1bEJq0rLGkespMBwk1KxSgQKQPIalA6Q MxGSkmcReAGpIzGBCMXM3wcCFg0kKQtqATJWIzbyQSZYkaezTiTqVzUlhJqEXAWJQlGxFVJEBECS SXkZDkLKK2KJoxHsxfKqblRaxSyYCgOnLiMEliWlQsggyhJDG/+XoRF0NDI5rEjyVIFjFjU2NhaJ z3w85hBGz0ad4Il1Ge7IeRURIYxcLgyGXjaNuuufClLgFbXEtx9VIqLB0l/+M61yLAVna92aUMxr VgFfe7SZ10IBeuFcxHaGnkeijNi29GoiIDsqAiY6GkPnowxLIiI4/YlHpklBaMD7cC4lhcuSLlVV FBZ0MZNWFVYzi4FMaFGn15wv3tVGp9Z920Ki9jBTOhk5DdZCrF0kpF6LRIjYq47jsNR2m8y2FrGp 8qIRTW5BBCk03M13kn0HGNr03F8jZGhuTxmpDmB6JpxDu1UAbHSogqDDAy1P7L/bgV4lYqBiy5pJ g2G8fImZ0RYIJecdo1hwKDxvIHEQYG52OB1xikgxNeeaJGNx4OJsbklsnFMM3UZFmy8LFTKNeGuP NWMukigyseKNohUZAIstWhoQZDJKn3bCWOF4CmF6MK5GhIzYOpuotipkiCqVZANytkVdSEkVAqxE 0M6Vom5Ewm8sO34DqpZUMci7PqOzLI4kkDDLKLT89KcekkQeMtthcyGKDFY3wYUU1KbbpD6qjCok KJtpv5cCp2L6F2ncUlKgKiUM7wHJMbhoEU4xIYJc3MTPZf+RVK5GtEkcDUY1uJuVESV5/Ue4d0bi hI4FZtNH+KI/gj3RWiYLxxPdGbFu7lHjHF8Xly375PKcLC05ncqVU2XTpftO2VQgtZEmEJPsMEkp IstRUY0kQ1J5zYb/xlJATL4B0obVdFOYt0N6nYRRErqKnK/HuGbcnDAVsq6EBsM+vVSEpUEG0ISd eS9bFF2JDhyvMhmF3kRaYWGJaEioIyFyxYcdxIFpIcykROCNLThVAEx5AuR2TfMyIrTPHOsaDG2m Rsxizl7uWMHueM5J4tFEJJZO9RiZySiE0ouegF+8MhkShXeMDDoVKOMbQGIMoOC2J4CDdk7b3saK TrkspK5XQkvfoWwTetlPJ25uPI4G57kpTJNOrY0MZk8MzQ6WNcdrkoT4p1IiJbWZ3bzHdGrJ7hrj DLTEKtQ+TGoIjRZTMuAw5obT0KDkyoNpeWm8IOQ8yQ5adEYH5AqeSIQR6TrQluzongVtE5Jvg0vY hS80irCvLXlGoNk78RjiYTIrgtH4X7esKbBlvHuNCB2njcReGpDjk8XlZMkNYIlhtxvBMjcZ10Ji PXJVuWka1HW1UnNSspnmhyGmFZRBcWG09/JDM2TY2HoefbrpuerQ47KjbuJFybhmZyCvSEiapbDe kq1uqS04AKqbFfKhwB/2m0iEi8oVIsRyAWEjIgOMbiiKFznjZca2QcDGlIO/zDcq4rpS9mliZz4E yJoqzy3ZtGeIQVVxttV7M8y1PhiysNiOtww4lWz3yTJo9SrKTmhoOhja5QcrJuMVzuaaSVNS4sCC GRRilkSBbqQkWKZM12lUcTgjxeNj4mCniYmR5G2qK6+pYoNRjFSDiQwtnmxx6nOFvCzi+iIMTKHN Y6WC8hE3EEELyhccajh480KESREY6VBcZET17BEO4vAS8AzLa92mig2jYRlUsBmDlCvC2Vle9r0Y Ad4GbYAyc7GmjOLRYwQEg2jbhjAYkrUhy8kUxPcE6qLHKyhG81LzRF1qHyEmonEehRFWk7UNGs5E tRMLiaxrd0lUcxoMkFFIrUWWDuszg6U2DVEql/Dv77vAR32uJFo7G0fIrRkVEkkpmt+hWw8yBikl RROvXItRcHZHRG1HsiMTsiSIo9EQOGGOnDjKOotoYbpKryiC6vbfz64RJUQrBktAw8LNYqhVJ7Ry R60bF8HeGLrqKaFm8RfMjdirHZ2W23m4aSOwM9KQSKxMzXTSApIdYVR2WUNY1wVXs8FdyMR1OTYU 4cDYbaCjK3N46QScBUhOw5j4HFL3xSJyJZFjE9DJ2bT5soD331caxjuc7VqKg5CjCGFqcVICXU5l 8yOkklFzce1pddq3mxRoQKVkag3QsRz57IPvJN4oxlETxQZyvBaOsVw6DmXRElEcUDquUsUUNkUN WY5Lg5QZ4l+M4onAw52MjhBiBQsOMCpUYsTHbyb7kjjQhAqqL5xLwF+OFRRa/TGm0cAyPxOy5qO7 a1vAich9Jsky5SiR3ErhE0lRzEKOIv4YyRdXQXBBqtcURCURjAuEsCFW5YzcvNqzKIgtZGG/15Df PaUS0hwIBFqoFKY9qiJ1lM/Yon5ltJnwl5fCzrXzAh5fJwn7G8zxvjNGbakpLrabY2MbbTQcQFMQ 4kCGNIBgYm4/UII7j4xHuz0H4PzWvu74L4XK+SUIL4fm48CXL8v8ypxSj9v4/+P+n2J+J7/5F6yT Ef3/lrXeEQRARCEAxBEm7GPt1Tm6Sxzkqn9Nq/PyIT3JuhP5lGVRSDhGg54+B/w8hZWtWBUHkMMM pGI1gisfpS57smOLAh9oemAoDJna9dDAjdenmOj+g6DHeTPC2OisJvmthdNyk35ILLW89ivdfYqp MDtxVQoY9v4JsrFtpSI3qNibxaQIKhgxLzAYTiiWlsafvETy+VWOde1IU1LUZBcwbzEljpHgfEZb hN9G2EnPwYrgVW87badnGiCdgHnjBdAJDknqdJrIencjtHnXMkTxMyA4EBHgMhri+ujfAbCAGIFC MGA/cezqfTS3ADSPfpuunYTvI2ZqIyIl+wYmzNuO6gdyhZkMGhwe3WlkbfgSTyrSx0C1gLvAD5n5 /X1Kc8rOKGsHknHcm77fvRAE9Tu8dh3uhmXM8bkk296D3n0/ek0fcn6PqoR87EBSsNsswigj2rAj BWGHPgl6xlIhABH3f1mqe4oS68yDOHAQJCVX1kBoXEexXWoAZfikCUg0SSYgauGukFCMTNOAMWPJ sjiGcGdX2/n+FJKiTIBe9XquMRDqPqGEBz5PUek/kXQ9Q5+nz3LjkDczHlsQGCRhiTKP5nUaxF06 giBAqK8C0+73qGlPvKTqNpv6eQhlRQ/g7DibjOYF2Yuaj3p06SohOqsoRJlZXhcAYJI7jqRvnCOn +c7/BN2S/mRVicmBvLYflQTps+1H1tGsWsQMAzMuZ5CbijSg+jwWlA+ig6ImbYS8HaL+iF6rkkga SBEyfXWoU7V+8maEqmRdJNjpLxLKWqGR3CLSdLwyH1QaPms2aSktiWY4Crdpquq8prNVAkcz2JzT RlzfX2HLw5sdweBx0Fh6So/ArMhQWmQ8ru+24zpaSLQYJBxKSZ5EjywMfw9fktprSwsJnrLi06ES JmWhqS+gC7JZ0laRVDI3Q9mZv5/s9Pj7s29hT2u9MjgA7U4GtVvtLC9d9hJO7IzDvfWgFkALYnBC w2lQE/LpnphoVqSFkjw0m49aFc3H8DkczpEKzU6jhaULioqO8iRMr8hzexzL6zuZF5kWmpuRQ80T NhxAO7HDBM8TE+wuOxicUHkwkN4FpURDOwyMTZt+5y4ZBPyKg9CyVY28+BqXJXDaCt9HDyZYo+Zu JjbGHGB0Azwo6I8eNkJBHkNiGVuQCH1nHFH1x+8dGb2K03o37URGAXCqoRhxXhmRC4YXFkvcYgyT aKhQ24Ig9LYd4gk1DukZHWFEeB955jM9PUwKyqJuHJGcisoSPIme/P2CssNC8tPXYQIjOMRYqNUI uLzMWdWYkXFm04lCuwbSovM7y4SC9UBQQMwZm/j19nHB2BhmZkMIDM0yNDUzHMTZM4jEjA/OEmG8 oESsZAsN1AH6U3JNiaFZ2dFtPvBFL1zexGvIgAdP8TsgYBwTDpDCHq22zBid3NpHJF5V7Nh9yLEU 3a+mylzjevKci539G6tx4Ucpai5Kh4QBZXH4JOF5YCYak1mycC7Oua1NPCBGGYcZnN2rK95kiOKK qwD0EQHaMIHZ2ULGx4Ct7spEwO/MhIfMckjbW6pTxzj6DDNnvxLVb45IfJEcT2KjEkfRHYfuWmYx Z6UOXJbG4tBgR9RBz1AzGRJkzA/JIVqSIzTHQqJmew01ORyCACmTUDwK0Erz1EalPbsfzeCCnbtO 6I8I0EmUVu8qtNm1kIPCgUG8yODqB1N46OXj93UuKN8hrnOfM4AuRzJnclhu4GqNDwQdK8jZm5ps 6o/+IrpgeCO6OfXYkL06qCjkMIRvPPmkZFI+rEKZfihKBpiCAN4pkSI+Q48lQg7sj0o4zHiIbcOI cMs8JKlsqQ5KoK4cBNh6Q4i6GPYaPkJt/ewDIdbCDDzoTR+2tGXldCcQDeavIAigTDIgBUUZVuED GIfK0ZgwWAA5uYhpV6AXIj3XSubcQiS4ChmOgwMz7D90H7oWInHJUOs6+RzO+ZSUQc+RLtB5HsmW dKcz4tloXngUlpCr7EpLT3I23k0VVjRR9CB9pImc1sKiBuUxs8S4eAxUTMpg3AkzUWkwLiw6kyGw E5gcwfFLCg4/aIbZCELqEOSaS00rckA9pU5IA0kNh6SSdBM70sSaelLfNOxL8CFTPJl4Fidh6aRp RHaCvEq6ygTalHfAzgZECNqadeaq0hkipXorW/ge623OfPDM7gpROK/j2Igi43guSojQHKGGqTjj kD6qAyUB0vhtRnFgEYy6oXONtMVgIoTGj5qg9yOvpw+xpar4/jcPGISYdN6++SMfO8Oh0oGqNfqU ASYjxXvNTR1PiGfqN6CSOLwGsBQL06yOpDxKp/jikEWos32woVyCDT8i1TMhed0G87TrWcChZhQY mZtQwM4VAlJsznc5BV2mUsS0O1uDuSzZczVIZZc0oksbHLHlmbalhcGQ0Rt7fI8zEtReMmGGBO4v zKu9+C3osgkERBDn3AOjTr7qoi+MSftMqfPZwKUVrIfqTBD1n3Yp6EFzcQ9JoZPHnclKePutDyOG pUuWiLEeKSW5yHwYNoCeaNNQUJID2pzL96dqpSayE9hqbl0ptS65MTcZYO4aY8CA+GyQwBEZBfmo gYffci0RawlkiwuMinujdgORgAI2ZXj3/NIg79FUGRSfxN3IJKFqKECGUhBoIxine7oDB3yyC0oH OZSZwcoK0gYmCFIXxU3kJ3EC5UiwjrraEVgmG4I/B6hITemAlyB2AKNOXu0SgKIpI68DiaWeVJEk MjaTK2ZhtpZBJIGHA7BLClYsFzo6N27upE8aIUIzHf+sI535iw/csyuj9CjBUXvHmcymogZWcXAu qKoNyWwcm1QHkwCDinhJ/OHpAWVuw4A7n6fMGnC8pwBNCBUVFR1AviacH6XLUmsjfF7uDgecdSSl SkQhBNJhuA+I3cbep7RkpNvcUxkKixzF72Bpcq+gryBhkjIPRjkwEyVrEFsRyRTC0RQJTKCJSiYA N8eNMowXYYKmMYm000MEJjEYOyGPYZHnvnesmJlLMF6VQLhgYK7T6pBcsEAJEoZDBADfBIc6YJ5l gVHypScuvygAhJcQZE08s0Aeytmagcak9qfFpZ7K0sRE0gBNgzzOn1GUUCkw72pMGmsLeZhcMwsP NNU4YYiBgHtRQzKk6YNDCUC+ZWaUFcQvbpqV4JVh4n5pLgldlV8LkFh9Ukt5wBpExAjqyPEIPoaS C4tO9J+aBwm5mCGEYNyB4ExCEXIidmNhfYbNYOtM6Uo8vQ9sbIHmivQIuj8Ljhu85nDMFuC9aoJh m4HtmbC+VpzSsgnURl4JSnrTpT0nynBOlV6wdadBsVfBPUbU6Pn8ToKUocyQAJxTmak3gvJgiA3h XP5HbsRzI6SBdHAiBjGDTGxjIhQNtg22htQhw2PgRAiQH0NdPcvCpLXDxDgl6bAEygQKqEjxkEQb Gg2KUOB+UF9/lSQK562Gog4yx0UQPkckTgbGEIkj9gZaI+cYxO47iYJY4tp6mFCd27TrCHyoQuBX mDDJDyBYpQSDVi5sS5AWVG1HFIWSDeEZ9CMyNIEJjNCGEERmSLgnBSgZAhJkEPZz9xgQ6cdMWyom 15VmUxseH0vWQiQU1FONFQSUPqdyq47kmXsepeAdl9vuaF5nuuydmH+OkA5dTryQMdmEbSMD7Rnj /AbEfgPAmeKeLfYBkgSILhDq5gLtxMuR4ANZgECCfWAvUdYHa0m0qM1tEG4ZsggiCCIIHccdxx3H GGHjdbx9PxXjmCYCiGVFWRRZGWgCmHSZIDp5V5EMWqkIsAwkZgGt+fubu6EWE80uWcKuLtpE0iHl UXA7gcURCLJlaitI+QQq8kShtrx3ovYxWz0M4S7SKgePxYyJSdS5MJWVYtVRjN7URcwLFMt3kjlq HDFYLJILiktCqvZWhtwTf4HqSstbL3KRakTlKFgoQORA5HcEEFAUIsISlIXztGblB3oYYESSZMOE tEgetTSSyErGeI1J1+pdIHLduY2BFNBwmCFBzTUd6YrSnXHZ2SCfd0r2P4gUzx0To7ksQ35cQ4zd vgMfQ+dxUdUVgt2chIjhA/Cngl1SpSNZsTxT46eRC1G67AFZxyIKXXQKT1JBg50oprOv0HF8zem0 ml4OoB8ZplSL67HWaN4GMEfIWv2lGUDYR9hEQLMNHVn6+ogPOo+YJLecOR3r5gUW87HK6i4hxoLY Y+AZokcbNth5MbVJ1JLey6IyBZI0R0AucRLA7dkjCIBgIymoIIT1/VRb4ms437E7A3jHYkFHY7T0 FNFIDuTR0Jtbk+Mqa4NQbk0lgGInSkvUZEI6JiUkHy2zCZiJalTrSabDpT4EvLw1m7OTsJqJlXUm CSKU4yEv2peu18Qtaq2SdjgUGhJ0JMRLU7052uc7p7ChRg1G1Ig7Akr+yOqIodG1EjBKlSH1DSiN 5oPVuVbvZ0kRaIMZ85oTOWhmzGDUm83p8ZVoS/aAskgqTgGo0JqN50JaXnAxxVa2m5NJwS5N2hNC dQcyGIH4Zf/F3JFOFCQvHB2hAA== --===============5995465070153345949==--