Skip to content

Commit de77344

Browse files
committed
Promote pack/unpack format errors
Errors related to invalid format strings (unlike data mismatch errors) should throw ValueError. Closes GH-6185.
1 parent 048cc9b commit de77344

File tree

8 files changed

+81
-79
lines changed

8 files changed

+81
-79
lines changed

ext/opcache/Optimizer/zend_func_info.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static const func_info_t func_infos[] = {
324324
F1("realpath", MAY_BE_FALSE | MAY_BE_STRING),
325325
F1("fsockopen", MAY_BE_FALSE | MAY_BE_RESOURCE),
326326
FN("pfsockopen", MAY_BE_FALSE | MAY_BE_RESOURCE),
327-
F1("pack", MAY_BE_FALSE | MAY_BE_STRING),
327+
F1("pack", MAY_BE_STRING),
328328
F1("unpack", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY),
329329
F1("get_browser", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_ANY),
330330
F1("crypt", MAY_BE_STRING),

ext/standard/basic_functions.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ function getrusage(int $who = 0): array|false {}
11341134

11351135
/* pack.c */
11361136

1137-
function pack(string $format, mixed ...$args): string|false {}
1137+
function pack(string $format, mixed ...$args): string {}
11381138

11391139
function unpack(string $format, string $data, int $offset = 0): array|false {}
11401140

ext/standard/basic_functions_arginfo.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 3c02183529eed2eb21d801ed2ba615deaf749b1d */
2+
* Stub hash: f029ab7f1d9fa2a99a5612a928d0b731de6aaeed */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
@@ -1747,10 +1747,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_getrusage, 0, 0, MAY_BE_ARRAY|MA
17471747
ZEND_END_ARG_INFO()
17481748
#endif
17491749

1750-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pack, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
1751-
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
1752-
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
1753-
ZEND_END_ARG_INFO()
1750+
#define arginfo_pack arginfo_sprintf
17541751

17551752
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_unpack, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE)
17561753
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)

ext/standard/pack.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \
4848
efree(formatcodes); \
4949
efree(formatargs); \
50-
php_error_docref(NULL, E_WARNING, "Type %c: integer overflow in format string", code); \
51-
RETURN_FALSE; \
50+
zend_value_error("Type %c: integer overflow in format string", code); \
51+
RETURN_THROWS(); \
5252
} \
5353
outputpos += (a)*(b);
5454

@@ -282,8 +282,8 @@ PHP_FUNCTION(pack)
282282
if (currentarg >= num_args) {
283283
efree(formatcodes);
284284
efree(formatargs);
285-
php_error_docref(NULL, E_WARNING, "Type %c: not enough arguments", code);
286-
RETURN_FALSE;
285+
zend_value_error("Type %c: not enough arguments", code);
286+
RETURN_THROWS();
287287
}
288288

289289
if (arg < 0) {
@@ -313,8 +313,8 @@ PHP_FUNCTION(pack)
313313
#if SIZEOF_ZEND_LONG < 8
314314
efree(formatcodes);
315315
efree(formatargs);
316-
php_error_docref(NULL, E_WARNING, "64-bit format codes are not available for 32-bit versions of PHP");
317-
RETURN_FALSE;
316+
zend_value_error("64-bit format codes are not available for 32-bit versions of PHP");
317+
RETURN_THROWS();
318318
#endif
319319
case 'c':
320320
case 'C':
@@ -346,16 +346,16 @@ PHP_FUNCTION(pack)
346346
too_few_args:
347347
efree(formatcodes);
348348
efree(formatargs);
349-
php_error_docref(NULL, E_WARNING, "Type %c: too few arguments", code);
350-
RETURN_FALSE;
349+
zend_value_error("Type %c: too few arguments", code);
350+
RETURN_THROWS();
351351
}
352352
break;
353353

354354
default:
355355
efree(formatcodes);
356356
efree(formatargs);
357-
php_error_docref(NULL, E_WARNING, "Type %c: unknown format code", code);
358-
RETURN_FALSE;
357+
zend_value_error("Type %c: unknown format code", code);
358+
RETURN_THROWS();
359359
}
360360

361361
formatcodes[formatcount] = code;
@@ -845,9 +845,9 @@ PHP_FUNCTION(unpack)
845845
size = 8;
846846
break;
847847
#else
848-
php_error_docref(NULL, E_WARNING, "64-bit format codes are not available for 32-bit versions of PHP");
848+
zend_value_error("64-bit format codes are not available for 32-bit versions of PHP");
849849
zend_array_destroy(Z_ARR_P(return_value));
850-
RETURN_FALSE;
850+
RETURN_THROWS();
851851
#endif
852852

853853
/* Use sizeof(float) bytes of input */
@@ -865,10 +865,9 @@ PHP_FUNCTION(unpack)
865865
break;
866866

867867
default:
868-
php_error_docref(NULL, E_WARNING, "Invalid format type %c", type);
868+
zend_value_error("Invalid format type %c", type);
869869
zend_array_destroy(Z_ARR_P(return_value));
870-
RETURN_FALSE;
871-
break;
870+
RETURN_THROWS();
872871
}
873872

874873
if (size != 0 && size != -1 && size < 0) {

ext/standard/tests/strings/bug78833.phpt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
Bug #78833 (Integer overflow in pack causes out-of-bound access)
33
--FILE--
44
<?php
5-
var_dump(pack("E2E2147483647H*", 0x0, 0x0, 0x0));
5+
try {
6+
var_dump(pack("E2E2147483647H*", 0x0, 0x0, 0x0));
7+
} catch (ValueError $e) {
8+
echo $e->getMessage(), "\n";
9+
}
610
?>
7-
--EXPECTF--
8-
Warning: pack(): Type E: too few arguments in %s on line %d
9-
bool(false)
11+
--EXPECT--
12+
Type E: too few arguments

ext/standard/tests/strings/pack64_32.phpt

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,55 @@ if (PHP_INT_SIZE > 4) {
88
?>
99
--FILE--
1010
<?php
11-
var_dump(pack("Q", 0));
12-
var_dump(pack("J", 0));
13-
var_dump(pack("P", 0));
14-
var_dump(pack("q", 0));
11+
try {
12+
var_dump(pack("Q", 0));
13+
} catch (ValueError $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
try {
17+
var_dump(pack("J", 0));
18+
} catch (ValueError $e) {
19+
echo $e->getMessage(), "\n";
20+
}
21+
try {
22+
var_dump(pack("P", 0));
23+
} catch (ValueError $e) {
24+
echo $e->getMessage(), "\n";
25+
}
26+
try {
27+
var_dump(pack("q", 0));
28+
} catch (ValueError $e) {
29+
echo $e->getMessage(), "\n";
30+
}
31+
32+
try {
33+
var_dump(unpack("Q", ''));
34+
} catch (ValueError $e) {
35+
echo $e->getMessage(), "\n";
36+
}
37+
try {
38+
var_dump(unpack("J", ''));
39+
} catch (ValueError $e) {
40+
echo $e->getMessage(), "\n";
41+
}
42+
try {
43+
var_dump(unpack("P", ''));
44+
} catch (ValueError $e) {
45+
echo $e->getMessage(), "\n";
46+
}
47+
try {
48+
var_dump(unpack("q", ''));
49+
} catch (ValueError $e) {
50+
echo $e->getMessage(), "\n";
51+
}
1552

16-
var_dump(unpack("Q", ''));
17-
var_dump(unpack("J", ''));
18-
var_dump(unpack("P", ''));
19-
var_dump(unpack("q", ''));
2053
?>
2154
--EXPECTF--
22-
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
23-
bool(false)
24-
25-
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
26-
bool(false)
27-
28-
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
29-
bool(false)
30-
31-
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
32-
bool(false)
33-
34-
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
35-
bool(false)
36-
37-
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
38-
bool(false)
39-
40-
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
41-
bool(false)
42-
43-
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
44-
bool(false)
55+
64-bit format codes are not available for 32-bit versions of PHP
56+
64-bit format codes are not available for 32-bit versions of PHP
57+
64-bit format codes are not available for 32-bit versions of PHP
58+
64-bit format codes are not available for 32-bit versions of PHP
59+
64-bit format codes are not available for 32-bit versions of PHP
60+
64-bit format codes are not available for 32-bit versions of PHP
61+
64-bit format codes are not available for 32-bit versions of PHP
62+
64-bit format codes are not available for 32-bit versions of PHP

ext/standard/tests/strings/unpack.phpt

Lines changed: 0 additions & 11 deletions
This file was deleted.

ext/standard/tests/strings/unpack_error.phpt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@ Test unpack() function : error conditions
33
--FILE--
44
<?php
55

6-
echo "*** Testing unpack() : error conditions ***\n";
6+
try {
7+
var_dump(unpack("B", pack("I", 65534)));
8+
} catch (ValueError $e) {
9+
echo $e->getMessage(), "\n";
10+
}
711

8-
echo "\n-- Testing unpack() function with invalid format character --\n";
9-
$extra_arg = 10;
10-
var_dump(unpack("B", pack("I", 65534)));
1112
?>
12-
--EXPECTF--
13-
*** Testing unpack() : error conditions ***
14-
15-
-- Testing unpack() function with invalid format character --
16-
17-
Warning: unpack(): Invalid format type B in %s on line %d
18-
bool(false)
13+
--EXPECT--
14+
Invalid format type B

0 commit comments

Comments
 (0)