@@ -490,8 +490,55 @@ static PHP_GINIT_FUNCTION(pgsql)
490
490
#if defined(COMPILE_DL_PGSQL ) && defined(ZTS )
491
491
ZEND_TSRMLS_CACHE_UPDATE ();
492
492
#endif
493
+
494
+ size_t i = 0 ;
493
495
memset (pgsql_globals , 0 , sizeof (zend_pgsql_globals ));
494
496
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" );
495
542
}
496
543
497
544
static void php_libpq_version (char * buf , size_t len )
@@ -560,6 +607,9 @@ PHP_MSHUTDOWN_FUNCTION(pgsql)
560
607
UNREGISTER_INI_ENTRIES ();
561
608
zend_hash_destroy (& PGG (connections ));
562
609
610
+ for (size_t i = 0 ; i < PGSQL_MAX_REGEXES ; i ++ )
611
+ zend_string_release_ex (PGG (regexes [i ]), true);
612
+
563
613
return SUCCESS ;
564
614
}
565
615
@@ -4671,12 +4721,11 @@ static php_pgsql_data_type php_pgsql_get_data_type(const zend_string *type_name)
4671
4721
/* {{{ php_pgsql_convert_match
4672
4722
* test field value with regular expression specified.
4673
4723
*/
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 )
4675
4725
{
4726
+ pcre_cache_entry * centry ;
4676
4727
pcre2_code * re ;
4677
- PCRE2_SIZE err_offset ;
4678
- int res , errnumber ;
4679
- uint32_t options = PCRE2_NO_AUTO_CAPTURE ;
4728
+ int res ;
4680
4729
size_t i ;
4681
4730
pcre2_match_data * match_data ;
4682
4731
@@ -4689,27 +4738,21 @@ static int php_pgsql_convert_match(const zend_string *str, const char *regex , s
4689
4738
}
4690
4739
}
4691
4740
4692
- if (icase ) {
4693
- options |= PCRE2_CASELESS ;
4694
- }
4695
-
4696
- re = pcre2_compile ((PCRE2_SPTR )regex , regex_len , options , & errnumber , & err_offset , php_pcre_cctx ());
4697
- if (NULL == re ) {
4698
- PCRE2_UCHAR err_msg [128 ];
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 ) {
4701
4743
return FAILURE ;
4702
4744
}
4703
4745
4746
+ re = php_pcre_pce_re (centry );
4704
4747
match_data = php_pcre_create_match_data (0 , re );
4705
4748
if (NULL == match_data ) {
4706
- pcre2_code_free (re );
4707
4749
php_error_docref (NULL , E_WARNING , "Cannot allocate match data" );
4708
4750
return FAILURE ;
4709
4751
}
4752
+ php_pcre_pce_incref (centry );
4710
4753
res = pcre2_match (re , (PCRE2_SPTR )ZSTR_VAL (str ), ZSTR_LEN (str ), 0 , 0 , match_data , php_pcre_mctx ());
4711
4754
php_pcre_free_match_data (match_data );
4712
- pcre2_code_free ( re );
4755
+ php_pcre_pce_decref ( centry );
4713
4756
4714
4757
if (res == PCRE2_ERROR_NOMATCH ) {
4715
4758
return FAILURE ;
@@ -4890,14 +4933,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4890
4933
}
4891
4934
else {
4892
4935
/* FIXME: better regex must be used */
4893
- #define REGEX0 "^([+-]{0,1}[0-9]+)$"
4894
- 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 ) {
4895
4937
err = 1 ;
4896
4938
}
4897
4939
else {
4898
4940
ZVAL_STRINGL (& new_val , Z_STRVAL_P (val ), Z_STRLEN_P (val ));
4899
4941
}
4900
- #undef REGEX0
4901
4942
}
4902
4943
break ;
4903
4944
@@ -4933,11 +4974,9 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4933
4974
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
4934
4975
}
4935
4976
else {
4936
- #define REGEX0 "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$"
4937
- #define REGEX1 "^[+-]{0,1}(inf)(inity){0,1}$"
4938
4977
/* better regex? */
4939
- if (php_pgsql_convert_match (Z_STR_P (val ), REGEX0 , sizeof ( REGEX0 ) - 1 , 0 ) == FAILURE ) {
4940
- 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 ) {
4941
4980
err = 1 ;
4942
4981
} else {
4943
4982
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
@@ -4946,8 +4985,6 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4946
4985
else {
4947
4986
ZVAL_STRING (& new_val , Z_STRVAL_P (val ));
4948
4987
}
4949
- #undef REGEX0
4950
- #undef REGEX1
4951
4988
}
4952
4989
break ;
4953
4990
@@ -5043,7 +5080,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5043
5080
}
5044
5081
else {
5045
5082
/* better regex? */
5046
- 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 ) {
5047
5084
err = 1 ;
5048
5085
}
5049
5086
else {
@@ -5083,20 +5120,16 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5083
5120
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5084
5121
}
5085
5122
else {
5086
- #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})?$"
5087
- #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})?$"
5088
5123
/* The inet type holds an IPv4 or IPv6 host address, and optionally its subnet, all in one field. See more in the doc.
5089
5124
The regex might still be not perfect, but catches the most of IP variants. We might decide to remove the regex
5090
5125
at all though and let the server side to handle it.*/
5091
- if (php_pgsql_convert_match (Z_STR_P (val ), REGEX0 , sizeof ( REGEX0 ) - 1 , 0 ) == FAILURE
5092
- && 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 ) {
5093
5128
err = 2 ;
5094
5129
}
5095
5130
else {
5096
5131
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5097
5132
}
5098
- #undef REGEX0
5099
- #undef REGEX1
5100
5133
}
5101
5134
break ;
5102
5135
@@ -5127,14 +5160,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5127
5160
} else if (zend_string_equals_literal_ci (Z_STR_P (val ), "now()" )) {
5128
5161
ZVAL_STRINGL (& new_val , "NOW()" , sizeof ("NOW()" )- 1 );
5129
5162
} else {
5130
- #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}$"
5131
5163
/* better regex? */
5132
- 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 ) {
5133
5165
err = 1 ;
5134
5166
} else {
5135
5167
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5136
5168
}
5137
- #undef REGEX0
5138
5169
}
5139
5170
break ;
5140
5171
@@ -5158,15 +5189,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5158
5189
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5159
5190
}
5160
5191
else {
5161
- #define REGEX0 "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$"
5162
5192
/* FIXME: better regex must be used */
5163
- 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 ) {
5164
5194
err = 1 ;
5165
5195
}
5166
5196
else {
5167
5197
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5168
5198
}
5169
- #undef REGEX0
5170
5199
}
5171
5200
break ;
5172
5201
@@ -5190,15 +5219,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5190
5219
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5191
5220
}
5192
5221
else {
5193
- #define REGEX0 "^(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}){0,1}$"
5194
5222
/* FIXME: better regex must be used */
5195
- 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 ) {
5196
5224
err = 1 ;
5197
5225
}
5198
5226
else {
5199
5227
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5200
5228
}
5201
- #undef REGEX0
5202
5229
}
5203
5230
break ;
5204
5231
@@ -5239,44 +5266,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5239
5266
unit markings. For example, '1 12:59:10' is read the same as '1 day 12 hours 59 min 10
5240
5267
sec'.
5241
5268
*/
5242
- #define REGEX0 \
5243
- "^(@?[ \\t]+)?(" \
5244
- /* Textual time units and their abbreviations: */ \
5245
- "(([-+]?[ \\t]+)?" \
5246
- "[0-9]+(\\.[0-9]*)?[ \\t]*" \
5247
- "(millenniums|millennia|millennium|mil|mils|" \
5248
- "centuries|century|cent|c|" \
5249
- "decades|decade|dec|decs|" \
5250
- "years|year|y|" \
5251
- "months|month|mon|" \
5252
- "weeks|week|w|" \
5253
- "days|day|d|" \
5254
- "hours|hour|hr|hrs|h|" \
5255
- "minutes|minute|mins|min|m|" \
5256
- "seconds|second|secs|sec|s))+|" \
5257
- /* Textual time units plus (dd)* hh[:mm[:ss]] */ \
5258
- "((([-+]?[ \\t]+)?" \
5259
- "[0-9]+(\\.[0-9]*)?[ \\t]*" \
5260
- "(millenniums|millennia|millennium|mil|mils|" \
5261
- "centuries|century|cent|c|" \
5262
- "decades|decade|dec|decs|" \
5263
- "years|year|y|" \
5264
- "months|month|mon|" \
5265
- "weeks|week|w|" \
5266
- "days|day|d))+" \
5267
- "([-+]?[ \\t]+" \
5268
- "([0-9]+[ \\t]+)+" /* dd */ \
5269
- "(([0-9]{1,2}:){0,2}[0-9]{0,2})" /* hh:[mm:[ss]] */ \
5270
- ")?))" \
5271
- "([ \\t]+ago)?$"
5272
-
5273
- 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 ) {
5274
5271
err = 1 ;
5275
5272
}
5276
5273
else {
5277
5274
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5278
5275
}
5279
- #undef REGEX0
5280
5276
}
5281
5277
break ;
5282
5278
@@ -5341,14 +5337,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5341
5337
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5342
5338
}
5343
5339
else {
5344
- #define REGEX0 "^([0-9a-f]{2,2}:){5,5}[0-9a-f]{2,2}$"
5345
- 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 ) {
5346
5341
err = 1 ;
5347
5342
}
5348
5343
else {
5349
5344
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5350
5345
}
5351
- #undef REGEX0
5352
5346
}
5353
5347
break ;
5354
5348
0 commit comments