xref: /PHP-8.2/ext/pdo_sqlite/sqlite_driver.c (revision d6a0b3af)
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 "pdo/php_pdo.h"
25 #include "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 (!Z_ISUNDEF(func->func)) {
116 			zval_ptr_dtor(&func->func);
117 		}
118 		if (!Z_ISUNDEF(func->step)) {
119 			zval_ptr_dtor(&func->step);
120 		}
121 		if (!Z_ISUNDEF(func->fini)) {
122 			zval_ptr_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 (!Z_ISUNDEF(collation->callback)) {
143 			zval_ptr_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_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)285 static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
286 {
287 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
288 	zend_long lval;
289 
290 	switch (attr) {
291 		case PDO_ATTR_TIMEOUT:
292 			if (!pdo_get_long_param(&lval, val)) {
293 				return false;
294 			}
295 			sqlite3_busy_timeout(H->db, lval * 1000);
296 			return true;
297 		case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
298 			if (!pdo_get_long_param(&lval, val)) {
299 				return false;
300 			}
301 			sqlite3_extended_result_codes(H->db, lval);
302 			return true;
303 	}
304 	return false;
305 }
306 
307 typedef struct {
308 	zval val;
309 	zend_long row;
310 } aggregate_context;
311 
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)312 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, int argc, sqlite3_value **argv, sqlite3_context *context, int is_agg)
313 {
314 	zval *zargs = NULL;
315 	zval retval;
316 	int i;
317 	int ret;
318 	int fake_argc;
319 	aggregate_context *agg_context = NULL;
320 
321 	if (is_agg) {
322 		is_agg = 2;
323 	}
324 
325 	fake_argc = argc + is_agg;
326 
327 	fc->fci.size = sizeof(fc->fci);
328 	ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
329 	fc->fci.object = NULL;
330 	fc->fci.retval = &retval;
331 	fc->fci.param_count = fake_argc;
332 
333 	/* build up the params */
334 
335 	if (fake_argc) {
336 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
337 	}
338 
339 	if (is_agg) {
340 		agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
341 		if (!agg_context) {
342 			efree(zargs);
343 			return FAILURE;
344 		}
345 		if (Z_ISUNDEF(agg_context->val)) {
346 			ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
347 		}
348 		ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
349 		ZVAL_LONG(&zargs[1], ++agg_context->row);
350 	}
351 
352 	for (i = 0; i < argc; i++) {
353 		/* get the value */
354 		switch (sqlite3_value_type(argv[i])) {
355 			case SQLITE_INTEGER:
356 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
357 				break;
358 
359 			case SQLITE_FLOAT:
360 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
361 				break;
362 
363 			case SQLITE_NULL:
364 				ZVAL_NULL(&zargs[i + is_agg]);
365 				break;
366 
367 			case SQLITE_BLOB:
368 			case SQLITE3_TEXT:
369 			default:
370 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
371 				break;
372 		}
373 	}
374 
375 	fc->fci.params = zargs;
376 
377 	if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
378 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
379 	}
380 
381 	/* clean up the params */
382 	if (zargs) {
383 		for (i = is_agg; i < fake_argc; i++) {
384 			zval_ptr_dtor(&zargs[i]);
385 		}
386 		if (is_agg) {
387 			zval_ptr_dtor(&zargs[1]);
388 		}
389 		efree(zargs);
390 	}
391 
392 	if (!is_agg || !argv) {
393 		/* only set the sqlite return value if we are a scalar function,
394 		 * or if we are finalizing an aggregate */
395 		if (!Z_ISUNDEF(retval)) {
396 			switch (Z_TYPE(retval)) {
397 				case IS_LONG:
398 					sqlite3_result_int(context, Z_LVAL(retval));
399 					break;
400 
401 				case IS_NULL:
402 					sqlite3_result_null(context);
403 					break;
404 
405 				case IS_DOUBLE:
406 					sqlite3_result_double(context, Z_DVAL(retval));
407 					break;
408 
409 				default:
410 					if (!try_convert_to_string(&retval)) {
411 						ret = FAILURE;
412 						break;
413 					}
414 					sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
415 					break;
416 			}
417 		} else {
418 			sqlite3_result_error(context, "failed to invoke callback", 0);
419 		}
420 
421 		if (agg_context) {
422 			zval_ptr_dtor(&agg_context->val);
423 		}
424 	} else {
425 		/* we're stepping in an aggregate; the return value goes into
426 		 * the context */
427 		if (agg_context) {
428 			if (Z_ISUNDEF(retval)) {
429 				zval_ptr_dtor(&agg_context->val);
430 				return FAILURE;
431 			}
432 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
433 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
434 			ZVAL_UNDEF(&retval);
435 		}
436 	}
437 
438 	if (!Z_ISUNDEF(retval)) {
439 		zval_ptr_dtor(&retval);
440 	}
441 
442 	return ret;
443 }
444 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)445 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
446 {
447 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
448 
449 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
450 }
451 
php_sqlite3_func_final_callback(sqlite3_context * context)452 static void php_sqlite3_func_final_callback(sqlite3_context *context)
453 {
454 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
455 
456 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
457 }
458 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)459 static int php_sqlite3_collation_callback(void *context, int string1_len, const void *string1, int string2_len, const void *string2)
460 {
461 	int ret;
462 	zval zargs[2];
463 	zval retval;
464 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
465 
466 	collation->fc.fci.size = sizeof(collation->fc.fci);
467 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
468 	collation->fc.fci.object = NULL;
469 	collation->fc.fci.retval = &retval;
470 
471 	/* Prepare the arguments. */
472 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
473 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
474 	collation->fc.fci.param_count = 2;
475 	collation->fc.fci.params = zargs;
476 
477 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
478 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
479 	} else if (!Z_ISUNDEF(retval)) {
480 		if (Z_TYPE(retval) != IS_LONG) {
481 			convert_to_long(&retval);
482 		}
483 		ret = 0;
484 		if (Z_LVAL(retval) > 0) {
485 			ret = 1;
486 		} else if (Z_LVAL(retval) < 0) {
487 			ret = -1;
488 		}
489 		zval_ptr_dtor(&retval);
490 	}
491 
492 	zval_ptr_dtor(&zargs[0]);
493 	zval_ptr_dtor(&zargs[1]);
494 
495 	return ret;
496 }
497 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)498 static void php_sqlite3_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
499 {
500 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
501 
502 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
503 }
504 
pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)505 void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)
506 {
507 	struct pdo_sqlite_func *func;
508 	zend_fcall_info fci;
509 	zend_fcall_info_cache fcc;
510 	char *func_name;
511 	size_t func_name_len;
512 	zend_long argc = -1;
513 	zend_long flags = 0;
514 	pdo_dbh_t *dbh;
515 	pdo_sqlite_db_handle *H;
516 	int ret;
517 
518 	ZEND_PARSE_PARAMETERS_START(2, 4)
519 		Z_PARAM_STRING(func_name, func_name_len)
520 		Z_PARAM_FUNC(fci, fcc)
521 		Z_PARAM_OPTIONAL
522 		Z_PARAM_LONG(argc)
523 		Z_PARAM_LONG(flags)
524 	ZEND_PARSE_PARAMETERS_END();
525 
526 	dbh = Z_PDO_DBH_P(ZEND_THIS);
527 	PDO_CONSTRUCT_CHECK;
528 
529 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
530 
531 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
532 
533 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, func, php_sqlite3_func_callback, NULL, NULL);
534 	if (ret == SQLITE_OK) {
535 		func->funcname = estrdup(func_name);
536 
537 		ZVAL_COPY(&func->func, &fci.function_name);
538 
539 		func->argc = argc;
540 
541 		func->next = H->funcs;
542 		H->funcs = func;
543 
544 		RETURN_TRUE;
545 	}
546 
547 	efree(func);
548 	RETURN_FALSE;
549 }
550 
551 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
552    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)553 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
554 {
555 	pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
556 }
557 /* }}} */
558 
pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)559 void pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS)
560 {
561 	struct pdo_sqlite_func *func;
562 	zend_fcall_info step_fci, fini_fci;
563 	zend_fcall_info_cache step_fcc, fini_fcc;
564 	char *func_name;
565 	size_t func_name_len;
566 	zend_long argc = -1;
567 	pdo_dbh_t *dbh;
568 	pdo_sqlite_db_handle *H;
569 	int ret;
570 
571 	ZEND_PARSE_PARAMETERS_START(3, 4)
572 		Z_PARAM_STRING(func_name, func_name_len)
573 		Z_PARAM_FUNC(step_fci, step_fcc)
574 		Z_PARAM_FUNC(fini_fci, fini_fcc)
575 		Z_PARAM_OPTIONAL
576 		Z_PARAM_LONG(argc)
577 	ZEND_PARSE_PARAMETERS_END();
578 
579 	dbh = Z_PDO_DBH_P(ZEND_THIS);
580 	PDO_CONSTRUCT_CHECK;
581 
582 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
583 
584 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
585 
586 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, func, NULL,
587 		php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
588 	if (ret == SQLITE_OK) {
589 		func->funcname = estrdup(func_name);
590 
591 		ZVAL_COPY(&func->step, &step_fci.function_name);
592 
593 		ZVAL_COPY(&func->fini, &fini_fci.function_name);
594 
595 		func->argc = argc;
596 
597 		func->next = H->funcs;
598 		H->funcs = func;
599 
600 		RETURN_TRUE;
601 	}
602 
603 	efree(func);
604 	RETURN_FALSE;
605 }
606 
607 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
608    Registers a UDF with the sqlite db handle */
609 
610 /* The step function should have the prototype:
611    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
612 
613    $context will be null for the first row; on subsequent rows it will have
614    the value that was previously returned from the step function; you should
615    use this to maintain state for the aggregate.
616 
617    The fini function should have the prototype:
618    mixed fini(mixed $context, int $rownumber)
619 
620    $context will hold the return value from the very last call to the step function.
621    rownumber will hold the number of rows over which the aggregate was performed.
622    The return value of this function will be used as the return value for this
623    aggregate UDF.
624 */
625 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)626 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
627 {
628 	pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
629 }
630 /* }}} */
631 
pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS,pdo_sqlite_create_collation_callback callback)632 void pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS, pdo_sqlite_create_collation_callback callback)
633 {
634 	struct pdo_sqlite_collation *collation;
635 	zend_fcall_info fci;
636 	zend_fcall_info_cache fcc;
637 	char *collation_name;
638 	size_t collation_name_len;
639 	pdo_dbh_t *dbh;
640 	pdo_sqlite_db_handle *H;
641 	int ret;
642 
643 	ZEND_PARSE_PARAMETERS_START(2, 2)
644 		Z_PARAM_STRING(collation_name, collation_name_len)
645 		Z_PARAM_FUNC(fci, fcc)
646 	ZEND_PARSE_PARAMETERS_END();
647 
648 	dbh = Z_PDO_DBH_P(ZEND_THIS);
649 	PDO_CONSTRUCT_CHECK;
650 
651 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
652 
653 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
654 
655 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, callback);
656 	if (ret == SQLITE_OK) {
657 		collation->name = estrdup(collation_name);
658 
659 		ZVAL_COPY(&collation->callback, &fci.function_name);
660 
661 		collation->next = H->collations;
662 		H->collations = collation;
663 
664 		RETURN_TRUE;
665 	}
666 
667 	if (UNEXPECTED(EG(exception))) {
668 		RETURN_THROWS();
669 	}
670 
671 	efree(collation);
672 	RETURN_FALSE;
673 }
674 
675 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
676    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)677 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
678 {
679 	pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_sqlite3_collation_callback);
680 }
681 /* }}} */
682 
get_driver_methods(pdo_dbh_t * dbh,int kind)683 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
684 {
685 	switch (kind) {
686 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
687 			return class_PDO_SQLite_Ext_methods;
688 
689 		default:
690 			return NULL;
691 	}
692 }
693 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)694 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
695 {
696 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
697 	/* unregister functions, so that they don't linger for the next
698 	 * request */
699 	if (H) {
700 		pdo_sqlite_cleanup_callbacks(H);
701 	}
702 }
703 
pdo_sqlite_get_gc(pdo_dbh_t * dbh,zend_get_gc_buffer * gc_buffer)704 static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
705 {
706 	pdo_sqlite_db_handle *H = dbh->driver_data;
707 
708 	struct pdo_sqlite_func *func = H->funcs;
709 	while (func) {
710 		zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
711 		zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
712 		zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
713 		func = func->next;
714 	}
715 
716 	struct pdo_sqlite_collation *collation = H->collations;
717 	while (collation) {
718 		zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
719 		collation = collation->next;
720 	}
721 }
722 
723 static const struct pdo_dbh_methods sqlite_methods = {
724 	sqlite_handle_closer,
725 	sqlite_handle_preparer,
726 	sqlite_handle_doer,
727 	sqlite_handle_quoter,
728 	sqlite_handle_begin,
729 	sqlite_handle_commit,
730 	sqlite_handle_rollback,
731 	pdo_sqlite_set_attr,
732 	pdo_sqlite_last_insert_id,
733 	pdo_sqlite_fetch_error_func,
734 	pdo_sqlite_get_attribute,
735 	NULL,	/* check_liveness: not needed */
736 	get_driver_methods,
737 	pdo_sqlite_request_shutdown,
738 	NULL, /* in transaction, use PDO's internal tracking mechanism */
739 	pdo_sqlite_get_gc
740 };
741 
make_filename_safe(const char * filename)742 static char *make_filename_safe(const char *filename)
743 {
744 	if (!filename) {
745 		return NULL;
746 	}
747 	if (*filename && strncasecmp(filename, "file:", 5) == 0) {
748 		if (PG(open_basedir) && *PG(open_basedir)) {
749 			return NULL;
750 		}
751 		return estrdup(filename);
752 	}
753 	if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
754 		char *fullpath = expand_filepath(filename, NULL);
755 
756 		if (!fullpath) {
757 			return NULL;
758 		}
759 
760 		if (php_check_open_basedir(fullpath)) {
761 			efree(fullpath);
762 			return NULL;
763 		}
764 		return fullpath;
765 	}
766 	return estrdup(filename);
767 }
768 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)769 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
770 		const char *arg5, const char *arg6)
771 {
772 	char *filename;
773 	switch (access_type) {
774 		case SQLITE_ATTACH: {
775 			filename = make_filename_safe(arg3);
776 			if (!filename) {
777 				return SQLITE_DENY;
778 			}
779 			efree(filename);
780 			return SQLITE_OK;
781 		}
782 
783 		default:
784 			/* access allowed */
785 			return SQLITE_OK;
786 	}
787 }
788 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)789 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
790 {
791 	pdo_sqlite_db_handle *H;
792 	int i, ret = 0;
793 	zend_long timeout = 60, flags;
794 	char *filename;
795 
796 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
797 
798 	H->einfo.errcode = 0;
799 	H->einfo.errmsg = NULL;
800 	dbh->driver_data = H;
801 
802 	/* skip all but this one param event */
803 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
804 
805 	filename = make_filename_safe(dbh->data_source);
806 
807 	if (!filename) {
808 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
809 			"open_basedir prohibits opening %s",
810 			dbh->data_source);
811 		goto cleanup;
812 	}
813 
814 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
815 
816 	if (!(PG(open_basedir) && *PG(open_basedir))) {
817 		flags |= SQLITE_OPEN_URI;
818 	}
819 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
820 
821 	efree(filename);
822 
823 	if (i != SQLITE_OK) {
824 		pdo_sqlite_error(dbh);
825 		goto cleanup;
826 	}
827 
828 	if (PG(open_basedir) && *PG(open_basedir)) {
829 		sqlite3_set_authorizer(H->db, authorizer, NULL);
830 	}
831 
832 	if (driver_options) {
833 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
834 	}
835 	sqlite3_busy_timeout(H->db, timeout * 1000);
836 
837 	dbh->alloc_own_columns = 1;
838 	dbh->max_escaped_char_length = 2;
839 
840 	ret = 1;
841 
842 cleanup:
843 	dbh->methods = &sqlite_methods;
844 
845 	return ret;
846 }
847 /* }}} */
848 
849 const pdo_driver_t pdo_sqlite_driver = {
850 	PDO_DRIVER_HEADER(sqlite),
851 	pdo_sqlite_handle_factory
852 };
853