xref: /PHP-8.4/ext/pdo_sqlite/sqlite_driver.c (revision 11accb5c)
1 /*
2   +----------------------------------------------------------------------+
3   | Copyright (c) The PHP Group                                          |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | https://www.php.net/license/3_01.txt                                 |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Author: Wez Furlong <wez@php.net>                                    |
14   +----------------------------------------------------------------------+
15 */
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20 
21 #include "php.h"
22 #include "php_ini.h"
23 #include "ext/standard/info.h"
24 #include "ext/pdo/php_pdo.h"
25 #include "ext/pdo/php_pdo_driver.h"
26 #include "php_pdo_sqlite.h"
27 #include "php_pdo_sqlite_int.h"
28 #include "zend_exceptions.h"
29 #include "sqlite_driver_arginfo.h"
30 
_pdo_sqlite_error(pdo_dbh_t * dbh,pdo_stmt_t * stmt,const char * file,int line)31 int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line) /* {{{ */
32 {
33 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
34 	pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
35 	pdo_sqlite_error_info *einfo = &H->einfo;
36 
37 	einfo->errcode = sqlite3_errcode(H->db);
38 	einfo->file = file;
39 	einfo->line = line;
40 
41 	if (einfo->errcode != SQLITE_OK) {
42 		if (einfo->errmsg) {
43 			pefree(einfo->errmsg, dbh->is_persistent);
44 		}
45 		einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
46 	} else { /* no error */
47 		strncpy(*pdo_err, PDO_ERR_NONE, sizeof(*pdo_err));
48 		return 0;
49 	}
50 	switch (einfo->errcode) {
51 		case SQLITE_NOTFOUND:
52 			strncpy(*pdo_err, "42S02", sizeof(*pdo_err));
53 			break;
54 
55 		case SQLITE_INTERRUPT:
56 			strncpy(*pdo_err, "01002", sizeof(*pdo_err));
57 			break;
58 
59 		case SQLITE_NOLFS:
60 			strncpy(*pdo_err, "HYC00", sizeof(*pdo_err));
61 			break;
62 
63 		case SQLITE_TOOBIG:
64 			strncpy(*pdo_err, "22001", sizeof(*pdo_err));
65 			break;
66 
67 		case SQLITE_CONSTRAINT:
68 			strncpy(*pdo_err, "23000", sizeof(*pdo_err));
69 			break;
70 
71 		case SQLITE_ERROR:
72 		default:
73 			strncpy(*pdo_err, "HY000", sizeof(*pdo_err));
74 			break;
75 	}
76 
77 	if (!dbh->methods) {
78 		pdo_throw_exception(einfo->errcode, einfo->errmsg, pdo_err);
79 	}
80 
81 	return einfo->errcode;
82 }
83 /* }}} */
84 
pdo_sqlite_fetch_error_func(pdo_dbh_t * dbh,pdo_stmt_t * stmt,zval * info)85 static void pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
86 {
87 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
88 	pdo_sqlite_error_info *einfo = &H->einfo;
89 
90 	if (einfo->errcode) {
91 		add_next_index_long(info, einfo->errcode);
92 		add_next_index_string(info, einfo->errmsg);
93 	}
94 }
95 
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H)96 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
97 {
98 	struct pdo_sqlite_func *func;
99 
100 	while (H->funcs) {
101 		func = H->funcs;
102 		H->funcs = func->next;
103 
104 		if (H->db) {
105 			/* delete the function from the handle */
106 			sqlite3_create_function(H->db,
107 				func->funcname,
108 				func->argc,
109 				SQLITE_UTF8,
110 				func,
111 				NULL, NULL, NULL);
112 		}
113 
114 		efree((char*)func->funcname);
115 		if (ZEND_FCC_INITIALIZED(func->func)) {
116 			zend_fcc_dtor(&func->func);
117 		}
118 		if (ZEND_FCC_INITIALIZED(func->step)) {
119 			zend_fcc_dtor(&func->step);
120 		}
121 		if (ZEND_FCC_INITIALIZED(func->fini)) {
122 			zend_fcc_dtor(&func->fini);
123 		}
124 		efree(func);
125 	}
126 
127 	while (H->collations) {
128 		struct pdo_sqlite_collation *collation;
129 		collation = H->collations;
130 		H->collations = collation->next;
131 
132 		if (H->db) {
133 			/* delete the collation from the handle */
134 			sqlite3_create_collation(H->db,
135 				collation->name,
136 				SQLITE_UTF8,
137 				collation,
138 				NULL);
139 		}
140 
141 		efree((char*)collation->name);
142 		if (ZEND_FCC_INITIALIZED(collation->callback)) {
143 			zend_fcc_dtor(&collation->callback);
144 		}
145 		efree(collation);
146 	}
147 }
148 
sqlite_handle_closer(pdo_dbh_t * dbh)149 static void sqlite_handle_closer(pdo_dbh_t *dbh) /* {{{ */
150 {
151 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
152 
153 	if (H) {
154 		pdo_sqlite_error_info *einfo = &H->einfo;
155 
156 		pdo_sqlite_cleanup_callbacks(H);
157 		if (H->db) {
158 #ifdef HAVE_SQLITE3_CLOSE_V2
159 			sqlite3_close_v2(H->db);
160 #else
161 			sqlite3_close(H->db);
162 #endif
163 			H->db = NULL;
164 		}
165 		if (einfo->errmsg) {
166 			pefree(einfo->errmsg, dbh->is_persistent);
167 			einfo->errmsg = NULL;
168 		}
169 		pefree(H, dbh->is_persistent);
170 		dbh->driver_data = NULL;
171 	}
172 }
173 /* }}} */
174 
sqlite_handle_preparer(pdo_dbh_t * dbh,zend_string * sql,pdo_stmt_t * stmt,zval * driver_options)175 static bool sqlite_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options)
176 {
177 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
178 	pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
179 	int i;
180 	const char *tail;
181 
182 	S->H = H;
183 	stmt->driver_data = S;
184 	stmt->methods = &sqlite_stmt_methods;
185 	stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
186 
187 	if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY)) {
188 		H->einfo.errcode = SQLITE_ERROR;
189 		pdo_sqlite_error(dbh);
190 		return false;
191 	}
192 
193 	i = sqlite3_prepare_v2(H->db, ZSTR_VAL(sql), ZSTR_LEN(sql), &S->stmt, &tail);
194 	if (i == SQLITE_OK) {
195 		return true;
196 	}
197 
198 	pdo_sqlite_error(dbh);
199 
200 	return false;
201 }
202 
sqlite_handle_doer(pdo_dbh_t * dbh,const zend_string * sql)203 static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
204 {
205 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
206 
207 	if (sqlite3_exec(H->db, ZSTR_VAL(sql), NULL, NULL, NULL) != SQLITE_OK) {
208 		pdo_sqlite_error(dbh);
209 		return -1;
210 	} else {
211 		return sqlite3_changes(H->db);
212 	}
213 }
214 
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const zend_string * name)215 static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string *name)
216 {
217 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
218 
219 	return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
220 }
221 
222 /* NB: doesn't handle binary strings... use prepared stmts for that */
sqlite_handle_quoter(pdo_dbh_t * dbh,const zend_string * unquoted,enum pdo_param_type paramtype)223 static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
224 {
225 	char *quoted;
226 	if (ZSTR_LEN(unquoted) > (INT_MAX - 3) / 2) {
227 		return NULL;
228 	}
229 	quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
230 	/* TODO use %Q format? */
231 	sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted));
232 	zend_string *quoted_str = zend_string_init(quoted, strlen(quoted), 0);
233 	efree(quoted);
234 	return quoted_str;
235 }
236 
sqlite_handle_begin(pdo_dbh_t * dbh)237 static bool sqlite_handle_begin(pdo_dbh_t *dbh)
238 {
239 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
240 
241 	if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK) {
242 		pdo_sqlite_error(dbh);
243 		return false;
244 	}
245 	return true;
246 }
247 
sqlite_handle_commit(pdo_dbh_t * dbh)248 static bool sqlite_handle_commit(pdo_dbh_t *dbh)
249 {
250 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
251 
252 	if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) {
253 		pdo_sqlite_error(dbh);
254 		return false;
255 	}
256 	return true;
257 }
258 
sqlite_handle_rollback(pdo_dbh_t * dbh)259 static bool sqlite_handle_rollback(pdo_dbh_t *dbh)
260 {
261 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
262 
263 	if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, NULL) != SQLITE_OK) {
264 		pdo_sqlite_error(dbh);
265 		return false;
266 	}
267 	return true;
268 }
269 
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)270 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
271 {
272 	switch (attr) {
273 		case PDO_ATTR_CLIENT_VERSION:
274 		case PDO_ATTR_SERVER_VERSION:
275 			ZVAL_STRING(return_value, (char *)sqlite3_libversion());
276 			break;
277 
278 		default:
279 			return 0;
280 	}
281 
282 	return 1;
283 }
284 
pdo_sqlite_in_transaction(pdo_dbh_t * dbh)285 static bool pdo_sqlite_in_transaction(pdo_dbh_t *dbh)
286 {
287 	pdo_sqlite_db_handle* H = (pdo_sqlite_db_handle*) dbh->driver_data;
288 	/* It's not possible in sqlite3 to explicitly turn autocommit off other
289 	 * than manually starting a transaction. Manual transactions always are
290 	 * the mode of operation when autocommit is off. */
291 	return H->db && sqlite3_get_autocommit(H->db) == 0;
292 }
293 
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)294 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
295 {
296 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
297 	zend_long lval;
298 
299 	switch (attr) {
300 		case PDO_ATTR_TIMEOUT:
301 			if (!pdo_get_long_param(&lval, val)) {
302 				return false;
303 			}
304 			sqlite3_busy_timeout(H->db, lval * 1000);
305 			return true;
306 		case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
307 			if (!pdo_get_long_param(&lval, val)) {
308 				return false;
309 			}
310 			sqlite3_extended_result_codes(H->db, lval);
311 			return true;
312 	}
313 	return false;
314 }
315 
316 typedef struct {
317 	zval val;
318 	zend_long row;
319 } aggregate_context;
320 
do_callback(zend_fcall_info_cache * fcc,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)321 static int do_callback(zend_fcall_info_cache *fcc, int argc, sqlite3_value **argv, sqlite3_context *context, int is_agg)
322 {
323 	zval *zargs = NULL;
324 	zval retval;
325 	int i;
326 	int ret = SUCCESS;
327 	int fake_argc;
328 	aggregate_context *agg_context = NULL;
329 
330 	if (is_agg) {
331 		is_agg = 2;
332 	}
333 
334 	fake_argc = argc + is_agg;
335 
336 	/* build up the params */
337 	if (fake_argc) {
338 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
339 	}
340 
341 	if (is_agg) {
342 		agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
343 		if (!agg_context) {
344 			efree(zargs);
345 			return FAILURE;
346 		}
347 		if (Z_ISUNDEF(agg_context->val)) {
348 			ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
349 		}
350 		ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
351 		ZVAL_LONG(&zargs[1], ++agg_context->row);
352 	}
353 
354 	for (i = 0; i < argc; i++) {
355 		/* get the value */
356 		switch (sqlite3_value_type(argv[i])) {
357 			case SQLITE_INTEGER:
358 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
359 				break;
360 
361 			case SQLITE_FLOAT:
362 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
363 				break;
364 
365 			case SQLITE_NULL:
366 				ZVAL_NULL(&zargs[i + is_agg]);
367 				break;
368 
369 			case SQLITE_BLOB:
370 			case SQLITE3_TEXT:
371 			default:
372 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
373 				break;
374 		}
375 	}
376 
377 	zend_call_known_fcc(fcc, &retval, fake_argc, zargs, /* named_params */ NULL);
378 
379 	/* clean up the params */
380 	if (zargs) {
381 		for (i = is_agg; i < fake_argc; i++) {
382 			zval_ptr_dtor(&zargs[i]);
383 		}
384 		if (is_agg) {
385 			zval_ptr_dtor(&zargs[1]);
386 		}
387 		efree(zargs);
388 	}
389 
390 	if (!is_agg || !argv) {
391 		/* only set the sqlite return value if we are a scalar function,
392 		 * or if we are finalizing an aggregate */
393 		if (!Z_ISUNDEF(retval)) {
394 			switch (Z_TYPE(retval)) {
395 				case IS_LONG:
396 					sqlite3_result_int(context, Z_LVAL(retval));
397 					break;
398 
399 				case IS_NULL:
400 					sqlite3_result_null(context);
401 					break;
402 
403 				case IS_DOUBLE:
404 					sqlite3_result_double(context, Z_DVAL(retval));
405 					break;
406 
407 				default:
408 					if (!try_convert_to_string(&retval)) {
409 						ret = FAILURE;
410 						break;
411 					}
412 					sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
413 					break;
414 			}
415 		} else {
416 			sqlite3_result_error(context, "failed to invoke callback", 0);
417 		}
418 
419 		if (agg_context) {
420 			zval_ptr_dtor(&agg_context->val);
421 		}
422 	} else {
423 		/* we're stepping in an aggregate; the return value goes into
424 		 * the context */
425 		if (agg_context) {
426 			if (Z_ISUNDEF(retval)) {
427 				return FAILURE;
428 			}
429 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
430 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
431 			ZVAL_UNDEF(&retval);
432 		}
433 	}
434 
435 	if (!Z_ISUNDEF(retval)) {
436 		zval_ptr_dtor(&retval);
437 	}
438 
439 	return ret;
440 }
441 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)442 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
443 {
444 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
445 
446 	do_callback(&func->step, argc, argv, context, 1);
447 }
448 
php_sqlite3_func_final_callback(sqlite3_context * context)449 static void php_sqlite3_func_final_callback(sqlite3_context *context)
450 {
451 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
452 
453 	do_callback(&func->fini, 0, NULL, context, 1);
454 }
455 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)456 static int php_sqlite3_collation_callback(void *context, int string1_len, const void *string1, int string2_len, const void *string2)
457 {
458 	int ret = 0;
459 	zval zargs[2];
460 	zval retval;
461 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
462 
463 	/* Prepare the arguments. */
464 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
465 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
466 
467 	zend_call_known_fcc(&collation->callback, &retval, /* argc */ 2, zargs, /* named_params */ NULL);
468 
469 	if (!Z_ISUNDEF(retval)) {
470 		if (Z_TYPE(retval) != IS_LONG) {
471 			convert_to_long(&retval);
472 		}
473 		if (Z_LVAL(retval) > 0) {
474 			ret = 1;
475 		} else if (Z_LVAL(retval) < 0) {
476 			ret = -1;
477 		}
478 		zval_ptr_dtor(&retval);
479 	}
480 
481 	zval_ptr_dtor(&zargs[0]);
482 	zval_ptr_dtor(&zargs[1]);
483 
484 	return ret;
485 }
486 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)487 static void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
488 {
489 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
490 
491 	do_callback(&func->func, argc, argv, context, 0);
492 }
493 
pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)494 void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)
495 {
496 	struct pdo_sqlite_func *func;
497 	zend_fcall_info fci = empty_fcall_info;
498 	zend_fcall_info_cache fcc = empty_fcall_info_cache;
499 	char *func_name;
500 	size_t func_name_len;
501 	zend_long argc = -1;
502 	zend_long flags = 0;
503 	pdo_dbh_t *dbh;
504 	pdo_sqlite_db_handle *H;
505 	int ret;
506 
507 	ZEND_PARSE_PARAMETERS_START(2, 4)
508 		Z_PARAM_STRING(func_name, func_name_len)
509 		Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
510 		Z_PARAM_OPTIONAL
511 		Z_PARAM_LONG(argc)
512 		Z_PARAM_LONG(flags)
513 	ZEND_PARSE_PARAMETERS_END_EX(goto error;);
514 
515 	dbh = Z_PDO_DBH_P(ZEND_THIS);
516 	PDO_CONSTRUCT_CHECK;
517 
518 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
519 
520 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
521 
522 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, func, php_sqlite3_func_callback, NULL, NULL);
523 	if (ret == SQLITE_OK) {
524 		func->funcname = estrdup(func_name);
525 
526 		zend_fcc_dup(&func->func, &fcc);
527 
528 		func->argc = argc;
529 
530 		func->next = H->funcs;
531 		H->funcs = func;
532 
533 		RETURN_TRUE;
534 	}
535 
536 	efree(func);
537 
538 error:
539 	zend_release_fcall_info_cache(&fcc);
540 	RETURN_FALSE;
541 }
542 
543 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
544    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)545 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
546 {
547 	pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
548 }
549 /* }}} */
550 
pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)551 void pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)
552 {
553 	struct pdo_sqlite_func *func;
554 	zend_fcall_info step_fci = empty_fcall_info;
555 	zend_fcall_info fini_fci = empty_fcall_info;
556 	zend_fcall_info_cache step_fcc = empty_fcall_info_cache;
557 	zend_fcall_info_cache fini_fcc = empty_fcall_info_cache;
558 	char *func_name;
559 	size_t func_name_len;
560 	zend_long argc = -1;
561 	pdo_dbh_t *dbh;
562 	pdo_sqlite_db_handle *H;
563 	int ret;
564 
565 	ZEND_PARSE_PARAMETERS_START(3, 4)
566 		Z_PARAM_STRING(func_name, func_name_len)
567 		Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(step_fci, step_fcc)
568 		Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fini_fci, fini_fcc)
569 		Z_PARAM_OPTIONAL
570 		Z_PARAM_LONG(argc)
571 	ZEND_PARSE_PARAMETERS_END_EX(goto error;);
572 
573 	dbh = Z_PDO_DBH_P(ZEND_THIS);
574 	PDO_CONSTRUCT_CHECK;
575 
576 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
577 
578 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
579 
580 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, func, NULL,
581 		php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
582 	if (ret == SQLITE_OK) {
583 		func->funcname = estrdup(func_name);
584 
585 		zend_fcc_dup(&func->step, &step_fcc);
586 		zend_fcc_dup(&func->fini, &fini_fcc);
587 
588 		func->argc = argc;
589 
590 		func->next = H->funcs;
591 		H->funcs = func;
592 
593 		RETURN_TRUE;
594 	}
595 
596 	efree(func);
597 
598 error:
599 	zend_release_fcall_info_cache(&step_fcc);
600 	zend_release_fcall_info_cache(&fini_fcc);
601 	RETURN_FALSE;
602 }
603 
604 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
605    Registers a UDF with the sqlite db handle */
606 
607 /* The step function should have the prototype:
608    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
609 
610    $context will be null for the first row; on subsequent rows it will have
611    the value that was previously returned from the step function; you should
612    use this to maintain state for the aggregate.
613 
614    The fini function should have the prototype:
615    mixed fini(mixed $context, int $rownumber)
616 
617    $context will hold the return value from the very last call to the step function.
618    rownumber will hold the number of rows over which the aggregate was performed.
619    The return value of this function will be used as the return value for this
620    aggregate UDF.
621 */
622 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)623 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
624 {
625 	pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
626 }
627 /* }}} */
628 
pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS,pdo_sqlite_create_collation_callback callback)629 void pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS, pdo_sqlite_create_collation_callback callback)
630 {
631 	struct pdo_sqlite_collation *collation;
632 	zend_fcall_info fci = empty_fcall_info;
633 	zend_fcall_info_cache fcc = empty_fcall_info_cache;
634 	char *collation_name;
635 	size_t collation_name_len;
636 	pdo_dbh_t *dbh;
637 	pdo_sqlite_db_handle *H;
638 	int ret;
639 
640 	ZEND_PARSE_PARAMETERS_START(2, 2)
641 		Z_PARAM_STRING(collation_name, collation_name_len)
642 		Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
643 	ZEND_PARSE_PARAMETERS_END();
644 
645 	dbh = Z_PDO_DBH_P(ZEND_THIS);
646 	PDO_CONSTRUCT_CHECK;
647 
648 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
649 
650 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
651 
652 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, callback);
653 	if (ret == SQLITE_OK) {
654 		collation->name = estrdup(collation_name);
655 
656 		zend_fcc_dup(&collation->callback, &fcc);
657 
658 		collation->next = H->collations;
659 		H->collations = collation;
660 
661 		RETURN_TRUE;
662 	}
663 
664 	zend_release_fcall_info_cache(&fcc);
665 
666 	if (UNEXPECTED(EG(exception))) {
667 		RETURN_THROWS();
668 	}
669 
670 	efree(collation);
671 	RETURN_FALSE;
672 }
673 
674 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
675    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)676 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
677 {
678 	pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_sqlite3_collation_callback);
679 }
680 /* }}} */
681 
get_driver_methods(pdo_dbh_t * dbh,int kind)682 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
683 {
684 	switch (kind) {
685 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
686 			return class_PDO_SQLite_Ext_methods;
687 
688 		default:
689 			return NULL;
690 	}
691 }
692 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)693 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
694 {
695 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
696 	/* unregister functions, so that they don't linger for the next
697 	 * request */
698 	if (H) {
699 		pdo_sqlite_cleanup_callbacks(H);
700 	}
701 }
702 
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)703 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
704 {
705 	pdo_sqlite_db_handle *H = dbh->driver_data;
706 
707 	struct pdo_sqlite_func *func = H->funcs;
708 	while (func) {
709 		if (ZEND_FCC_INITIALIZED(func->func)) {
710 			zend_get_gc_buffer_add_fcc(gc_buffer, &func->func);
711 		}
712 		if (ZEND_FCC_INITIALIZED(func->step)) {
713 			zend_get_gc_buffer_add_fcc(gc_buffer, &func->step);
714 		}
715 		if (ZEND_FCC_INITIALIZED(func->fini)) {
716 			zend_get_gc_buffer_add_fcc(gc_buffer, &func->fini);
717 		}
718 		func = func->next;
719 	}
720 
721 	struct pdo_sqlite_collation *collation = H->collations;
722 	while (collation) {
723 		if (ZEND_FCC_INITIALIZED(collation->callback)) {
724 			zend_get_gc_buffer_add_fcc(gc_buffer, &collation->callback);
725 		}
726 		collation = collation->next;
727 	}
728 }
729 
730 static const struct pdo_dbh_methods sqlite_methods = {
731 	sqlite_handle_closer,
732 	sqlite_handle_preparer,
733 	sqlite_handle_doer,
734 	sqlite_handle_quoter,
735 	sqlite_handle_begin,
736 	sqlite_handle_commit,
737 	sqlite_handle_rollback,
738 	pdo_sqlite_set_attr,
739 	pdo_sqlite_last_insert_id,
740 	pdo_sqlite_fetch_error_func,
741 	pdo_sqlite_get_attribute,
742 	NULL,	/* check_liveness: not needed */
743 	get_driver_methods,
744 	pdo_sqlite_request_shutdown,
745 	pdo_sqlite_in_transaction,
746 	pdo_sqlite_get_gc,
747     pdo_sqlite_scanner
748 };
749 
make_filename_safe(const char * filename)750 static char *make_filename_safe(const char *filename)
751 {
752 	if (!filename) {
753 		return NULL;
754 	}
755 	if (*filename && strncasecmp(filename, "file:", 5) == 0) {
756 		if (PG(open_basedir) && *PG(open_basedir)) {
757 			return NULL;
758 		}
759 		return estrdup(filename);
760 	}
761 	if (*filename && strcmp(filename, ":memory:")) {
762 		char *fullpath = expand_filepath(filename, NULL);
763 
764 		if (!fullpath) {
765 			return NULL;
766 		}
767 
768 		if (php_check_open_basedir(fullpath)) {
769 			efree(fullpath);
770 			return NULL;
771 		}
772 		return fullpath;
773 	}
774 	return estrdup(filename);
775 }
776 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)777 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
778 		const char *arg5, const char *arg6)
779 {
780 	char *filename;
781 	switch (access_type) {
782 		case SQLITE_ATTACH: {
783 			filename = make_filename_safe(arg3);
784 			if (!filename) {
785 				return SQLITE_DENY;
786 			}
787 			efree(filename);
788 			return SQLITE_OK;
789 		}
790 
791 		default:
792 			/* access allowed */
793 			return SQLITE_OK;
794 	}
795 }
796 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)797 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
798 {
799 	pdo_sqlite_db_handle *H;
800 	int i, ret = 0;
801 	zend_long timeout = 60, flags;
802 	char *filename;
803 
804 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
805 
806 	H->einfo.errcode = 0;
807 	H->einfo.errmsg = NULL;
808 	dbh->driver_data = H;
809 
810 	/* skip all but this one param event */
811 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
812 
813 	filename = make_filename_safe(dbh->data_source);
814 
815 	if (!filename) {
816 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
817 			"open_basedir prohibits opening %s",
818 			dbh->data_source);
819 		goto cleanup;
820 	}
821 
822 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
823 
824 	if (!(PG(open_basedir) && *PG(open_basedir))) {
825 		flags |= SQLITE_OPEN_URI;
826 	}
827 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
828 
829 	efree(filename);
830 
831 	if (i != SQLITE_OK) {
832 		pdo_sqlite_error(dbh);
833 		goto cleanup;
834 	}
835 
836 	if (PG(open_basedir) && *PG(open_basedir)) {
837 		sqlite3_set_authorizer(H->db, authorizer, NULL);
838 	}
839 
840 	if (driver_options) {
841 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
842 	}
843 	sqlite3_busy_timeout(H->db, timeout * 1000);
844 
845 	dbh->alloc_own_columns = 1;
846 	dbh->max_escaped_char_length = 2;
847 
848 	ret = 1;
849 
850 cleanup:
851 	dbh->methods = &sqlite_methods;
852 
853 	return ret;
854 }
855 /* }}} */
856 
857 const pdo_driver_t pdo_sqlite_driver = {
858 	PDO_DRIVER_HEADER(sqlite),
859 	pdo_sqlite_handle_factory
860 };
861