Skip to content

Commit 702a69e

Browse files
iluuu1994Girgias
authored andcommitted
Implement underflow handling for str_decrement
1 parent 483bfa6 commit 702a69e

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

ext/standard/string.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ PHP_FUNCTION(str_increment)
12091209
RETURN_THROWS();
12101210
}
12111211

1212-
zend_string *incremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistant */ false);
1212+
zend_string *incremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistent */ false);
12131213
size_t position = ZSTR_LEN(str)-1;
12141214
bool carry = false;
12151215

@@ -1241,7 +1241,7 @@ PHP_FUNCTION(str_increment)
12411241
ZSTR_VAL(tmp)[0] = ZSTR_VAL(incremented)[0];
12421242
break;
12431243
}
1244-
zend_string_release_ex(incremented, /* persistant */ false);
1244+
zend_string_release_ex(incremented, /* persistent */ false);
12451245
RETURN_STR(tmp);
12461246
}
12471247
RETURN_STR(incremented);
@@ -1264,8 +1264,12 @@ PHP_FUNCTION(str_decrement)
12641264
zend_argument_value_error(1, "must be composed only of alphanumeric ASCII characters");
12651265
RETURN_THROWS();
12661266
}
1267+
if (ZSTR_LEN(str) >= 1 && ZSTR_VAL(str)[0] == '0') {
1268+
zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str));
1269+
RETURN_THROWS();
1270+
}
12671271

1268-
zend_string *decremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistant */ false);
1272+
zend_string *decremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistent */ false);
12691273
size_t position = ZSTR_LEN(str)-1;
12701274
bool carry = false;
12711275

@@ -1285,10 +1289,17 @@ PHP_FUNCTION(str_decrement)
12851289
}
12861290
} while (carry && position-- > 0);
12871291

1288-
if (UNEXPECTED(carry)) {
1289-
zend_string_release_ex(decremented, /* persistant */ false);
1290-
zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str));
1291-
RETURN_THROWS();
1292+
if (UNEXPECTED(carry || ZSTR_VAL(decremented)[0] == '0')) {
1293+
if (ZSTR_LEN(decremented) == 1) {
1294+
zend_string_release_ex(decremented, /* persistent */ false);
1295+
zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str));
1296+
RETURN_THROWS();
1297+
}
1298+
zend_string *tmp = zend_string_alloc(ZSTR_LEN(decremented) - 1, 0);
1299+
memcpy(ZSTR_VAL(tmp), ZSTR_VAL(decremented) + 1, ZSTR_LEN(decremented) - 1);
1300+
ZSTR_VAL(tmp)[ZSTR_LEN(decremented) - 1] = '\0';
1301+
zend_string_release_ex(decremented, /* persistent */ false);
1302+
RETURN_STR(tmp);
12921303
}
12931304
RETURN_STR(decremented);
12941305
}

ext/standard/tests/strings/str_decrement_basic.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ $strictlyAlphaNumeric = [
1313
"zA",
1414
"Z0",
1515
"z0",
16+
// Underflow, removing leading character
17+
"Aa",
18+
"aA",
19+
"A0",
20+
"a0",
21+
"10",
22+
"1A",
23+
"1a",
24+
"10a",
1625
// string interpretable as a number in scientific notation
1726
"5e6",
1827
// Interned strings
@@ -44,6 +53,22 @@ string(2) "Y9"
4453
string(2) "Z0"
4554
string(2) "y9"
4655
string(2) "z0"
56+
string(1) "z"
57+
string(2) "Aa"
58+
string(1) "Z"
59+
string(2) "aA"
60+
string(1) "9"
61+
string(2) "A0"
62+
string(1) "9"
63+
string(2) "a0"
64+
string(1) "9"
65+
string(2) "10"
66+
string(1) "Z"
67+
string(2) "1A"
68+
string(1) "z"
69+
string(2) "1a"
70+
string(2) "9z"
71+
string(3) "10a"
4772
string(3) "5e5"
4873
string(3) "5e6"
4974
string(1) "c"

ext/standard/tests/strings/str_decrement_underflow.phpt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ str_decrement(): Out of Range ValueErrors for strings that cannot be decremented
44
<?php
55

66
$strings = [
7+
"",
78
"0",
89
"a",
910
"A",
1011
"00",
11-
"Aa",
12-
"aA",
13-
"A0",
14-
"a0",
1512
"0a",
1613
"0A",
1714
];
@@ -26,13 +23,10 @@ foreach ($strings as $s) {
2623

2724
?>
2825
--EXPECT--
26+
str_decrement(): Argument #1 ($string) cannot be empty
2927
str_decrement(): Argument #1 ($string) "0" is out of decrement range
3028
str_decrement(): Argument #1 ($string) "a" is out of decrement range
3129
str_decrement(): Argument #1 ($string) "A" is out of decrement range
3230
str_decrement(): Argument #1 ($string) "00" is out of decrement range
33-
str_decrement(): Argument #1 ($string) "Aa" is out of decrement range
34-
str_decrement(): Argument #1 ($string) "aA" is out of decrement range
35-
str_decrement(): Argument #1 ($string) "A0" is out of decrement range
36-
str_decrement(): Argument #1 ($string) "a0" is out of decrement range
3731
str_decrement(): Argument #1 ($string) "0a" is out of decrement range
3832
str_decrement(): Argument #1 ($string) "0A" is out of decrement range

0 commit comments

Comments
 (0)