xref: /PHP-8.0/ext/pdo_sqlite/sqlite_driver.c (revision 921b6813)
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   | http://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 int 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 	return 1;
96 }
97 
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H)98 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
99 {
100 	struct pdo_sqlite_func *func;
101 
102 	while (H->funcs) {
103 		func = H->funcs;
104 		H->funcs = func->next;
105 
106 		if (H->db) {
107 			/* delete the function from the handle */
108 			sqlite3_create_function(H->db,
109 				func->funcname,
110 				func->argc,
111 				SQLITE_UTF8,
112 				func,
113 				NULL, NULL, NULL);
114 		}
115 
116 		efree((char*)func->funcname);
117 		if (!Z_ISUNDEF(func->func)) {
118 			zval_ptr_dtor(&func->func);
119 		}
120 		if (!Z_ISUNDEF(func->step)) {
121 			zval_ptr_dtor(&func->step);
122 		}
123 		if (!Z_ISUNDEF(func->fini)) {
124 			zval_ptr_dtor(&func->fini);
125 		}
126 		efree(func);
127 	}
128 
129 	while (H->collations) {
130 		struct pdo_sqlite_collation *collation;
131 		collation = H->collations;
132 		H->collations = collation->next;
133 
134 		if (H->db) {
135 			/* delete the collation from the handle */
136 			sqlite3_create_collation(H->db,
137 				collation->name,
138 				SQLITE_UTF8,
139 				collation,
140 				NULL);
141 		}
142 
143 		efree((char*)collation->name);
144 		if (!Z_ISUNDEF(collation->callback)) {
145 			zval_ptr_dtor(&collation->callback);
146 		}
147 		efree(collation);
148 	}
149 }
150 
sqlite_handle_closer(pdo_dbh_t * dbh)151 static int sqlite_handle_closer(pdo_dbh_t *dbh) /* {{{ */
152 {
153 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
154 
155 	if (H) {
156 		pdo_sqlite_error_info *einfo = &H->einfo;
157 
158 		pdo_sqlite_cleanup_callbacks(H);
159 		if (H->db) {
160 #ifdef HAVE_SQLITE3_CLOSE_V2
161 			sqlite3_close_v2(H->db);
162 #else
163 			sqlite3_close(H->db);
164 #endif
165 			H->db = NULL;
166 		}
167 		if (einfo->errmsg) {
168 			pefree(einfo->errmsg, dbh->is_persistent);
169 			einfo->errmsg = NULL;
170 		}
171 		pefree(H, dbh->is_persistent);
172 		dbh->driver_data = NULL;
173 	}
174 	return 0;
175 }
176 /* }}} */
177 
sqlite_handle_preparer(pdo_dbh_t * dbh,const char * sql,size_t sql_len,pdo_stmt_t * stmt,zval * driver_options)178 static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options)
179 {
180 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
181 	pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
182 	int i;
183 	const char *tail;
184 
185 	S->H = H;
186 	stmt->driver_data = S;
187 	stmt->methods = &sqlite_stmt_methods;
188 	stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
189 
190 	if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY)) {
191 		H->einfo.errcode = SQLITE_ERROR;
192 		pdo_sqlite_error(dbh);
193 		return 0;
194 	}
195 
196 	i = sqlite3_prepare_v2(H->db, sql, sql_len, &S->stmt, &tail);
197 	if (i == SQLITE_OK) {
198 		return 1;
199 	}
200 
201 	pdo_sqlite_error(dbh);
202 
203 	return 0;
204 }
205 
sqlite_handle_doer(pdo_dbh_t * dbh,const char * sql,size_t sql_len)206 static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len)
207 {
208 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
209 	char *errmsg = NULL;
210 
211 	if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
212 		pdo_sqlite_error(dbh);
213 		if (errmsg)
214 			sqlite3_free(errmsg);
215 
216 		return -1;
217 	} else {
218 		return sqlite3_changes(H->db);
219 	}
220 }
221 
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const char * name,size_t * len)222 static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *len)
223 {
224 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
225 	char *id;
226 
227 	id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db));
228 	*len = strlen(id);
229 	return id;
230 }
231 
232 /* NB: doesn't handle binary strings... use prepared stmts for that */
sqlite_handle_quoter(pdo_dbh_t * dbh,const char * unquoted,size_t unquotedlen,char ** quoted,size_t * quotedlen,enum pdo_param_type paramtype)233 static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
234 {
235 	if (unquotedlen > (INT_MAX - 3) / 2) {
236 		return 0;
237 	}
238 	*quoted = safe_emalloc(2, unquotedlen, 3);
239 	sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
240 	*quotedlen = strlen(*quoted);
241 	return 1;
242 }
243 
sqlite_handle_begin(pdo_dbh_t * dbh)244 static int sqlite_handle_begin(pdo_dbh_t *dbh)
245 {
246 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
247 	char *errmsg = NULL;
248 
249 	if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
250 		pdo_sqlite_error(dbh);
251 		if (errmsg)
252 			sqlite3_free(errmsg);
253 		return 0;
254 	}
255 	return 1;
256 }
257 
sqlite_handle_commit(pdo_dbh_t * dbh)258 static int sqlite_handle_commit(pdo_dbh_t *dbh)
259 {
260 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
261 	char *errmsg = NULL;
262 
263 	if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
264 		pdo_sqlite_error(dbh);
265 		if (errmsg)
266 			sqlite3_free(errmsg);
267 		return 0;
268 	}
269 	return 1;
270 }
271 
sqlite_handle_rollback(pdo_dbh_t * dbh)272 static int sqlite_handle_rollback(pdo_dbh_t *dbh)
273 {
274 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
275 	char *errmsg = NULL;
276 
277 	if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
278 		pdo_sqlite_error(dbh);
279 		if (errmsg)
280 			sqlite3_free(errmsg);
281 		return 0;
282 	}
283 	return 1;
284 }
285 
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,zend_long attr,zval * return_value)286 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
287 {
288 	switch (attr) {
289 		case PDO_ATTR_CLIENT_VERSION:
290 		case PDO_ATTR_SERVER_VERSION:
291 			ZVAL_STRING(return_value, (char *)sqlite3_libversion());
292 			break;
293 
294 		default:
295 			return 0;
296 	}
297 
298 	return 1;
299 }
300 
pdo_sqlite_set_attr(pdo_dbh_t * dbh,zend_long attr,zval * val)301 static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
302 {
303 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
304 
305 	switch (attr) {
306 		case PDO_ATTR_TIMEOUT:
307 			sqlite3_busy_timeout(H->db, zval_get_long(val) * 1000);
308 			return 1;
309 		case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES:
310 			sqlite3_extended_result_codes(H->db, zval_get_long(val));
311 			return 1;
312 	}
313 	return 0;
314 }
315 
316 typedef struct {
317 	zval val;
318 	zend_long row;
319 } aggregate_context;
320 
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg)321 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
322 		int argc, sqlite3_value **argv, sqlite3_context *context,
323 		int is_agg)
324 {
325 	zval *zargs = NULL;
326 	zval retval;
327 	int i;
328 	int ret;
329 	int fake_argc;
330 	aggregate_context *agg_context = NULL;
331 
332 	if (is_agg) {
333 		is_agg = 2;
334 	}
335 
336 	fake_argc = argc + is_agg;
337 
338 	fc->fci.size = sizeof(fc->fci);
339 	ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
340 	fc->fci.object = NULL;
341 	fc->fci.retval = &retval;
342 	fc->fci.param_count = fake_argc;
343 
344 	/* build up the params */
345 
346 	if (fake_argc) {
347 		zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
348 	}
349 
350 	if (is_agg) {
351 		agg_context = sqlite3_aggregate_context(context, sizeof(aggregate_context));
352 		if (!agg_context) {
353 			efree(zargs);
354 			return FAILURE;
355 		}
356 		if (Z_ISUNDEF(agg_context->val)) {
357 			ZVAL_NEW_REF(&agg_context->val, &EG(uninitialized_zval));
358 		}
359 		ZVAL_COPY_VALUE(&zargs[0], &agg_context->val);
360 		ZVAL_LONG(&zargs[1], ++agg_context->row);
361 	}
362 
363 	for (i = 0; i < argc; i++) {
364 		/* get the value */
365 		switch (sqlite3_value_type(argv[i])) {
366 			case SQLITE_INTEGER:
367 				ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
368 				break;
369 
370 			case SQLITE_FLOAT:
371 				ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
372 				break;
373 
374 			case SQLITE_NULL:
375 				ZVAL_NULL(&zargs[i + is_agg]);
376 				break;
377 
378 			case SQLITE_BLOB:
379 			case SQLITE3_TEXT:
380 			default:
381 				ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
382 				break;
383 		}
384 	}
385 
386 	fc->fci.params = zargs;
387 
388 	if ((ret = zend_call_function(&fc->fci, &fc->fcc)) == FAILURE) {
389 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
390 	}
391 
392 	/* clean up the params */
393 	if (zargs) {
394 		for (i = is_agg; i < fake_argc; i++) {
395 			zval_ptr_dtor(&zargs[i]);
396 		}
397 		if (is_agg) {
398 			zval_ptr_dtor(&zargs[1]);
399 		}
400 		efree(zargs);
401 	}
402 
403 	if (!is_agg || !argv) {
404 		/* only set the sqlite return value if we are a scalar function,
405 		 * or if we are finalizing an aggregate */
406 		if (!Z_ISUNDEF(retval)) {
407 			switch (Z_TYPE(retval)) {
408 				case IS_LONG:
409 					sqlite3_result_int(context, Z_LVAL(retval));
410 					break;
411 
412 				case IS_NULL:
413 					sqlite3_result_null(context);
414 					break;
415 
416 				case IS_DOUBLE:
417 					sqlite3_result_double(context, Z_DVAL(retval));
418 					break;
419 
420 				default:
421 					if (!try_convert_to_string(&retval)) {
422 						ret = FAILURE;
423 						break;
424 					}
425 					sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
426 					break;
427 			}
428 		} else {
429 			sqlite3_result_error(context, "failed to invoke callback", 0);
430 		}
431 
432 		if (agg_context) {
433 			zval_ptr_dtor(&agg_context->val);
434 		}
435 	} else {
436 		/* we're stepping in an aggregate; the return value goes into
437 		 * the context */
438 		if (agg_context) {
439 			if (Z_ISUNDEF(retval)) {
440 				zval_ptr_dtor(&agg_context->val);
441 				return FAILURE;
442 			}
443 			zval_ptr_dtor(Z_REFVAL(agg_context->val));
444 			ZVAL_COPY_VALUE(Z_REFVAL(agg_context->val), &retval);
445 			ZVAL_UNDEF(&retval);
446 		}
447 	}
448 
449 	if (!Z_ISUNDEF(retval)) {
450 		zval_ptr_dtor(&retval);
451 	}
452 
453 	return ret;
454 }
455 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)456 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
457 	sqlite3_value **argv)
458 {
459 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
460 
461 	do_callback(&func->afunc, &func->func, argc, argv, context, 0);
462 }
463 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)464 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
465 	sqlite3_value **argv)
466 {
467 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
468 
469 	do_callback(&func->astep, &func->step, argc, argv, context, 1);
470 }
471 
php_sqlite3_func_final_callback(sqlite3_context * context)472 static void php_sqlite3_func_final_callback(sqlite3_context *context)
473 {
474 	struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
475 
476 	do_callback(&func->afini, &func->fini, 0, NULL, context, 1);
477 }
478 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)479 static int php_sqlite3_collation_callback(void *context,
480 	int string1_len, const void *string1,
481 	int string2_len, const void *string2)
482 {
483 	int ret;
484 	zval zargs[2];
485 	zval retval;
486 	struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
487 
488 	collation->fc.fci.size = sizeof(collation->fc.fci);
489 	ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
490 	collation->fc.fci.object = NULL;
491 	collation->fc.fci.retval = &retval;
492 
493 	// Prepare the arguments.
494 	ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
495 	ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
496 	collation->fc.fci.param_count = 2;
497 	collation->fc.fci.params = zargs;
498 
499 	if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc)) == FAILURE) {
500 		php_error_docref(NULL, E_WARNING, "An error occurred while invoking the callback");
501 	} else if (!Z_ISUNDEF(retval)) {
502 		if (Z_TYPE(retval) != IS_LONG) {
503 			convert_to_long_ex(&retval);
504 		}
505 		ret = 0;
506 		if (Z_LVAL(retval) > 0) {
507 			ret = 1;
508 		} else if (Z_LVAL(retval) < 0) {
509 			ret = -1;
510 		}
511 		zval_ptr_dtor(&retval);
512 	}
513 
514 	zval_ptr_dtor(&zargs[0]);
515 	zval_ptr_dtor(&zargs[1]);
516 
517 	return ret;
518 }
519 
520 /* {{{ bool SQLite::sqliteCreateFunction(string name, callable callback [, int argcount, int flags])
521    Registers a UDF with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateFunction)522 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateFunction)
523 {
524 	struct pdo_sqlite_func *func;
525 	zend_fcall_info fci;
526 	zend_fcall_info_cache fcc;
527 	char *func_name;
528 	size_t func_name_len;
529 	zend_long argc = -1;
530 	zend_long flags = 0;
531 	pdo_dbh_t *dbh;
532 	pdo_sqlite_db_handle *H;
533 	int ret;
534 
535 	ZEND_PARSE_PARAMETERS_START(2, 4)
536 		Z_PARAM_STRING(func_name, func_name_len)
537 		Z_PARAM_FUNC(fci, fcc)
538 		Z_PARAM_OPTIONAL
539 		Z_PARAM_LONG(argc)
540 		Z_PARAM_LONG(flags)
541 	ZEND_PARSE_PARAMETERS_END();
542 
543 	dbh = Z_PDO_DBH_P(ZEND_THIS);
544 	PDO_CONSTRUCT_CHECK;
545 
546 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
547 
548 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
549 
550 	ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8,
551 			func, php_sqlite3_func_callback, NULL, NULL);
552 	if (ret == SQLITE_OK) {
553 		func->funcname = estrdup(func_name);
554 
555 		ZVAL_COPY(&func->func, &fci.function_name);
556 
557 		func->argc = argc;
558 
559 		func->next = H->funcs;
560 		H->funcs = func;
561 
562 		RETURN_TRUE;
563 	}
564 
565 	efree(func);
566 	RETURN_FALSE;
567 }
568 /* }}} */
569 
570 /* {{{ bool SQLite::sqliteCreateAggregate(string name, callable step, callable fini [, int argcount])
571    Registers a UDF with the sqlite db handle */
572 
573 /* The step function should have the prototype:
574    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
575 
576    $context will be null for the first row; on subsequent rows it will have
577    the value that was previously returned from the step function; you should
578    use this to maintain state for the aggregate.
579 
580    The fini function should have the prototype:
581    mixed fini(mixed $context, int $rownumber)
582 
583    $context will hold the return value from the very last call to the step function.
584    rownumber will hold the number of rows over which the aggregate was performed.
585    The return value of this function will be used as the return value for this
586    aggregate UDF.
587 */
588 
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateAggregate)589 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateAggregate)
590 {
591 	struct pdo_sqlite_func *func;
592 	zend_fcall_info step_fci, fini_fci;
593 	zend_fcall_info_cache step_fcc, fini_fcc;
594 	char *func_name;
595 	size_t func_name_len;
596 	zend_long argc = -1;
597 	pdo_dbh_t *dbh;
598 	pdo_sqlite_db_handle *H;
599 	int ret;
600 
601 	ZEND_PARSE_PARAMETERS_START(3, 4)
602 		Z_PARAM_STRING(func_name, func_name_len)
603 		Z_PARAM_FUNC(step_fci, step_fcc)
604 		Z_PARAM_FUNC(fini_fci, fini_fcc)
605 		Z_PARAM_OPTIONAL
606 		Z_PARAM_LONG(argc)
607 	ZEND_PARSE_PARAMETERS_END();
608 
609 	dbh = Z_PDO_DBH_P(ZEND_THIS);
610 	PDO_CONSTRUCT_CHECK;
611 
612 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
613 
614 	func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
615 
616 	ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
617 			func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
618 	if (ret == SQLITE_OK) {
619 		func->funcname = estrdup(func_name);
620 
621 		ZVAL_COPY(&func->step, &step_fci.function_name);
622 
623 		ZVAL_COPY(&func->fini, &fini_fci.function_name);
624 
625 		func->argc = argc;
626 
627 		func->next = H->funcs;
628 		H->funcs = func;
629 
630 		RETURN_TRUE;
631 	}
632 
633 	efree(func);
634 	RETURN_FALSE;
635 }
636 /* }}} */
637 
638 /* {{{ bool SQLite::sqliteCreateCollation(string name, callable callback)
639    Registers a collation with the sqlite db handle */
PHP_METHOD(PDO_SQLite_Ext,sqliteCreateCollation)640 PHP_METHOD(PDO_SQLite_Ext, sqliteCreateCollation)
641 {
642 	struct pdo_sqlite_collation *collation;
643 	zend_fcall_info fci;
644 	zend_fcall_info_cache fcc;
645 	char *collation_name;
646 	size_t collation_name_len;
647 	pdo_dbh_t *dbh;
648 	pdo_sqlite_db_handle *H;
649 	int ret;
650 
651 	ZEND_PARSE_PARAMETERS_START(2, 2)
652 		Z_PARAM_STRING(collation_name, collation_name_len)
653 		Z_PARAM_FUNC(fci, fcc)
654 	ZEND_PARSE_PARAMETERS_END();
655 
656 	dbh = Z_PDO_DBH_P(ZEND_THIS);
657 	PDO_CONSTRUCT_CHECK;
658 
659 	H = (pdo_sqlite_db_handle *)dbh->driver_data;
660 
661 	collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
662 
663 	ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
664 	if (ret == SQLITE_OK) {
665 		collation->name = estrdup(collation_name);
666 
667 		ZVAL_COPY(&collation->callback, &fci.function_name);
668 
669 		collation->next = H->collations;
670 		H->collations = collation;
671 
672 		RETURN_TRUE;
673 	}
674 
675 	efree(collation);
676 	RETURN_FALSE;
677 }
678 /* }}} */
679 
get_driver_methods(pdo_dbh_t * dbh,int kind)680 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind)
681 {
682 	switch (kind) {
683 		case PDO_DBH_DRIVER_METHOD_KIND_DBH:
684 			return class_PDO_SQLite_Ext_methods;
685 
686 		default:
687 			return NULL;
688 	}
689 }
690 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh)691 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
692 {
693 	pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
694 	/* unregister functions, so that they don't linger for the next
695 	 * request */
696 	if (H) {
697 		pdo_sqlite_cleanup_callbacks(H);
698 	}
699 }
700 
701 static const struct pdo_dbh_methods sqlite_methods = {
702 	sqlite_handle_closer,
703 	sqlite_handle_preparer,
704 	sqlite_handle_doer,
705 	sqlite_handle_quoter,
706 	sqlite_handle_begin,
707 	sqlite_handle_commit,
708 	sqlite_handle_rollback,
709 	pdo_sqlite_set_attr,
710 	pdo_sqlite_last_insert_id,
711 	pdo_sqlite_fetch_error_func,
712 	pdo_sqlite_get_attribute,
713 	NULL,	/* check_liveness: not needed */
714 	get_driver_methods,
715 	pdo_sqlite_request_shutdown,
716 	NULL
717 };
718 
make_filename_safe(const char * filename)719 static char *make_filename_safe(const char *filename)
720 {
721 	if (!filename) {
722 		return NULL;
723 	}
724 	if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
725 		char *fullpath = expand_filepath(filename, NULL);
726 
727 		if (!fullpath) {
728 			return NULL;
729 		}
730 
731 		if (php_check_open_basedir(fullpath)) {
732 			efree(fullpath);
733 			return NULL;
734 		}
735 		return fullpath;
736 	}
737 	return estrdup(filename);
738 }
739 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)740 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
741 		const char *arg5, const char *arg6)
742 {
743 	char *filename;
744 	switch (access_type) {
745 		case SQLITE_COPY: {
746 			filename = make_filename_safe(arg4);
747 			if (!filename) {
748 				return SQLITE_DENY;
749 			}
750 			efree(filename);
751 			return SQLITE_OK;
752 		}
753 
754 		case SQLITE_ATTACH: {
755 			filename = make_filename_safe(arg3);
756 			if (!filename) {
757 				return SQLITE_DENY;
758 			}
759 			efree(filename);
760 			return SQLITE_OK;
761 		}
762 
763 		default:
764 			/* access allowed */
765 			return SQLITE_OK;
766 	}
767 }
768 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options)769 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
770 {
771 	pdo_sqlite_db_handle *H;
772 	int i, ret = 0;
773 	zend_long timeout = 60, flags;
774 	char *filename;
775 
776 	H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
777 
778 	H->einfo.errcode = 0;
779 	H->einfo.errmsg = NULL;
780 	dbh->driver_data = H;
781 
782 	/* skip all but this one param event */
783 	dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
784 
785 	filename = make_filename_safe(dbh->data_source);
786 
787 	if (!filename) {
788 		zend_throw_exception_ex(php_pdo_get_exception(), 0,
789 			"open_basedir prohibits opening %s",
790 			dbh->data_source);
791 		goto cleanup;
792 	}
793 
794 	flags = pdo_attr_lval(driver_options, PDO_SQLITE_ATTR_OPEN_FLAGS, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
795 
796 	i = sqlite3_open_v2(filename, &H->db, flags, NULL);
797 
798 	efree(filename);
799 
800 	if (i != SQLITE_OK) {
801 		pdo_sqlite_error(dbh);
802 		goto cleanup;
803 	}
804 
805 	if (PG(open_basedir) && *PG(open_basedir)) {
806 		sqlite3_set_authorizer(H->db, authorizer, NULL);
807 	}
808 
809 	if (driver_options) {
810 		timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout);
811 	}
812 	sqlite3_busy_timeout(H->db, timeout * 1000);
813 
814 	dbh->alloc_own_columns = 1;
815 	dbh->max_escaped_char_length = 2;
816 
817 	ret = 1;
818 
819 cleanup:
820 	dbh->methods = &sqlite_methods;
821 
822 	return ret;
823 }
824 /* }}} */
825 
826 const pdo_driver_t pdo_sqlite_driver = {
827 	PDO_DRIVER_HEADER(sqlite),
828 	pdo_sqlite_handle_factory
829 };
830