diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2020-12-13 19:00:51 +0100 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2020-12-13 23:55:33 +0100 |
commit | 2b7eb0e26a1816a3c5ddb28dd53f98ae0ecef047 (patch) | |
tree | d2c2a44268678ce0beb01dad86e66803db613fdc | |
parent | 269a8841ae6edae3bc0ed8675390c78bd9f09bd8 (diff) | |
download | php-git-2b7eb0e26a1816a3c5ddb28dd53f98ae0ecef047.tar.gz |
Disallow version_compare() $operator abbreviations
`version_compare()` does a sloppy check for the `$operators` argument
which allows arbitrary abbreviations of the supported operators to be
accepted. This is both undocumented and unexpected, and could lead to
subtle BC breaks, if the order of the comparisions will be changed.
Therefore we change to strict comparisons.
Closes GH-6510.
-rw-r--r-- | UPGRADING | 3 | ||||
-rw-r--r-- | ext/standard/tests/versioning/version_compare_op_abbrev.phpt | 21 | ||||
-rw-r--r-- | ext/standard/versioning.c | 19 |
3 files changed, 34 insertions, 9 deletions
@@ -19,6 +19,9 @@ PHP 8.1 UPGRADE NOTES 1. Backward Incompatible Changes ======================================== +- Standard: + . version_compare() no longer accepts undocumented operator abbreviations. + ======================================== 2. New Features ======================================== diff --git a/ext/standard/tests/versioning/version_compare_op_abbrev.phpt b/ext/standard/tests/versioning/version_compare_op_abbrev.phpt new file mode 100644 index 0000000000..241c1559fe --- /dev/null +++ b/ext/standard/tests/versioning/version_compare_op_abbrev.phpt @@ -0,0 +1,21 @@ +--TEST-- +version_compare() no longer supports operator abbreviations +--FILE-- +<?php +$abbrevs = ['', 'l', 'g', 'e', '!', 'n']; +foreach ($abbrevs as $op) { + try { + version_compare('1', '2', $op); + echo "'$op' succeeded\n"; + } catch (ValueError $err) { + echo "'$op' failed\n"; + } +} +?> +--EXPECT-- +'' failed +'l' failed +'g' failed +'e' failed +'!' failed +'n' failed diff --git a/ext/standard/versioning.c b/ext/standard/versioning.c index dbdae6ecf7..f4f20c9850 100644 --- a/ext/standard/versioning.c +++ b/ext/standard/versioning.c @@ -203,37 +203,38 @@ php_version_compare(const char *orig_ver1, const char *orig_ver2) PHP_FUNCTION(version_compare) { - char *v1, *v2, *op = NULL; - size_t v1_len, v2_len, op_len = 0; + char *v1, *v2; + zend_string *op = NULL; + size_t v1_len, v2_len; int compare; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STRING(v1, v1_len) Z_PARAM_STRING(v2, v2_len) Z_PARAM_OPTIONAL - Z_PARAM_STRING_OR_NULL(op, op_len) + Z_PARAM_STR_OR_NULL(op) ZEND_PARSE_PARAMETERS_END(); compare = php_version_compare(v1, v2); if (!op) { RETURN_LONG(compare); } - if (!strncmp(op, "<", op_len) || !strncmp(op, "lt", op_len)) { + if (zend_string_equals_literal(op, "<") || zend_string_equals_literal(op, "lt")) { RETURN_BOOL(compare == -1); } - if (!strncmp(op, "<=", op_len) || !strncmp(op, "le", op_len)) { + if (zend_string_equals_literal(op, "<=") || zend_string_equals_literal(op, "le")) { RETURN_BOOL(compare != 1); } - if (!strncmp(op, ">", op_len) || !strncmp(op, "gt", op_len)) { + if (zend_string_equals_literal(op, ">") || zend_string_equals_literal(op, "gt")) { RETURN_BOOL(compare == 1); } - if (!strncmp(op, ">=", op_len) || !strncmp(op, "ge", op_len)) { + if (zend_string_equals_literal(op, ">=") || zend_string_equals_literal(op, "ge")) { RETURN_BOOL(compare != -1); } - if (!strncmp(op, "==", op_len) || !strncmp(op, "=", op_len) || !strncmp(op, "eq", op_len)) { + if (zend_string_equals_literal(op, "==") || zend_string_equals_literal(op, "=") || zend_string_equals_literal(op, "eq")) { RETURN_BOOL(compare == 0); } - if (!strncmp(op, "!=", op_len) || !strncmp(op, "<>", op_len) || !strncmp(op, "ne", op_len)) { + if (zend_string_equals_literal(op, "!=") || zend_string_equals_literal(op, "<>") || zend_string_equals_literal(op, "ne")) { RETURN_BOOL(compare != 0); } |