@@ -2291,6 +2291,8 @@ static bool mariadb_dr_connect(
2291
2291
2292
2292
imp_dbh -> async_query_in_flight = NULL ;
2293
2293
2294
+ mariadb_list_add (imp_drh -> active_imp_dbhs , imp_dbh -> list_entry , imp_dbh );
2295
+
2294
2296
return TRUE;
2295
2297
}
2296
2298
@@ -2336,8 +2338,7 @@ static bool mariadb_db_my_login(pTHX_ SV* dbh, imp_dbh_t *imp_dbh)
2336
2338
char * user ;
2337
2339
char * password ;
2338
2340
char * mysql_socket ;
2339
- I32 i ;
2340
- bool found_taken_pmysql ;
2341
+ struct mariadb_list_entry * entry ;
2341
2342
D_imp_xxh (dbh );
2342
2343
D_imp_drh_from_dbh ;
2343
2344
@@ -2347,34 +2348,29 @@ static bool mariadb_db_my_login(pTHX_ SV* dbh, imp_dbh_t *imp_dbh)
2347
2348
{
2348
2349
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
2349
2350
PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "mariadb_db_my_login skip connect\n" );
2351
+
2350
2352
/* tell our parent we've adopted an active child */
2351
2353
++ DBIc_ACTIVE_KIDS (DBIc_PARENT_COM (imp_dbh ));
2352
- found_taken_pmysql = FALSE;
2353
- if ( imp_drh -> taken_pmysqls )
2354
+
2355
+ for ( entry = imp_drh -> taken_pmysqls ; entry ; entry = entry -> next )
2354
2356
{
2355
- for ( i = AvFILL ( imp_drh -> taken_pmysqls ); i >= 0 ; -- i )
2357
+ if (( MYSQL * ) entry -> data == imp_dbh -> pmysql )
2356
2358
{
2357
- svp = av_fetch (imp_drh -> taken_pmysqls , i , FALSE);
2358
- if (!svp || !* svp )
2359
- continue ;
2360
- SvGETMAGIC (* svp );
2361
- if (!SvIOK (* svp ))
2362
- continue ;
2363
- if (imp_dbh -> pmysql == INT2PTR (MYSQL * , SvIVX (* svp )))
2364
- {
2365
- found_taken_pmysql = TRUE;
2366
- av_delete (imp_drh -> taken_pmysqls , i , G_DISCARD );
2367
- break ;
2368
- }
2359
+ /* Remove MYSQL* entry from taken list */
2360
+ mariadb_list_remove (imp_drh -> taken_pmysqls , entry );
2361
+
2362
+ /* Add imp_dbh entry into active_imp_dbhs list */
2363
+ mariadb_list_add (imp_drh -> active_imp_dbhs , imp_dbh -> list_entry , imp_dbh );
2364
+
2365
+ return TRUE;
2369
2366
}
2370
2367
}
2371
- if (!found_taken_pmysql )
2372
- {
2373
- imp_dbh -> pmysql = NULL ;
2374
- mariadb_dr_do_error (dbh , CR_CONNECTION_ERROR , "Connection error: dbi_imp_data is not valid" , "HY000" );
2375
- return FALSE;
2376
- }
2377
- return TRUE;
2368
+
2369
+ /* This imp_dbh data belongs to different connection, so destructor should not touch it */
2370
+ imp_dbh -> list_entry = NULL ;
2371
+ imp_dbh -> pmysql = NULL ;
2372
+ mariadb_dr_do_error (dbh , CR_CONNECTION_ERROR , "Connection error: dbi_imp_data is not valid" , "HY000" );
2373
+ return FALSE;
2378
2374
}
2379
2375
if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
2380
2376
PerlIO_printf (DBIc_LOGPIO (imp_xxh ),
@@ -2445,12 +2441,15 @@ SV *mariadb_db_take_imp_data(SV *dbh, imp_xxh_t *imp_xxh, void *foo)
2445
2441
dTHX ;
2446
2442
D_imp_dbh (dbh );
2447
2443
D_imp_drh_from_dbh ;
2444
+ struct mariadb_list_entry * entry ;
2448
2445
PERL_UNUSED_ARG (imp_xxh );
2449
2446
PERL_UNUSED_ARG (foo );
2450
2447
2451
- if (!imp_drh -> taken_pmysqls )
2452
- imp_drh -> taken_pmysqls = newAV ();
2453
- av_push (imp_drh -> taken_pmysqls , newSViv (PTR2IV (imp_dbh -> pmysql )));
2448
+ /* Add MYSQL* into taken list */
2449
+ mariadb_list_add (imp_drh -> taken_pmysqls , entry , imp_dbh -> pmysql );
2450
+
2451
+ /* MYSQL* was taken from imp_dbh so remove it also from active_imp_dbhs list */
2452
+ mariadb_list_remove (imp_drh -> active_imp_dbhs , imp_dbh -> list_entry );
2454
2453
2455
2454
return & PL_sv_no ;
2456
2455
}
@@ -2979,39 +2978,23 @@ static void mariadb_dr_close_mysql(pTHX_ imp_drh_t *imp_drh, MYSQL *pmysql)
2979
2978
}
2980
2979
}
2981
2980
2982
- /*
2983
- ***************************************************************************
2984
- *
2985
- * Name: mariadb_db_disconnect
2986
- *
2987
- * Purpose: Disconnect a database handle from its database
2988
- *
2989
- * Input: dbh - database handle being disconnected
2990
- * imp_dbh - drivers private database handle data
2991
- *
2992
- * Returns: 1 for success (always)
2993
- *
2994
- **************************************************************************/
2995
-
2996
- int mariadb_db_disconnect (SV * dbh , imp_dbh_t * imp_dbh )
2981
+ static void mariadb_db_close_mysql (pTHX_ imp_drh_t * imp_drh , imp_dbh_t * imp_dbh )
2997
2982
{
2998
- dTHX ;
2999
2983
AV * av ;
3000
2984
I32 i ;
3001
2985
MAGIC * mg ;
3002
2986
SV * * svp ;
3003
2987
SV * sv ;
3004
2988
SV * sth ;
3005
2989
imp_sth_t * imp_sth ;
3006
- D_imp_xxh (dbh );
3007
- D_imp_drh_from_dbh ;
3008
2990
3009
- /* We assume that disconnect will always work */
3010
- /* since most errors imply already disconnected. */
2991
+ if (DBIc_TRACE_LEVEL (imp_dbh ) >= 2 )
2992
+ PerlIO_printf (DBIc_LOGPIO (imp_dbh ), "\tmariadb_db_close_mysql: imp_dbh=%p pmysql=%p\n" , imp_dbh , imp_dbh -> pmysql );
2993
+
3011
2994
DBIc_ACTIVE_off (imp_dbh );
3012
- if ( DBIc_TRACE_LEVEL ( imp_xxh ) >= 2 )
3013
- PerlIO_printf ( DBIc_LOGPIO ( imp_xxh ), " imp_dbh->pmysql: %p\n" ,
3014
- imp_dbh -> pmysql );
2995
+
2996
+ if ( imp_dbh -> list_entry )
2997
+ mariadb_list_remove ( imp_drh -> active_imp_dbhs , imp_dbh -> list_entry );
3015
2998
3016
2999
if (imp_dbh -> pmysql )
3017
3000
{
@@ -3045,14 +3028,39 @@ int mariadb_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh)
3045
3028
* CVE 2017-3302 do not do it. So do it manually to prevent crash. */
3046
3029
if (imp_sth -> stmt && imp_sth -> stmt -> mysql )
3047
3030
{
3048
- if (DBIc_TRACE_LEVEL (imp_xxh ) >= 2 )
3049
- PerlIO_printf (DBIc_LOGPIO (imp_xxh ), "Applying CVE 2017-3302 workaround for sth=0x %p\n" , imp_sth );
3031
+ if (DBIc_TRACE_LEVEL (imp_dbh ) >= 2 )
3032
+ PerlIO_printf (DBIc_LOGPIO (imp_dbh ), "Applying CVE 2017-3302 workaround for sth=%p\n" , imp_sth );
3050
3033
imp_sth -> stmt -> mysql = NULL ;
3051
3034
}
3052
3035
}
3053
3036
}
3054
3037
}
3055
3038
}
3039
+ }
3040
+
3041
+ /*
3042
+ ***************************************************************************
3043
+ *
3044
+ * Name: mariadb_db_disconnect
3045
+ *
3046
+ * Purpose: Disconnect a database handle from its database
3047
+ *
3048
+ * Input: dbh - database handle being disconnected
3049
+ * imp_dbh - drivers private database handle data
3050
+ *
3051
+ * Returns: 1 for success (always)
3052
+ *
3053
+ **************************************************************************/
3054
+
3055
+ int mariadb_db_disconnect (SV * dbh , imp_dbh_t * imp_dbh )
3056
+ {
3057
+ dTHX ;
3058
+ D_imp_drh_from_dbh ;
3059
+ PERL_UNUSED_ARG (dbh );
3060
+
3061
+ /* We assume that disconnect will always work */
3062
+ /* since most errors imply already disconnected. */
3063
+ mariadb_db_close_mysql (aTHX_ imp_drh , imp_dbh );
3056
3064
3057
3065
/* We don't free imp_dbh since a reference still exists */
3058
3066
/* The DESTROY method is the only one to 'free' memory. */
@@ -3075,57 +3083,18 @@ int mariadb_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh)
3075
3083
3076
3084
int mariadb_dr_discon_all (SV * drh , imp_drh_t * imp_drh ) {
3077
3085
dTHX ;
3078
- dSP ;
3079
3086
int ret ;
3080
- SV * * svp ;
3081
- AV * av ;
3082
- I32 i ;
3087
+ struct mariadb_list_entry * entry ;
3083
3088
PERL_UNUSED_ARG (drh );
3084
3089
3085
- if ( imp_drh -> taken_pmysqls )
3090
+ while (( entry = imp_drh -> taken_pmysqls ) )
3086
3091
{
3087
- for (i = AvFILL (imp_drh -> taken_pmysqls ); i >= 0 ; -- i )
3088
- {
3089
- svp = av_fetch (imp_drh -> taken_pmysqls , i , FALSE);
3090
- if (!svp || !* svp )
3091
- continue ;
3092
- SvGETMAGIC (* svp );
3093
- if (!SvIOK (* svp ))
3094
- continue ;
3095
- mariadb_dr_close_mysql (aTHX_ imp_drh , INT2PTR (MYSQL * , SvIVX (* svp )));
3096
- }
3097
- av_undef (imp_drh -> taken_pmysqls );
3098
- imp_drh -> taken_pmysqls = NULL ;
3092
+ mariadb_dr_close_mysql (aTHX_ imp_drh , (MYSQL * )entry -> data );
3093
+ mariadb_list_remove (imp_drh -> taken_pmysqls , entry );
3099
3094
}
3100
3095
3101
- svp = hv_fetchs ((HV * )DBIc_MY_H (imp_drh ), "ChildHandles" , FALSE);
3102
- if (svp && * svp )
3103
- {
3104
- SvGETMAGIC (* svp );
3105
- if (SvROK (* svp ) && SvTYPE (SvRV (* svp )) == SVt_PVAV )
3106
- {
3107
- av = (AV * )SvRV (* svp );
3108
- for (i = AvFILL (av ); i >= 0 ; -- i )
3109
- {
3110
- svp = av_fetch (av , i , FALSE);
3111
- if (!svp || !* svp || !sv_isobject (* svp ))
3112
- continue ;
3113
-
3114
- ENTER ;
3115
- SAVETMPS ;
3116
-
3117
- PUSHMARK (SP );
3118
- EXTEND (SP , 1 );
3119
- PUSHs (sv_2mortal (newSVsv (* svp )));
3120
- PUTBACK ;
3121
-
3122
- call_method ("disconnect" , G_VOID |G_DISCARD |G_EVAL |G_KEEPERR );
3123
-
3124
- FREETMPS ;
3125
- LEAVE ;
3126
- }
3127
- }
3128
- }
3096
+ while (imp_drh -> active_imp_dbhs )
3097
+ mariadb_db_close_mysql (aTHX_ imp_drh , (imp_dbh_t * )imp_drh -> active_imp_dbhs -> data );
3129
3098
3130
3099
ret = 1 ;
3131
3100
0 commit comments