@@ -180,6 +180,10 @@ static zend_always_inline zend_string *zend_add_interned_string(zend_string *str
180
180
GC_SET_REFCOUNT (str , 1 );
181
181
GC_ADD_FLAGS (str , IS_STR_INTERNED | flags );
182
182
183
+ if (!ZSTR_IS_VALID_UTF8 (str ) && zend_string_validate_utf8 (str )) {
184
+ GC_ADD_FLAGS (str , IS_STR_VALID_UTF8 );
185
+ }
186
+
183
187
ZVAL_INTERNED_STR (& val , str );
184
188
185
189
zend_hash_add_new (interned_strings , str , & val );
@@ -493,3 +497,45 @@ ZEND_API zend_string *zend_string_concat3(
493
497
494
498
return res ;
495
499
}
500
+
501
+ // Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
502
+ // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
503
+ // https://stackoverflow.com/a/22135005/1320374
504
+
505
+ enum {
506
+ UTF8_ACCEPT = 0 ,
507
+ UTF8_REJECT = 1 ,
508
+ };
509
+
510
+ static const uint8_t utf8d [] = {
511
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 00..1f
512
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 20..3f
513
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 40..5f
514
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 60..7f
515
+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 , // 80..9f
516
+ 7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 , // a0..bf
517
+ 8 ,8 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 , // c0..df
518
+ 0xa ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x3 ,0x4 ,0x3 ,0x3 , // e0..ef
519
+ 0xb ,0x6 ,0x6 ,0x6 ,0x5 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 ,0x8 , // f0..ff
520
+ 0x0 ,0x1 ,0x2 ,0x3 ,0x5 ,0x8 ,0x7 ,0x1 ,0x1 ,0x1 ,0x4 ,0x6 ,0x1 ,0x1 ,0x1 ,0x1 , // s0..s0
521
+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,1 ,1 ,1 ,1 , // s1..s2
522
+ 1 ,2 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 , // s3..s4
523
+ 1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,3 ,1 ,3 ,1 ,1 ,1 ,1 ,1 ,1 , // s5..s6
524
+ 1 ,3 ,1 ,1 ,1 ,1 ,1 ,3 ,1 ,3 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,3 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 , // s7..s8
525
+ };
526
+
527
+ ZEND_API bool zend_string_validate_utf8 (zend_string * string ) {
528
+ char * str = ZSTR_VAL (string );
529
+ size_t len = ZSTR_LEN (string );
530
+ uint32_t state = UTF8_ACCEPT ;
531
+
532
+ for (size_t i = 0 ; i < len ; i ++ ) {
533
+ uint32_t type = utf8d [(uint8_t )str [i ]];
534
+ state = utf8d [256 + state * 16 + type ];
535
+
536
+ if (state == UTF8_REJECT )
537
+ break ;
538
+ }
539
+
540
+ return state == UTF8_ACCEPT ;
541
+ }
0 commit comments