@@ -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,15 +4721,13 @@ 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
- PCRE2_UCHAR err_msg [128 ];
4683
4731
4684
4732
/* Check invalid chars for POSIX regex */
4685
4733
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
4690
4738
}
4691
4739
}
4692
4740
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 ) {
4701
4743
return FAILURE ;
4702
4744
}
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
4715
4745
4746
+ re = php_pcre_pce_re (centry );
4716
4747
match_data = php_pcre_create_match_data (0 , re );
4717
4748
if (NULL == match_data ) {
4718
- pcre2_code_free (re );
4719
4749
php_error_docref (NULL , E_WARNING , "Cannot allocate match data" );
4720
4750
return FAILURE ;
4721
4751
}
4752
+ php_pcre_pce_incref (centry );
4722
4753
res = pcre2_match (re , (PCRE2_SPTR )ZSTR_VAL (str ), ZSTR_LEN (str ), 0 , 0 , match_data , php_pcre_mctx ());
4723
4754
php_pcre_free_match_data (match_data );
4724
- pcre2_code_free ( re );
4755
+ php_pcre_pce_decref ( centry );
4725
4756
4726
4757
if (res == PCRE2_ERROR_NOMATCH ) {
4727
4758
return FAILURE ;
@@ -4902,14 +4933,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4902
4933
}
4903
4934
else {
4904
4935
/* 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 ) {
4907
4937
err = 1 ;
4908
4938
}
4909
4939
else {
4910
4940
ZVAL_STRINGL (& new_val , Z_STRVAL_P (val ), Z_STRLEN_P (val ));
4911
4941
}
4912
- #undef REGEX0
4913
4942
}
4914
4943
break ;
4915
4944
@@ -4945,11 +4974,9 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4945
4974
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
4946
4975
}
4947
4976
else {
4948
- #define REGEX0 "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$"
4949
- #define REGEX1 "^[+-]{0,1}(inf)(inity){0,1}$"
4950
4977
/* 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 ) {
4953
4980
err = 1 ;
4954
4981
} else {
4955
4982
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 *
4958
4985
else {
4959
4986
ZVAL_STRING (& new_val , Z_STRVAL_P (val ));
4960
4987
}
4961
- #undef REGEX0
4962
- #undef REGEX1
4963
4988
}
4964
4989
break ;
4965
4990
@@ -5055,7 +5080,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5055
5080
}
5056
5081
else {
5057
5082
/* 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 ) {
5059
5084
err = 1 ;
5060
5085
}
5061
5086
else {
@@ -5095,20 +5120,16 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5095
5120
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5096
5121
}
5097
5122
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})?$"
5100
5123
/* The inet type holds an IPv4 or IPv6 host address, and optionally its subnet, all in one field. See more in the doc.
5101
5124
The regex might still be not perfect, but catches the most of IP variants. We might decide to remove the regex
5102
5125
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 ) {
5105
5128
err = 2 ;
5106
5129
}
5107
5130
else {
5108
5131
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5109
5132
}
5110
- #undef REGEX0
5111
- #undef REGEX1
5112
5133
}
5113
5134
break ;
5114
5135
@@ -5139,14 +5160,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5139
5160
} else if (zend_string_equals_literal_ci (Z_STR_P (val ), "now()" )) {
5140
5161
ZVAL_STRINGL (& new_val , "NOW()" , sizeof ("NOW()" )- 1 );
5141
5162
} 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}$"
5143
5163
/* 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 ) {
5145
5165
err = 1 ;
5146
5166
} else {
5147
5167
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5148
5168
}
5149
- #undef REGEX0
5150
5169
}
5151
5170
break ;
5152
5171
@@ -5170,15 +5189,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5170
5189
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5171
5190
}
5172
5191
else {
5173
- #define REGEX0 "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$"
5174
5192
/* 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 ) {
5176
5194
err = 1 ;
5177
5195
}
5178
5196
else {
5179
5197
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5180
5198
}
5181
- #undef REGEX0
5182
5199
}
5183
5200
break ;
5184
5201
@@ -5202,15 +5219,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5202
5219
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5203
5220
}
5204
5221
else {
5205
- #define REGEX0 "^(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}){0,1}$"
5206
5222
/* 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 ) {
5208
5224
err = 1 ;
5209
5225
}
5210
5226
else {
5211
5227
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5212
5228
}
5213
- #undef REGEX0
5214
5229
}
5215
5230
break ;
5216
5231
@@ -5251,44 +5266,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5251
5266
unit markings. For example, '1 12:59:10' is read the same as '1 day 12 hours 59 min 10
5252
5267
sec'.
5253
5268
*/
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 ) {
5286
5271
err = 1 ;
5287
5272
}
5288
5273
else {
5289
5274
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5290
5275
}
5291
- #undef REGEX0
5292
5276
}
5293
5277
break ;
5294
5278
@@ -5353,14 +5337,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5353
5337
ZVAL_STR (& new_val , ZSTR_KNOWN (ZEND_STR_NULL ));
5354
5338
}
5355
5339
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 ) {
5358
5341
err = 1 ;
5359
5342
}
5360
5343
else {
5361
5344
ZVAL_STR (& new_val , php_pgsql_add_quotes (Z_STR_P (val )));
5362
5345
}
5363
- #undef REGEX0
5364
5346
}
5365
5347
break ;
5366
5348
0 commit comments