Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ php
/ext/json/json_scanner.c
/ext/json/php_json_scanner_defs.h
/ext/pdo/pdo_sql_parser.c
/ext/pdo_pgsql/pgsql_sql_parser.c
/ext/phar/phar_path_check.c
/ext/standard/url_scanner_ex.c
/ext/standard/var_unserializer.c
Expand Down
32 changes: 32 additions & 0 deletions ext/pdo/pdo_sql_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: George Schlossnagle <george@omniti.com> |
+----------------------------------------------------------------------+
*/

#define PDO_PARSER_TEXT 1
#define PDO_PARSER_BIND 2
#define PDO_PARSER_BIND_POS 3
#define PDO_PARSER_ESCAPED_QUESTION 4
#define PDO_PARSER_EOI 5

#define PDO_PARSER_BINDNO_ESCAPED_CHAR -1

#define RET(i) {s->cur = cursor; return i; }
#define SKIP_ONE(i) {s->cur = s->tok + 1; return i; }

#define YYCTYPE unsigned char
#define YYCURSOR cursor
#define YYLIMIT s->end
#define YYMARKER s->ptr
#define YYFILL(n) { RET(PDO_PARSER_EOI); }
11 changes: 5 additions & 6 deletions ext/pdo/pdo_sql_parser.re
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@
#define YYMARKER s->ptr
#define YYFILL(n) { RET(PDO_PARSER_EOI); }

typedef struct Scanner {
const char *ptr, *cur, *tok, *end;
} Scanner;

static int scan(Scanner *s)
static int default_scanner(pdo_parser_t *s)
{
const char *cursor = s->cur;

Expand Down Expand Up @@ -81,7 +77,7 @@ static void free_param_name(zval *el) {

PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string **outquery)
{
Scanner s;
pdo_parser_t s;
char *newbuffer;
ptrdiff_t t;
uint32_t bindno = 0;
Expand All @@ -91,6 +87,9 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
struct pdo_bound_param_data *param;
int query_type = PDO_PLACEHOLDER_NONE;
struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL;
int (*scan)(pdo_parser_t *s);

scan = stmt->dbh->methods->parser ? stmt->dbh->methods->parser : default_scanner;

s.cur = ZSTR_VAL(inquery);
s.end = s.cur + ZSTR_LEN(inquery) + 1;
Expand Down
11 changes: 10 additions & 1 deletion ext/pdo/php_pdo_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct _pdo_dbh_t pdo_dbh_t;
typedef struct _pdo_dbh_object_t pdo_dbh_object_t;
typedef struct _pdo_stmt_t pdo_stmt_t;
typedef struct _pdo_row_t pdo_row_t;
typedef struct _pdo_parser_t pdo_parser_t;
struct pdo_bound_param_data;

PDO_API zend_string *php_pdo_int64_to_str(int64_t i64);
Expand All @@ -35,7 +36,7 @@ PDO_API zend_string *php_pdo_int64_to_str(int64_t i64);
# define FALSE 0
#endif

#define PDO_DRIVER_API 20170320
#define PDO_DRIVER_API 20210325

enum pdo_param_type {
PDO_PARAM_NULL,
Expand Down Expand Up @@ -276,6 +277,9 @@ typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh);
* with any zvals in the driver_data that would be freed if the handle is destroyed. */
typedef void (*pdo_dbh_get_gc_func)(pdo_dbh_t *dbh, zend_get_gc_buffer *buffer);

/* driver specific re2s sql parser, overrides the default one if present */
typedef int (*pdo_dbh_sql_parser)(pdo_parser_t *s);

/* for adding methods to the dbh or stmt objects
pointer to a list of driver specific functions. The convention is
to prefix the function names using the PDO driver name; this will
Expand Down Expand Up @@ -308,6 +312,7 @@ struct pdo_dbh_methods {
/* if defined to NULL, PDO will use its internal transaction tracking state */
pdo_dbh_txn_func in_transaction;
pdo_dbh_get_gc_func get_gc;
pdo_dbh_sql_parser parser;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parser -> scanner, here and elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a couple of branches, not 100% sure I pushed the very latest one.

I was a bit undecided between scanner and parser and went back and forth a number of times, but it sounds like scanner is the winner ;-)

};

/* }}} */
Expand Down Expand Up @@ -648,6 +653,10 @@ struct _pdo_row_t {
pdo_stmt_t *stmt;
};

struct _pdo_parser_t {
const char *ptr, *cur, *tok, *end;
};

/* Call this in MINIT to register the PDO driver.
* Registering the driver might fail and should be reported accordingly in MINIT. */
PDO_API zend_result php_pdo_register_driver(const pdo_driver_t *driver);
Expand Down
7 changes: 7 additions & 0 deletions ext/pdo_pgsql/Makefile.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$(srcdir)/pgsql_sql_parser.c: $(srcdir)/pgsql_sql_parser.re
@(cd $(top_srcdir); \
if test -f ./pgsql_sql_parser.re; then \
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o pgsql_sql_parser.c pgsql_sql_parser.re; \
else \
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_pgsql/pgsql_sql_parser.c ext/pdo_pgsql/pgsql_sql_parser.re; \
fi)
3 changes: 3 additions & 0 deletions ext/pdo_pgsql/Makefile.frag.w32
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ext\pdo_pgsql\pgsql_sql_parser.c: ext\pdo_pgsql\pgsql_sql_parser.re
cd $(PHP_SRC_DIR)
$(RE2C) $(RE2C_FLAGS) --no-generation-date -o ext/pdo_pgsql/pgsql_sql_parser.c ext/pdo_pgsql/pgsql_sql_parser.re
3 changes: 2 additions & 1 deletion ext/pdo_pgsql/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ if test "$PHP_PDO_PGSQL" != "no"; then

PHP_CHECK_PDO_INCLUDES

PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_cv_inc_path)
PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c pgsql_sql_parser.c, $ext_shared,,-I$pdo_cv_inc_path)
PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo)
PHP_ADD_MAKEFILE_FRAGMENT
fi
3 changes: 2 additions & 1 deletion ext/pdo_pgsql/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ARG_WITH("pdo-pgsql", "PostgreSQL support for PDO", "no");
if (PHP_PDO_PGSQL != "no") {
if (CHECK_LIB("libpq.lib", "pdo_pgsql", PHP_PDO_PGSQL) &&
CHECK_HEADER_ADD_INCLUDE("libpq-fe.h", "CFLAGS_PDO_PGSQL", PHP_PDO_PGSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PHP_BUILD + "\\include\\libpq;")) {
EXTENSION("pdo_pgsql", "pdo_pgsql.c pgsql_driver.c pgsql_statement.c");
EXTENSION("pdo_pgsql", "pdo_pgsql.c pgsql_driver.c pgsql_statement.c pgsql_sql_parser.c");

if (X64) {
ADD_FLAG('CFLAGS_PDO_PGSQL', "/D HAVE_PG_LO64=1");
Expand All @@ -14,6 +14,7 @@ if (PHP_PDO_PGSQL != "no") {
AC_DEFINE('HAVE_PDO_PGSQL', 1, 'Have PostgreSQL library');

ADD_EXTENSION_DEP('pdo_pgsql', 'pdo');
ADD_MAKEFILE_FRAGMENT();
} else {
WARNING("pdo_pgsql not enabled; libraries and headers not found");
}
Expand Down
3 changes: 2 additions & 1 deletion ext/pdo_pgsql/pgsql_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,8 @@ static const struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_get_driver_methods, /* get_driver_methods */
NULL,
pgsql_handle_in_transaction,
NULL /* get_gc */
NULL, /* get_gc */
pdo_pgsql_parser
};

static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
Expand Down
49 changes: 49 additions & 0 deletions ext/pdo_pgsql/pgsql_sql_parser.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Matteo Beccati <mbeccati@php.net> |
+----------------------------------------------------------------------+
*/


#include "php.h"
#include "pdo/php_pdo_driver.h"
#include "pdo/php_pdo_int.h"
#include "pdo/pdo_sql_parser.h"

int pdo_pgsql_parser(pdo_parser_t *s)
{
const char *cursor = s->cur;

s->tok = cursor;
/*!re2c
BINDCHR = [:][a-zA-Z0-9_]+;
QUESTION = [?];
ESCQUESTION = [?][?];
COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*);
SPECIALS = [:?"'-/];
MULTICHAR = [:]{2,};
ANYNOEOF = [\001-\377];
*/

/*!re2c
(["]((["]["])|ANYNOEOF)*["]) { RET(PDO_PARSER_TEXT); }
(['](([']['])|ANYNOEOF)*[']) { RET(PDO_PARSER_TEXT); }
MULTICHAR { RET(PDO_PARSER_TEXT); }
ESCQUESTION { RET(PDO_PARSER_ESCAPED_QUESTION); }
BINDCHR { RET(PDO_PARSER_BIND); }
QUESTION { RET(PDO_PARSER_BIND_POS); }
SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); }
COMMENTS { RET(PDO_PARSER_TEXT); }
(ANYNOEOF\SPECIALS)+ { RET(PDO_PARSER_TEXT); }
*/
}
2 changes: 2 additions & 0 deletions ext/pdo_pgsql/php_pdo_pgsql_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,6 @@ extern const php_stream_ops pdo_pgsql_lob_stream_ops;

void pdo_libpq_version(char *buf, size_t len);

int pdo_pgsql_parser(pdo_parser_t *s);

#endif /* PHP_PDO_PGSQL_INT_H */
5 changes: 5 additions & 0 deletions scripts/dev/genfiles
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ $MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/pdo builddir=ext/pdo top_
-f ext/pdo/Makefile.frag \
ext/pdo/pdo_sql_parser.c

echo "genfiles: Generating PDO_pgsql lexer file"
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/pdo_pgsql builddir=ext/pdo_pgsql top_srcdir=. \
-f ext/pdo_pgsql/Makefile.frag \
ext/pdo_pgsql/pgsql_sql_parser.c

echo "genfiles: Generating standard extension lexer files"
$MAKE RE2C="$RE2C" RE2C_FLAGS="$RE2C_FLAGS" srcdir=ext/standard builddir=ext/standard top_srcdir=. \
-f ext/standard/Makefile.frag \
Expand Down