@@ -97,6 +97,10 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
9797{
9898 struct pdo_sqlite_func * func ;
9999
100+ if (ZEND_FCC_INITIALIZED (H -> authorizer_fcc )) {
101+ zend_fcc_dtor (& H -> authorizer_fcc );
102+ }
103+
100104 while (H -> funcs ) {
101105 func = H -> funcs ;
102106 H -> funcs = func -> next ;
@@ -714,6 +718,10 @@ static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
714718{
715719 pdo_sqlite_db_handle * H = dbh -> driver_data ;
716720
721+ if (ZEND_FCC_INITIALIZED (H -> authorizer_fcc )) {
722+ zend_get_gc_buffer_add_fcc (gc_buffer , & H -> authorizer_fcc );
723+ }
724+
717725 struct pdo_sqlite_func * func = H -> funcs ;
718726 while (func ) {
719727 if (ZEND_FCC_INITIALIZED (func -> func )) {
@@ -784,24 +792,77 @@ static char *make_filename_safe(const char *filename)
784792 return estrdup (filename );
785793}
786794
787- static int authorizer (void * autharg , int access_type , const char * arg3 , const char * arg4 ,
788- const char * arg5 , const char * arg6 )
795+ #define ZVAL_NULLABLE_STRING (zv , str ) do { \
796+ zval *zv_ = zv; \
797+ const char *str_ = str; \
798+ if (str_) { \
799+ ZVAL_STRING(zv_, str_); \
800+ } else { \
801+ ZVAL_NULL(zv_); \
802+ } \
803+ } while (0)
804+
805+ static int authorizer (void * autharg , int access_type , const char * arg1 , const char * arg2 ,
806+ const char * arg3 , const char * arg4 )
789807{
790- char * filename ;
791- switch (access_type ) {
792- case SQLITE_ATTACH : {
793- filename = make_filename_safe (arg3 );
808+ if (PG (open_basedir ) && * PG (open_basedir )) {
809+ if (access_type == SQLITE_ATTACH ) {
810+ char * filename = make_filename_safe (arg1 );
794811 if (!filename ) {
795812 return SQLITE_DENY ;
796813 }
797814 efree (filename );
798- return SQLITE_OK ;
799815 }
816+ }
800817
801- default :
802- /* access allowed */
803- return SQLITE_OK ;
818+ pdo_sqlite_db_handle * db_obj = autharg ;
819+
820+ /* fallback to access allowed if authorizer callback is not defined */
821+ if (!ZEND_FCC_INITIALIZED (db_obj -> authorizer_fcc )) {
822+ return SQLITE_OK ;
823+ }
824+
825+ /* call userland authorizer callback, if set */
826+ zval retval ;
827+ zval argv [5 ];
828+
829+ ZVAL_LONG (& argv [0 ], access_type );
830+ ZVAL_NULLABLE_STRING (& argv [1 ], arg1 );
831+ ZVAL_NULLABLE_STRING (& argv [2 ], arg2 );
832+ ZVAL_NULLABLE_STRING (& argv [3 ], arg3 );
833+ ZVAL_NULLABLE_STRING (& argv [4 ], arg4 );
834+
835+ int authreturn = SQLITE_DENY ;
836+
837+ zend_call_known_fcc (& db_obj -> authorizer_fcc , & retval , /* argc */ 5 , argv , /* named_params */ NULL );
838+ if (Z_ISUNDEF (retval )) {
839+ ZEND_ASSERT (EG (exception ));
840+ } else {
841+ if (Z_TYPE (retval ) != IS_LONG ) {
842+ zend_string * func_name = get_active_function_or_method_name ();
843+ zend_type_error ("%s(): Return value of the authorizer callback must be of type int, %s returned" ,
844+ ZSTR_VAL (func_name ), zend_zval_value_name (& retval ));
845+ zend_string_release (func_name );
846+ } else {
847+ authreturn = Z_LVAL (retval );
848+
849+ if (authreturn != SQLITE_OK && authreturn != SQLITE_IGNORE && authreturn != SQLITE_DENY ) {
850+ zend_string * func_name = get_active_function_or_method_name ();
851+ zend_value_error ("%s(): Return value of the authorizer callback must be one of Pdo\\Sqlite::OK, Pdo\\Sqlite::DENY, or Pdo\\Sqlite::IGNORE" ,
852+ ZSTR_VAL (func_name ));
853+ zend_string_release (func_name );
854+ authreturn = SQLITE_DENY ;
855+ }
856+ }
804857 }
858+
859+ zval_ptr_dtor (& retval );
860+ zval_ptr_dtor (& argv [1 ]);
861+ zval_ptr_dtor (& argv [2 ]);
862+ zval_ptr_dtor (& argv [3 ]);
863+ zval_ptr_dtor (& argv [4 ]);
864+
865+ return authreturn ;
805866}
806867
807868static int pdo_sqlite_handle_factory (pdo_dbh_t * dbh , zval * driver_options ) /* {{{ */
@@ -843,9 +904,7 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{
843904 goto cleanup ;
844905 }
845906
846- if (PG (open_basedir ) && * PG (open_basedir )) {
847- sqlite3_set_authorizer (H -> db , authorizer , NULL );
848- }
907+ sqlite3_set_authorizer (H -> db , authorizer , H );
849908
850909 if (driver_options ) {
851910 timeout = pdo_attr_lval (driver_options , PDO_ATTR_TIMEOUT , timeout );
0 commit comments