From 740f0df9d31728066aaee7cc34eb3d5076f5f6d7 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 22 Feb 2024 00:03:59 +0000 Subject: [PATCH] ext/intl: introduce SpoofChecker::areBidiConfusable. Adding a new more refined spoofchecker method in addition of the existing SpoofChecker::areConfusable which takes in account the text direction left to right and right to left. Adding UBIDI_LTR, UBIDI_RTL, UBIDI_MIXED and UBIDI_NEUTRAL. --- ext/intl/spoofchecker/spoofchecker.stub.php | 16 +++++++ ext/intl/spoofchecker/spoofchecker_arginfo.h | 49 +++++++++++++++++++- ext/intl/spoofchecker/spoofchecker_main.c | 39 ++++++++++++++++ ext/intl/tests/spoofchecker_ubidi.phpt | 21 +++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/spoofchecker_ubidi.phpt diff --git a/ext/intl/spoofchecker/spoofchecker.stub.php b/ext/intl/spoofchecker/spoofchecker.stub.php index b0afd4a796ae2..584873d419fec 100644 --- a/ext/intl/spoofchecker/spoofchecker.stub.php +++ b/ext/intl/spoofchecker/spoofchecker.stub.php @@ -39,6 +39,16 @@ class Spoofchecker /** @cvalue USPOOF_HIDDEN_OVERLAY */ public const int HIDDEN_OVERLAY = UNKNOWN; #endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + /** @cvalue UBIDI_LTR */ + public const int UBIDI_LTR = UNKNOWN; + /** @cvalue UBIDI_RTL */ + public const int UBIDI_RTL = UNKNOWN; + /** @cvalue UBIDI_MIXED */ + public const int UBIDI_MIXED = UNKNOWN; + /** @cvalue UBIDI_NEUTRAL */ + public const int UBIDI_NEUTRAL = UNKNOWN; +#endif public function __construct() {} @@ -64,4 +74,10 @@ public function setChecks(int $checks): void {} /** @tentative-return-type */ public function setRestrictionLevel(int $level): void {} #endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + /** + * @param int $errorCode + */ + public function areBidiConfusable(int $direction, string $string1, string $string2, &$errorCode = null): bool {} +#endif } diff --git a/ext/intl/spoofchecker/spoofchecker_arginfo.h b/ext/intl/spoofchecker/spoofchecker_arginfo.h index f76c3ca6fd055..8f1a7a3ef7970 100644 --- a/ext/intl/spoofchecker/spoofchecker_arginfo.h +++ b/ext/intl/spoofchecker/spoofchecker_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d74f65f808ec0f71ee0ae8c04e253c4412da885e */ + * Stub hash: 86b6fe10bb533a039bd338fc18464c5de54ef556 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Spoofchecker___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -29,6 +29,15 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Spoofchecker_set ZEND_END_ARG_INFO() #endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Spoofchecker_areBidiConfusable, 0, 3, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, direction, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, string1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, string2, IS_STRING, 0) + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, errorCode, "null") +ZEND_END_ARG_INFO() +#endif + ZEND_METHOD(Spoofchecker, __construct); ZEND_METHOD(Spoofchecker, isSuspicious); ZEND_METHOD(Spoofchecker, areConfusable); @@ -37,6 +46,9 @@ ZEND_METHOD(Spoofchecker, setChecks); #if U_ICU_VERSION_MAJOR_NUM >= 58 ZEND_METHOD(Spoofchecker, setRestrictionLevel); #endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 +ZEND_METHOD(Spoofchecker, areBidiConfusable); +#endif static const zend_function_entry class_Spoofchecker_methods[] = { ZEND_ME(Spoofchecker, __construct, arginfo_class_Spoofchecker___construct, ZEND_ACC_PUBLIC) @@ -46,6 +58,9 @@ static const zend_function_entry class_Spoofchecker_methods[] = { ZEND_ME(Spoofchecker, setChecks, arginfo_class_Spoofchecker_setChecks, ZEND_ACC_PUBLIC) #if U_ICU_VERSION_MAJOR_NUM >= 58 ZEND_ME(Spoofchecker, setRestrictionLevel, arginfo_class_Spoofchecker_setRestrictionLevel, ZEND_ACC_PUBLIC) +#endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + ZEND_ME(Spoofchecker, areBidiConfusable, arginfo_class_Spoofchecker_areBidiConfusable, ZEND_ACC_PUBLIC) #endif ZEND_FE_END }; @@ -163,6 +178,38 @@ static zend_class_entry *register_class_Spoofchecker(void) zend_declare_typed_class_constant(class_entry, const_HIDDEN_OVERLAY_name, &const_HIDDEN_OVERLAY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_HIDDEN_OVERLAY_name); #endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + + zval const_UBIDI_LTR_value; + ZVAL_LONG(&const_UBIDI_LTR_value, UBIDI_LTR); + zend_string *const_UBIDI_LTR_name = zend_string_init_interned("UBIDI_LTR", sizeof("UBIDI_LTR") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_UBIDI_LTR_name, &const_UBIDI_LTR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_UBIDI_LTR_name); +#endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + + zval const_UBIDI_RTL_value; + ZVAL_LONG(&const_UBIDI_RTL_value, UBIDI_RTL); + zend_string *const_UBIDI_RTL_name = zend_string_init_interned("UBIDI_RTL", sizeof("UBIDI_RTL") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_UBIDI_RTL_name, &const_UBIDI_RTL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_UBIDI_RTL_name); +#endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + + zval const_UBIDI_MIXED_value; + ZVAL_LONG(&const_UBIDI_MIXED_value, UBIDI_MIXED); + zend_string *const_UBIDI_MIXED_name = zend_string_init_interned("UBIDI_MIXED", sizeof("UBIDI_MIXED") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_UBIDI_MIXED_name, &const_UBIDI_MIXED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_UBIDI_MIXED_name); +#endif +#if U_ICU_VERSION_MAJOR_NUM >= 74 + + zval const_UBIDI_NEUTRAL_value; + ZVAL_LONG(&const_UBIDI_NEUTRAL_value, UBIDI_NEUTRAL); + zend_string *const_UBIDI_NEUTRAL_name = zend_string_init_interned("UBIDI_NEUTRAL", sizeof("UBIDI_NEUTRAL") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_UBIDI_NEUTRAL_name, &const_UBIDI_NEUTRAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_UBIDI_NEUTRAL_name); +#endif return class_entry; } diff --git a/ext/intl/spoofchecker/spoofchecker_main.c b/ext/intl/spoofchecker/spoofchecker_main.c index 3831b9403ea48..063c3a17d4de3 100644 --- a/ext/intl/spoofchecker/spoofchecker_main.c +++ b/ext/intl/spoofchecker/spoofchecker_main.c @@ -167,3 +167,42 @@ PHP_METHOD(Spoofchecker, setRestrictionLevel) } /* }}} */ #endif + +#if U_ICU_VERSION_MAJOR_NUM >= 74 +PHP_METHOD(Spoofchecker, areBidiConfusable) +{ + int ret; + char *id1, *id2; + size_t length1, length2; + zend_long direction; + zval *error_code = NULL; + SPOOFCHECKER_METHOD_INIT_VARS; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "lss|z", &direction, &id1, &length1, + &id2, &length2, &error_code)) { + RETURN_THROWS(); + } + + SPOOFCHECKER_METHOD_FETCH_OBJECT; + if (direction != UBIDI_LTR && direction != UBIDI_RTL) { + zend_argument_value_error(1, "must be either SpoofChecker::UBIDI_LTR or SpoofChecker::UBIDI_RTL"); + RETURN_THROWS(); + } + if(length1 > INT32_MAX || length2 > INT32_MAX) { + SPOOFCHECKER_ERROR_CODE(co) = U_BUFFER_OVERFLOW_ERROR; + } else { + ret = uspoof_areBidiConfusableUTF8(co->uspoof, (UBiDiDirection)direction, id1, (int32_t)length1, id2, (int32_t)length2, SPOOFCHECKER_ERROR_CODE_P(co)); + } + if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { + php_error_docref(NULL, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co))); + RETURN_TRUE; + } + + if (error_code) { + zval_ptr_dtor(error_code); + ZVAL_LONG(Z_REFVAL_P(error_code), ret); + Z_TRY_ADDREF_P(error_code); + } + RETVAL_BOOL(ret != 0); +} +#endif diff --git a/ext/intl/tests/spoofchecker_ubidi.phpt b/ext/intl/tests/spoofchecker_ubidi.phpt new file mode 100644 index 0000000000000..3127dde0fbdd6 --- /dev/null +++ b/ext/intl/tests/spoofchecker_ubidi.phpt @@ -0,0 +1,21 @@ +--TEST-- +spoofchecker checks if strings are confusable in a given direction. +--EXTENSIONS-- +intl +--SKIPIF-- + += 74'); ?> +--FILE-- +areBidiConfusable(SpoofChecker::UBIDI_RTL + 1, "a", "a"); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +var_dump($s->areBidiConfusable(SpoofChecker::UBIDI_LTR, "\x73\x63", "sc")); +var_dump($s->areBidiConfusable(SpoofChecker::UBIDI_RTL, "sc", "\x73\x63")); +--EXPECT-- +Spoofchecker::areBidiConfusable(): Argument #1 ($direction) must be either SpoofChecker::UBIDI_LTR or SpoofChecker::UBIDI_RTL +bool(true) +bool(true)