Skip to content

Commit 985b227

Browse files
committed
changes from feedback, using cache
1 parent ec1cdb0 commit 985b227

File tree

2 files changed

+74
-89
lines changed

2 files changed

+74
-89
lines changed

ext/pgsql/pgsql.c

Lines changed: 70 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -490,8 +490,55 @@ static PHP_GINIT_FUNCTION(pgsql)
490490
#if defined(COMPILE_DL_PGSQL) && defined(ZTS)
491491
ZEND_TSRMLS_CACHE_UPDATE();
492492
#endif
493+
494+
size_t i = 0;
493495
memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
494496
zend_hash_init(&pgsql_globals->connections, 0, NULL, NULL, 1);
497+
498+
#define ADD_REGEX(reg) \
499+
do { \
500+
ZEND_ASSERT(i < PGSQL_MAX_REGEXES); \
501+
pgsql_globals->regexes[i ++] = zend_string_init(reg, strlen(reg), true);\
502+
} while(0)
503+
ADD_REGEX("#^([+-]{0,1}[0-9]+)$#n");
504+
ADD_REGEX("#^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$#n");
505+
ADD_REGEX("#^[+-]{0,1}(inf)(inity){0,1}$#ni");
506+
ADD_REGEX("#^[0-9]+$#n");
507+
ADD_REGEX("#^((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])(\\/[0-9]{1,3})?$#n");
508+
ADD_REGEX("#^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(\\/[0-9]{1,3})?$#n");
509+
ADD_REGEX("#^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})(([ \\t]+|T)(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}(\\.[0-9]+){0,1}([ \\t]*([+-][0-9]{1,4}(:[0-9]{1,2}){0,1}|[-a-zA-Z_/+]{1,50})){0,1})){0,1}$#ni");
510+
ADD_REGEX("#^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$#ni");
511+
ADD_REGEX("#^(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}){0,1}$#ni");
512+
ADD_REGEX("#^(@?[ \\t]+)?("
513+
/* Textual time units and their abbreviations: */
514+
"(([-+]?[ \\t]+)?"
515+
"[0-9]+(\\.[0-9]*)?[ \\t]*"
516+
"(millenniums|millennia|millennium|mil|mils|"
517+
"centuries|century|cent|c|"
518+
"decades|decade|dec|decs|"
519+
"years|year|y|"
520+
"months|month|mon|"
521+
"weeks|week|w|"
522+
"days|day|d|"
523+
"hours|hour|hr|hrs|h|"
524+
"minutes|minute|mins|min|m|"
525+
"seconds|second|secs|sec|s))+|"
526+
/* Textual time units plus (dd)* hh[:mm[:ss]] */
527+
"((([-+]?[ \\t]+)?"
528+
"[0-9]+(\\.[0-9]*)?[ \\t]*"
529+
"(millenniums|millennia|millennium|mil|mils|"
530+
"centuries|century|cent|c|"
531+
"decades|decade|dec|decs|"
532+
"years|year|y|"
533+
"months|month|mon|"
534+
"weeks|week|w|"
535+
"days|day|d))+"
536+
"([-+]?[ \\t]+"
537+
"([0-9]+[ \\t]+)+" /* dd */
538+
"(([0-9]{1,2}:){0,2}[0-9]{0,2})" /* hh:[mm:[ss]] */
539+
")?))"
540+
"([ \\t]+ago)?$#ni");
541+
ADD_REGEX("#^([0-9a-f]{2,2}:){5,5}[0-9a-f]{2,2}$#ni");
495542
}
496543

497544
static void php_libpq_version(char *buf, size_t len)
@@ -560,6 +607,9 @@ PHP_MSHUTDOWN_FUNCTION(pgsql)
560607
UNREGISTER_INI_ENTRIES();
561608
zend_hash_destroy(&PGG(connections));
562609

610+
for (size_t i = 0; i < PGSQL_MAX_REGEXES; i ++)
611+
zend_string_release_ex(PGG(regexes[i]), true);
612+
563613
return SUCCESS;
564614
}
565615

@@ -4671,15 +4721,13 @@ static php_pgsql_data_type php_pgsql_get_data_type(const zend_string *type_name)
46714721
/* {{{ php_pgsql_convert_match
46724722
* test field value with regular expression specified.
46734723
*/
4674-
static int php_pgsql_convert_match(const zend_string *str, const char *regex , size_t regex_len, int icase)
4724+
static int php_pgsql_convert_match(const zend_string *str, zend_string *regex)
46754725
{
4726+
pcre_cache_entry *centry;
46764727
pcre2_code *re;
4677-
PCRE2_SIZE err_offset;
4678-
int res, errnumber;
4679-
uint32_t options = PCRE2_NO_AUTO_CAPTURE;
4728+
int res;
46804729
size_t i;
46814730
pcre2_match_data *match_data;
4682-
PCRE2_UCHAR err_msg[128];
46834731

46844732
/* Check invalid chars for POSIX regex */
46854733
for (i = 0; i < ZSTR_LEN(str); i++) {
@@ -4690,38 +4738,21 @@ static int php_pgsql_convert_match(const zend_string *str, const char *regex , s
46904738
}
46914739
}
46924740

4693-
if (icase) {
4694-
options |= PCRE2_CASELESS;
4695-
}
4696-
4697-
re = pcre2_compile((PCRE2_SPTR)regex, regex_len, options, &errnumber, &err_offset, php_pcre_cctx());
4698-
if (NULL == re) {
4699-
pcre2_get_error_message(errnumber, err_msg, sizeof(err_msg));
4700-
php_error_docref(NULL, E_WARNING, "Cannot compile regex: '%s'", err_msg);
4741+
centry = pcre_get_compiled_regex_cache(regex);
4742+
if (NULL == centry) {
47014743
return FAILURE;
47024744
}
4703-
#if defined(HAVE_PCRE_JIT_SUPPORT)
4704-
if (PCRE_G(jit)) {
4705-
/*
4706-
* Check if the JIT pass did not work, but the regex had been compiled successfully earlier
4707-
* so let's not end it here.
4708-
*/
4709-
if (UNEXPECTED(pcre2_jit_compile(re, PCRE2_JIT_COMPLETE) != 0)) {
4710-
pcre2_get_error_message(errnumber, err_msg, sizeof(err_msg));
4711-
php_error_docref(NULL, E_WARNING, "Cannot use JIT on regex: '%s'", err_msg);
4712-
}
4713-
}
4714-
#endif
47154745

4746+
re = php_pcre_pce_re(centry);
47164747
match_data = php_pcre_create_match_data(0, re);
47174748
if (NULL == match_data) {
4718-
pcre2_code_free(re);
47194749
php_error_docref(NULL, E_WARNING, "Cannot allocate match data");
47204750
return FAILURE;
47214751
}
4752+
php_pcre_pce_incref(centry);
47224753
res = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(str), ZSTR_LEN(str), 0, 0, match_data, php_pcre_mctx());
47234754
php_pcre_free_match_data(match_data);
4724-
pcre2_code_free(re);
4755+
php_pcre_pce_decref(centry);
47254756

47264757
if (res == PCRE2_ERROR_NOMATCH) {
47274758
return FAILURE;
@@ -4902,14 +4933,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
49024933
}
49034934
else {
49044935
/* FIXME: better regex must be used */
4905-
#define REGEX0 "^([+-]{0,1}[0-9]+)$"
4906-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 0) == FAILURE) {
4936+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[0])) == FAILURE) {
49074937
err = 1;
49084938
}
49094939
else {
49104940
ZVAL_STRINGL(&new_val, Z_STRVAL_P(val), Z_STRLEN_P(val));
49114941
}
4912-
#undef REGEX0
49134942
}
49144943
break;
49154944

@@ -4945,11 +4974,9 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
49454974
ZVAL_STR(&new_val, ZSTR_KNOWN(ZEND_STR_NULL));
49464975
}
49474976
else {
4948-
#define REGEX0 "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$"
4949-
#define REGEX1 "^[+-]{0,1}(inf)(inity){0,1}$"
49504977
/* better regex? */
4951-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 0) == FAILURE) {
4952-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX1, sizeof(REGEX1)-1, 1) == FAILURE) {
4978+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[1])) == FAILURE) {
4979+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[2])) == FAILURE) {
49534980
err = 1;
49544981
} else {
49554982
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
@@ -4958,8 +4985,6 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
49584985
else {
49594986
ZVAL_STRING(&new_val, Z_STRVAL_P(val));
49604987
}
4961-
#undef REGEX0
4962-
#undef REGEX1
49634988
}
49644989
break;
49654990

@@ -5055,7 +5080,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
50555080
}
50565081
else {
50575082
/* better regex? */
5058-
if (php_pgsql_convert_match(Z_STR_P(val), "^[0-9]+$", sizeof("^[0-9]+$")-1, 0) == FAILURE) {
5083+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[3])) == FAILURE) {
50595084
err = 1;
50605085
}
50615086
else {
@@ -5095,20 +5120,16 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
50955120
ZVAL_STR(&new_val, ZSTR_KNOWN(ZEND_STR_NULL));
50965121
}
50975122
else {
5098-
#define REGEX0 "^((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])(\\/[0-9]{1,3})?$"
5099-
#define REGEX1 "^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(\\/[0-9]{1,3})?$"
51005123
/* The inet type holds an IPv4 or IPv6 host address, and optionally its subnet, all in one field. See more in the doc.
51015124
The regex might still be not perfect, but catches the most of IP variants. We might decide to remove the regex
51025125
at all though and let the server side to handle it.*/
5103-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 0) == FAILURE
5104-
&& php_pgsql_convert_match(Z_STR_P(val), REGEX1, sizeof(REGEX1)-1, 0) == FAILURE) {
5126+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[4])) == FAILURE
5127+
&& php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[5])) == FAILURE) {
51055128
err = 2;
51065129
}
51075130
else {
51085131
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
51095132
}
5110-
#undef REGEX0
5111-
#undef REGEX1
51125133
}
51135134
break;
51145135

@@ -5139,14 +5160,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51395160
} else if (zend_string_equals_literal_ci(Z_STR_P(val), "now()")) {
51405161
ZVAL_STRINGL(&new_val, "NOW()", sizeof("NOW()")-1);
51415162
} else {
5142-
#define REGEX0 "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})(([ \\t]+|T)(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}(\\.[0-9]+){0,1}([ \\t]*([+-][0-9]{1,4}(:[0-9]{1,2}){0,1}|[-a-zA-Z_/+]{1,50})){0,1})){0,1}$"
51435163
/* better regex? */
5144-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 1) == FAILURE) {
5164+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[6])) == FAILURE) {
51455165
err = 1;
51465166
} else {
51475167
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
51485168
}
5149-
#undef REGEX0
51505169
}
51515170
break;
51525171

@@ -5170,15 +5189,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51705189
ZVAL_STR(&new_val, ZSTR_KNOWN(ZEND_STR_NULL));
51715190
}
51725191
else {
5173-
#define REGEX0 "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$"
51745192
/* FIXME: better regex must be used */
5175-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 1) == FAILURE) {
5193+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[7])) == FAILURE) {
51765194
err = 1;
51775195
}
51785196
else {
51795197
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
51805198
}
5181-
#undef REGEX0
51825199
}
51835200
break;
51845201

@@ -5202,15 +5219,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
52025219
ZVAL_STR(&new_val, ZSTR_KNOWN(ZEND_STR_NULL));
52035220
}
52045221
else {
5205-
#define REGEX0 "^(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}){0,1}$"
52065222
/* FIXME: better regex must be used */
5207-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 1) == FAILURE) {
5223+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[8])) == FAILURE) {
52085224
err = 1;
52095225
}
52105226
else {
52115227
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
52125228
}
5213-
#undef REGEX0
52145229
}
52155230
break;
52165231

@@ -5251,44 +5266,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
52515266
unit markings. For example, '1 12:59:10' is read the same as '1 day 12 hours 59 min 10
52525267
sec'.
52535268
*/
5254-
#define REGEX0 \
5255-
"^(@?[ \\t]+)?(" \
5256-
/* Textual time units and their abbreviations: */ \
5257-
"(([-+]?[ \\t]+)?" \
5258-
"[0-9]+(\\.[0-9]*)?[ \\t]*" \
5259-
"(millenniums|millennia|millennium|mil|mils|" \
5260-
"centuries|century|cent|c|" \
5261-
"decades|decade|dec|decs|" \
5262-
"years|year|y|" \
5263-
"months|month|mon|" \
5264-
"weeks|week|w|" \
5265-
"days|day|d|" \
5266-
"hours|hour|hr|hrs|h|" \
5267-
"minutes|minute|mins|min|m|" \
5268-
"seconds|second|secs|sec|s))+|" \
5269-
/* Textual time units plus (dd)* hh[:mm[:ss]] */ \
5270-
"((([-+]?[ \\t]+)?" \
5271-
"[0-9]+(\\.[0-9]*)?[ \\t]*" \
5272-
"(millenniums|millennia|millennium|mil|mils|" \
5273-
"centuries|century|cent|c|" \
5274-
"decades|decade|dec|decs|" \
5275-
"years|year|y|" \
5276-
"months|month|mon|" \
5277-
"weeks|week|w|" \
5278-
"days|day|d))+" \
5279-
"([-+]?[ \\t]+" \
5280-
"([0-9]+[ \\t]+)+" /* dd */ \
5281-
"(([0-9]{1,2}:){0,2}[0-9]{0,2})" /* hh:[mm:[ss]] */ \
5282-
")?))" \
5283-
"([ \\t]+ago)?$"
5284-
5285-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 1) == FAILURE) {
5269+
5270+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[9])) == FAILURE) {
52865271
err = 1;
52875272
}
52885273
else {
52895274
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
52905275
}
5291-
#undef REGEX0
52925276
}
52935277
break;
52945278

@@ -5353,14 +5337,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
53535337
ZVAL_STR(&new_val, ZSTR_KNOWN(ZEND_STR_NULL));
53545338
}
53555339
else {
5356-
#define REGEX0 "^([0-9a-f]{2,2}:){5,5}[0-9a-f]{2,2}$"
5357-
if (php_pgsql_convert_match(Z_STR_P(val), REGEX0, sizeof(REGEX0)-1, 1) == FAILURE) {
5340+
if (php_pgsql_convert_match(Z_STR_P(val), PGG(regexes[10])) == FAILURE) {
53585341
err = 1;
53595342
}
53605343
else {
53615344
ZVAL_STR(&new_val, php_pgsql_add_quotes(Z_STR_P(val)));
53625345
}
5363-
#undef REGEX0
53645346
}
53655347
break;
53665348

ext/pgsql/php_pgsql.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,17 @@ static const php_stream_ops php_stream_pgsql_fd_ops = {
175175
php_pgsql_fd_set_option
176176
};
177177

178+
#define PGSQL_MAX_REGEXES 11
179+
178180
ZEND_BEGIN_MODULE_GLOBALS(pgsql)
179181
zend_long num_links,num_persistent;
180182
zend_long max_links,max_persistent;
181183
bool allow_persistent;
182-
int ignore_notices;
184+
int ignore_notices;
183185
zend_long auto_reset_persistent;
184186
int log_notices;
185187
zend_object *default_link; /* default link when connection is omitted */
188+
zend_string *regexes[PGSQL_MAX_REGEXES];
186189
HashTable field_oids;
187190
HashTable table_oids;
188191
HashTable connections;

0 commit comments

Comments
 (0)