Promote pack/unpack format errors

Errors related to invalid format strings (unlike data mismatch
errors) should throw ValueError.

Closes GH-6185.
This commit is contained in:
Nikita Popov 2020-09-22 14:08:13 +02:00
parent 048cc9ba78
commit de77344de2
8 changed files with 81 additions and 79 deletions

View File

@ -324,7 +324,7 @@ static const func_info_t func_infos[] = {
F1("realpath", MAY_BE_FALSE | MAY_BE_STRING),
F1("fsockopen", MAY_BE_FALSE | MAY_BE_RESOURCE),
FN("pfsockopen", MAY_BE_FALSE | MAY_BE_RESOURCE),
F1("pack", MAY_BE_FALSE | MAY_BE_STRING),
F1("pack", MAY_BE_STRING),
F1("unpack", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY),
F1("get_browser", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_ANY),
F1("crypt", MAY_BE_STRING),

View File

@ -1134,7 +1134,7 @@ function getrusage(int $who = 0): array|false {}
/* pack.c */
function pack(string $format, mixed ...$args): string|false {}
function pack(string $format, mixed ...$args): string {}
function unpack(string $format, string $data, int $offset = 0): array|false {}

View File

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 3c02183529eed2eb21d801ed2ba615deaf749b1d */
* Stub hash: f029ab7f1d9fa2a99a5612a928d0b731de6aaeed */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
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
ZEND_END_ARG_INFO()
#endif
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pack, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
ZEND_END_ARG_INFO()
#define arginfo_pack arginfo_sprintf
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_unpack, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)

View File

@ -47,8 +47,8 @@
if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \
efree(formatcodes); \
efree(formatargs); \
php_error_docref(NULL, E_WARNING, "Type %c: integer overflow in format string", code); \
RETURN_FALSE; \
zend_value_error("Type %c: integer overflow in format string", code); \
RETURN_THROWS(); \
} \
outputpos += (a)*(b);
@ -282,8 +282,8 @@ PHP_FUNCTION(pack)
if (currentarg >= num_args) {
efree(formatcodes);
efree(formatargs);
php_error_docref(NULL, E_WARNING, "Type %c: not enough arguments", code);
RETURN_FALSE;
zend_value_error("Type %c: not enough arguments", code);
RETURN_THROWS();
}
if (arg < 0) {
@ -313,8 +313,8 @@ PHP_FUNCTION(pack)
#if SIZEOF_ZEND_LONG < 8
efree(formatcodes);
efree(formatargs);
php_error_docref(NULL, E_WARNING, "64-bit format codes are not available for 32-bit versions of PHP");
RETURN_FALSE;
zend_value_error("64-bit format codes are not available for 32-bit versions of PHP");
RETURN_THROWS();
#endif
case 'c':
case 'C':
@ -346,16 +346,16 @@ PHP_FUNCTION(pack)
too_few_args:
efree(formatcodes);
efree(formatargs);
php_error_docref(NULL, E_WARNING, "Type %c: too few arguments", code);
RETURN_FALSE;
zend_value_error("Type %c: too few arguments", code);
RETURN_THROWS();
}
break;
default:
efree(formatcodes);
efree(formatargs);
php_error_docref(NULL, E_WARNING, "Type %c: unknown format code", code);
RETURN_FALSE;
zend_value_error("Type %c: unknown format code", code);
RETURN_THROWS();
}
formatcodes[formatcount] = code;
@ -845,9 +845,9 @@ PHP_FUNCTION(unpack)
size = 8;
break;
#else
php_error_docref(NULL, E_WARNING, "64-bit format codes are not available for 32-bit versions of PHP");
zend_value_error("64-bit format codes are not available for 32-bit versions of PHP");
zend_array_destroy(Z_ARR_P(return_value));
RETURN_FALSE;
RETURN_THROWS();
#endif
/* Use sizeof(float) bytes of input */
@ -865,10 +865,9 @@ PHP_FUNCTION(unpack)
break;
default:
php_error_docref(NULL, E_WARNING, "Invalid format type %c", type);
zend_value_error("Invalid format type %c", type);
zend_array_destroy(Z_ARR_P(return_value));
RETURN_FALSE;
break;
RETURN_THROWS();
}
if (size != 0 && size != -1 && size < 0) {

View File

@ -2,8 +2,11 @@
Bug #78833 (Integer overflow in pack causes out-of-bound access)
--FILE--
<?php
var_dump(pack("E2E2147483647H*", 0x0, 0x0, 0x0));
try {
var_dump(pack("E2E2147483647H*", 0x0, 0x0, 0x0));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECTF--
Warning: pack(): Type E: too few arguments in %s on line %d
bool(false)
--EXPECT--
Type E: too few arguments

View File

@ -8,37 +8,55 @@ if (PHP_INT_SIZE > 4) {
?>
--FILE--
<?php
var_dump(pack("Q", 0));
var_dump(pack("J", 0));
var_dump(pack("P", 0));
var_dump(pack("q", 0));
try {
var_dump(pack("Q", 0));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(pack("J", 0));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(pack("P", 0));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(pack("q", 0));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(unpack("Q", ''));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(unpack("J", ''));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(unpack("P", ''));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(unpack("q", ''));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
var_dump(unpack("Q", ''));
var_dump(unpack("J", ''));
var_dump(unpack("P", ''));
var_dump(unpack("q", ''));
?>
--EXPECTF--
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: pack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
Warning: unpack(): 64-bit format codes are not available for 32-bit versions of PHP in %s on line %d
bool(false)
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP
64-bit format codes are not available for 32-bit versions of PHP

View File

@ -1,11 +0,0 @@
--TEST--
Invalid format type validation
--FILE--
<?php
var_dump(unpack("-2222", 1));
echo "Done\n";
?>
--EXPECTF--
Warning: unpack(): Invalid format type - in %sunpack.php on line %d
bool(false)
Done

View File

@ -3,16 +3,12 @@ Test unpack() function : error conditions
--FILE--
<?php
echo "*** Testing unpack() : error conditions ***\n";
try {
var_dump(unpack("B", pack("I", 65534)));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
echo "\n-- Testing unpack() function with invalid format character --\n";
$extra_arg = 10;
var_dump(unpack("B", pack("I", 65534)));
?>
--EXPECTF--
*** Testing unpack() : error conditions ***
-- Testing unpack() function with invalid format character --
Warning: unpack(): Invalid format type B in %s on line %d
bool(false)
--EXPECT--
Invalid format type B