Commit 2e51f41e authored by Ondrej Sury's avatar Ondrej Sury

Imported Upstream version 5.6.23+dfsg

parent 03d17de8
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
23 Jun 2016, PHP 5.6.23
- Core:
. Fixed bug #72275 (Integer Overflow in json_encode()/json_decode()/
json_utf8_to_utf16()). (Stas)
. Fixed bug #72400 (Integer Overflow in addcslashes/addslashes). (Stas)
. Fixed bug #72403 (Integer Overflow in Length of String-typed ZVAL). (Stas)
- GD:
. Fixed bug #72298 (pass2_no_dither out-of-bounds access). (Stas)
. Fixed bug #72337 (invalid dimensions can lead to crash) (Pierre)
. Fixed bug #72339 (Integer Overflow in _gd2GetHeader() resulting in
heap overflow). (Pierre)
. Fixed bug #72407 (NULL Pointer Dereference at _gdScaleVert). (Stas)
. Fixed bug #72446 (Integer Overflow in gdImagePaletteToTrueColor() resulting
in heap overflow). (Pierre)
- Intl:
. Fixed bug #70484 (selectordinal doesn't work with named parameters).
(Anatol)
- mbstring:
. Fixed bug #72402 (_php_mb_regex_ereg_replace_exec - double free). (Stas)
- mcrypt:
. Fixed bug #72455 (Heap Overflow due to integer overflows). (Stas)
- Phar:
. Fixed bug #72321 (invalid free in phar_extract_file()).
(hji at dyntopia dot com)
- SPL:
. Fixed bug #72262 (int/size_t confusion in SplFileObject::fread). (Stas)
. Fixed bug #72433 (Use After Free Vulnerability in PHP's GC algorithm and
unserialize). (Dmitry)
- OpenSSL:
. Fixed bug #72140 (segfault after calling ERR_free_strings()).
(Jakub Zelenka)
- WDDX:
. Fixed bug #72340 (Double Free Courruption in wddx_deserialize). (Stas)
- zip:
. Fixed bug #72434 (ZipArchive class Use After Free Vulnerability in PHP's GC
algorithm and unserialize). (Dmitry)
26 May 2016, PHP 5.6.22
- Core:
......@@ -35,6 +82,8 @@ PHP NEWS
(Michael Sierks)
- Date:
. Fixed bug #63740 (strtotime seems to use both sunday and monday as start of
week). (Derick)
. Fixed bug #71889 (DateInterval::format Segmentation fault). (Thomas Punt)
- EXIF:
......@@ -468,7 +517,8 @@ PHP NEWS
- GD:
. Fixed bug #53156 (imagerectangle problem with point ordering). (cmb)
. Fixed bug #66387 (Stack overflow with imagefilltoborder). (cmb)
. Fixed bug #66387 (Stack overflow with imagefilltoborder). (CVE-2015-8874)
(cmb)
. Fixed bug #70102 (imagecreatefromwebm() shifts colors). (cmb)
. Fixed bug #66590 (imagewebp() doesn't pad to even length). (cmb)
. Fixed bug #66882 (imagerotate by -90 degrees truncates image by 1px). (cmb)
......
......@@ -13,5 +13,5 @@ var_dump(gc_collect_cycles());
echo "ok\n";
?>
--EXPECT--
int(1)
int(2)
ok
......@@ -3672,7 +3672,7 @@ ac_config_headers="$ac_config_headers main/php_config.h"
PHP_MAJOR_VERSION=5
PHP_MINOR_VERSION=6
PHP_RELEASE_VERSION=22
PHP_RELEASE_VERSION=23
PHP_EXTRA_VERSION=""
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr $PHP_MAJOR_VERSION \* 10000 + $PHP_MINOR_VERSION \* 100 + $PHP_RELEASE_VERSION`
......@@ -119,7 +119,7 @@ int zend_sprintf(char *buffer, const char *format, ...);
PHP_MAJOR_VERSION=5
PHP_MINOR_VERSION=6
PHP_RELEASE_VERSION=22
PHP_RELEASE_VERSION=23
PHP_EXTRA_VERSION=""
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
......
......@@ -310,33 +310,33 @@ void timelib_dump_rel_time(timelib_rel_time *d)
timelib_long timelib_parse_tz_cor(char **ptr)
{
char *begin = *ptr, *end;
timelib_long tmp;
while (isdigit(**ptr) || **ptr == ':') {
++*ptr;
}
end = *ptr;
switch (end - begin) {
case 1:
case 2:
return HOUR(strtol(begin, NULL, 10));
break;
case 3:
case 4:
if (begin[1] == ':') {
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
return tmp;
} else if (begin[2] == ':') {
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
return tmp;
} else {
tmp = strtol(begin, NULL, 10);
return HOUR(tmp / 100) + tmp % 100;
}
case 5:
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
return tmp;
}
return 0;
char *begin = *ptr, *end;
timelib_long tmp;
while (isdigit(**ptr) || **ptr == ':') {
++*ptr;
}
end = *ptr;
switch (end - begin) {
case 1: /* H */
case 2: /* HH */
return HOUR(strtol(begin, NULL, 10));
break;
case 3: /* H:M */
case 4: /* H:MM, HH:M, HHMM */
if (begin[1] == ':') {
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
return tmp;
} else if (begin[2] == ':') {
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
return tmp;
} else {
tmp = strtol(begin, NULL, 10);
return HOUR(tmp / 100) + tmp % 100;
}
case 5: /* HH:MM */
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
return tmp;
}
return 0;
}
......@@ -38,8 +38,8 @@
# define timelib_free free
#endif
#define TIMELIB_VERSION 201502
#define TIMELIB_ASCII_VERSION "2015.02"
#define TIMELIB_VERSION 201602
#define TIMELIB_ASCII_VERSION "2016.02"
#define TIMELIB_NONE 0x00
#define TIMELIB_OVERRIDE_TIME 0x01
......
......@@ -152,9 +152,17 @@ static void do_adjust_for_weekday(timelib_time* time)
current_dow = timelib_day_of_week(time->y, time->m, time->d);
if (time->relative.weekday_behavior == 2)
{
if (time->relative.weekday == 0) {
/* To make "this week" work, where the current DOW is a "sunday" */
if (current_dow == 0 && time->relative.weekday != 0) {
time->relative.weekday = -6;
}
/* To make "sunday this week" work, where the current DOW is not a
* "sunday" */
if (time->relative.weekday == 0 && current_dow != 0) {
time->relative.weekday = 7;
}
time->d -= current_dow;
time->d += time->relative.weekday;
return;
......
--TEST--
Bug #63740 (strtotime seems to use both sunday and monday as start of week)
--FILE--
<?php
$dates = [
'2015-07-04',
'2015-07-05',
'2015-07-06',
'2015-07-07',
'2015-07-08',
'2015-07-09',
'2015-07-10',
'2015-07-11',
'2015-07-12',
'2015-07-13',
'2015-07-14',
];
foreach ( $dates as $date )
{
$dt = new DateTimeImmutable( "$date 00:00 UTC" );
echo $dt->format( "D Y-m-d H:i" ), " → ";
$dtn = $dt->modify( "this week" );
echo $dtn->format( "D Y-m-d H:i" ), "\n";
}
?>
--EXPECT--
Sat 2015-07-04 00:00 → Mon 2015-06-29 00:00
Sun 2015-07-05 00:00 → Mon 2015-06-29 00:00
Mon 2015-07-06 00:00 → Mon 2015-07-06 00:00
Tue 2015-07-07 00:00 → Mon 2015-07-06 00:00
Wed 2015-07-08 00:00 → Mon 2015-07-06 00:00
Thu 2015-07-09 00:00 → Mon 2015-07-06 00:00
Fri 2015-07-10 00:00 → Mon 2015-07-06 00:00
Sat 2015-07-11 00:00 → Mon 2015-07-06 00:00
Sun 2015-07-12 00:00 → Mon 2015-07-06 00:00
Mon 2015-07-13 00:00 → Mon 2015-07-13 00:00
Tue 2015-07-14 00:00 → Mon 2015-07-13 00:00
......@@ -5145,6 +5145,10 @@ PHP_FUNCTION(imagescale)
}
}
if (tmp_h <= 0 || tmp_w <= 0) {
RETURN_FALSE;
}
new_width = tmp_w;
new_height = tmp_h;
......
......@@ -133,6 +133,10 @@ gdImagePtr gdImageCreate (int sx, int sy)
return NULL;
}
if (overflow2(sizeof(unsigned char *), sx)) {
return NULL;
}
im = (gdImage *) gdCalloc(1, sizeof(gdImage));
/* Row-major ever since gd 1.3 */
......@@ -1098,12 +1102,12 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
int thick = im->thick;
if (color == gdAntiAliased) {
/*
/*
gdAntiAliased passed as color: use the much faster, much cheaper
and equally attractive gdImageAALine implementation. That
clips too, so don't clip twice.
*/
gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
return;
}
......@@ -1769,6 +1773,12 @@ void gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
return;
}
if (!im->trueColor) {
if ((color > (im->colorsTotal - 1)) || (border > (im->colorsTotal - 1)) || (color < 0)) {
return;
}
}
restoreAlphaBlending = im->alphaBlendingFlag;
im->alphaBlendingFlag = 0;
......@@ -1880,7 +1890,7 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc)
return;
}
alphablending_bak = im->alphaBlendingFlag;
alphablending_bak = im->alphaBlendingFlag;
im->alphaBlendingFlag = 0;
if (nc==gdTiled){
......@@ -1892,7 +1902,7 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc)
wx2=im->sx;wy2=im->sy;
oc = gdImageGetPixel(im, x, y);
if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) {
im->alphaBlendingFlag = alphablending_bak;
im->alphaBlendingFlag = alphablending_bak;
return;
}
......@@ -1955,7 +1965,7 @@ skip: for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++);
efree(stack);
done:
im->alphaBlendingFlag = alphablending_bak;
im->alphaBlendingFlag = alphablending_bak;
}
static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc)
......@@ -2063,7 +2073,7 @@ void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
x1ul = x1 - half;
y1ul = y1 - half;
x2lr = x2 + half;
y2lr = y2 + half;
......@@ -2265,7 +2275,7 @@ void gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int s
int tox, toy;
int ncR, ncG, ncB;
toy = dstY;
for (y = srcY; y < (srcY + h); y++) {
tox = dstX;
for (x = srcX; x < (srcX + w); x++) {
......@@ -2362,7 +2372,7 @@ void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int
int colorMap[gdMaxColors];
/* Stretch vectors */
int *stx, *sty;
if (overflow2(sizeof(int), srcW)) {
return;
}
......@@ -2907,7 +2917,7 @@ int gdAlphaBlend (int dst, int src) {
src_weight = gdAlphaTransparent - src_alpha;
dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
tot_weight = src_weight + dst_weight;
/* -------------------------------------------------------------------- */
/* What red, green and blue result values will we use? */
/* -------------------------------------------------------------------- */
......
......@@ -138,11 +138,18 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in
if (gd2_compressed(*fmt)) {
nc = (*ncx) * (*ncy);
GD2_DBG(php_gd_error("Reading %d chunk index entries", nc));
if (overflow2(sizeof(t_chunk_info), nc)) {
goto fail1;
}
sidx = sizeof(t_chunk_info) * nc;
if (sidx <= 0) {
goto fail1;
}
cidx = gdCalloc(sidx, 1);
if (cidx == NULL) {
goto fail1;
}
for (i = 0; i < nc; i++) {
if (gdGetInt(&cidx[i].offset, in) != 1) {
gdFree(cidx);
......
......@@ -1047,6 +1047,9 @@ static inline void _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_w
}
contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation);
if (contrib == NULL) {
return;
}
/* scale each column */
for (u = 0; u < dst_width - 1; u++) {
_gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib);
......@@ -1059,6 +1062,10 @@ gdImagePtr gdImageScaleTwoPass(const gdImagePtr src, const unsigned int src_widt
gdImagePtr tmp_im;
gdImagePtr dst;
if (new_width == 0 || new_height == 0) {
return NULL;
}
/* Convert to truecolor if it isn't; this code requires it. */
if (!src->trueColor) {
gdImagePaletteToTrueColor(src);
......@@ -1087,6 +1094,10 @@ gdImagePtr Scale(const gdImagePtr src, const unsigned int src_width, const unsig
{
gdImagePtr tmp_im;
if (new_width == 0 || new_height == 0) {
return NULL;
}
tmp_im = gdImageCreateTrueColor(new_width, src_height);
if (tmp_im == NULL) {
return NULL;
......@@ -1120,6 +1131,10 @@ gdImagePtr gdImageScaleNearestNeighbour(gdImagePtr im, const unsigned int width,
unsigned long dst_offset_y = 0;
unsigned int i;
if (new_width == 0 || new_height == 0) {
return NULL;
}
dst_img = gdImageCreateTrueColor(new_width, new_height);
if (dst_img == NULL) {
......@@ -1221,6 +1236,10 @@ static gdImagePtr gdImageScaleBilinearPalette(gdImagePtr im, const unsigned int
gdImagePtr new_img;
const int transparent = im->transparent;
if (new_width == 0 || new_height == 0) {
return NULL;
}
new_img = gdImageCreateTrueColor(new_width, new_height);
if (new_img == NULL) {
return NULL;
......@@ -1313,6 +1332,10 @@ static gdImagePtr gdImageScaleBilinearTC(gdImagePtr im, const unsigned int new_w
long i;
gdImagePtr new_img;
if (new_width == 0 || new_height == 0) {
return NULL;
}
new_img = gdImageCreateTrueColor(new_width, new_height);
if (!new_img){
return NULL;
......@@ -1412,6 +1435,10 @@ gdImagePtr gdImageScaleBicubicFixed(gdImagePtr src, const unsigned int width, co
unsigned int dst_offset_y = 0;
long i;
if (new_width == 0 || new_height == 0) {
return NULL;
}
/* impact perf a bit, but not that much. Implementation for palette
images can be done at a later point.
*/
......@@ -1634,7 +1661,11 @@ gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, cons
gdImagePtr im_scaled = NULL;
if (src == NULL || src->interpolation_id < 0 || src->interpolation_id > GD_METHOD_COUNT) {
return 0;
return NULL;
}
if (new_width == 0 || new_height == 0) {
return NULL;
}
switch (src->interpolation_id) {
......@@ -1680,6 +1711,10 @@ gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, co
unsigned int i;
gdImagePtr dst;
if (new_width == 0 || new_height == 0) {
return NULL;
}
dst = gdImageCreateTrueColor(new_width, new_height);
if (!dst) {
return NULL;
......
......@@ -43,7 +43,7 @@
* If it is not working, it's not Thomas G. Lane's fault.
*/
/*
/*
SETTING THIS ONE CAUSES STRIPED IMAGE
to be done: solve this
#define ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS
......@@ -152,7 +152,7 @@
* color space, and repeatedly splits the "largest" remaining box until we
* have as many boxes as desired colors. Then the mean color in each
* remaining box becomes one of the possible output colors.
*
*
* The second pass over the image maps each input pixel to the closest output
* color (optionally after applying a Floyd-Steinberg dithering correction).
* This mapping is logically trivial, but making it go fast enough requires
......@@ -1320,16 +1320,16 @@ pass2_no_dither (j_decompress_ptr cinfo,
#else
r = gdTrueColorGetRed (*inptr);
g = gdTrueColorGetGreen (*inptr);
/*
/*
2.0.24: inptr must not be incremented until after
transparency check, if any. Thanks to "Super Pikeman."
transparency check, if any. Thanks to "Super Pikeman."
*/
b = gdTrueColorGetBlue (*inptr);
/* If the pixel is transparent, we assign it the palette index that
* will later be added at the end of the palette as the transparent
* index. */
if ((oim->transparent >= 0) && (oim->transparent == *(inptr - 1)))
if ((oim->transparent >= 0) && (oim->transparent == *inptr))
{
*outptr++ = nim->colorsTotal;
inptr++;
......@@ -1795,7 +1795,7 @@ static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int color
}
} else {
nim = oim;
}
}
if (!oim->trueColor)
{
/* (Almost) nothing to do! */
......@@ -2004,7 +2004,7 @@ static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int color
}
/* Success! Get rid of the truecolor image data. */
if (!cimP) {
if (!cimP) {
oim->trueColor = 0;
/* Junk the truecolor pixels */
for (i = 0; i < oim->sy; i++)
......
--TEST--
Bug #72298: pass2_no_dither out-of-bounds access
--SKIPIF--
<?php
if (!extension_loaded('gd')) die("skip gd extension not available\n");
?>
--FILE--
<?php
$img = imagecreatetruecolor (1 , 1);
imagecolortransparent($img, 0);
imagetruecolortopalette($img, false, 4);
?>
DONE
--EXPECT--
DONE
\ No newline at end of file
--TEST--
#72337 segfault in imagescale with new dimensions being <=0)
--SKIPIF--
<?php
if (!function_exists('imagescale')) die("skip gd extension not available\n");
?>
--FILE--
<?php
$im = imagecreatetruecolor(1, 1);
imagescale($im, 0, 0, IMG_BICUBIC_FIXED);
echo "OK";
?>
--EXPECT--
OK
--TEST--
Bug #72339 Integer Overflow in _gd2GetHeader() resulting in heap overflow
--SKIPIF--
<?php if (!function_exists("imagecreatefromgd2")) print "skip"; ?>
--FILE--
<?php
$fname = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug72339.gd";
$fh = fopen($fname, "w");
fwrite($fh, "gd2\x00");
fwrite($fh, pack("n", 2));
fwrite($fh, pack("n", 1));
fwrite($fh, pack("n", 1));
fwrite($fh, pack("n", 0x40));
fwrite($fh, pack("n", 2));
fwrite($fh, pack("n", 0x5AA0)); // Chunks Wide
fwrite($fh, pack("n", 0x5B00)); // Chunks Vertically
fwrite($fh, str_repeat("\x41\x41\x41\x41", 0x1000000)); // overflow data
fclose($fh);
$im = imagecreatefromgd2($fname);
if ($im) {
imagedestroy($im);
}
unlink($fname);
?>
--EXPECTF--
Warning: imagecreatefromgd2(): gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully
in %sbug72339.php on line %d
Warning: imagecreatefromgd2(): '%sbug72339.gd' is not a valid GD2 file in %sbug72339.php on line %d
--TEST--
Github #215 (imagefilltoborder stack overflow when invalid pallete index used)
--SKIPIF--
<?php
if (!extension_loaded("gd")) die("skip GD not present");
?>
--FILE--
<?php
$image = imagecreate( 10, 10 );
$bgd = imagecolorallocate( $image, 0, 0, 0 );
$border = imagecolorallocate( $image, 255, 0, 0 );
$fillcolor = imagecolorallocate( $image, 255, 0, 0 );
/* Use unallocated color index */
imagefilltoborder( $image, 0,0, $border+10, $fillcolor);
echo "#1 passes\n";
/* Use negative color index */
imagefilltoborder( $image, 0,0, -$border, $fillcolor);
echo "#2 passes\n";
/* Use unallocated color index */
imagefilltoborder( $image, 0,0, $border, $fillcolor+10);
echo "#3 passes\n";
/* Use negative color index */
imagefilltoborder( $image, 0,0, $border, -$fillcolor);
echo "#4 passes\n";
/* Use negative color index */
imagefilltoborder( $image, 0,0, $border+10, $fillcolor+10);
echo "#5 passes";
?>
--EXPECT--
#1 passes
#2 passes
#3 passes
#4 passes
#5 passes
......@@ -264,6 +264,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo,
type = Formattable::kDouble;
} else if (argType == UMSGPAT_ARG_TYPE_SELECT) {
type = Formattable::kString;
#if U_ICU_VERSION_MAJOR_NUM >= 50
} else if (argType == UMSGPAT_ARG_TYPE_SELECTORDINAL) {
type = Formattable::kDouble;
#endif
} else {
type = Formattable::kString;
}
......
--TEST--
Bug #53735 NumberFormatter returns NaN when converting float point
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if (version_compare(INTL_ICU_VERSION, '51.2') < 0) die('skip for ICU >= 51.2'); ?>
--FILE--
<?php
$fmt = numfmt_create("da_DK", \NumberFormatter::CURRENCY);
var_dump(numfmt_format($fmt, 5.5));
setlocale(LC_ALL, "da_DK.UTF-8");
var_dump(numfmt_format($fmt, 5.5));
var_dump(numfmt_format($fmt, "5,5"));
$fmt = new \NumberFormatter("de_DE", \NumberFormatter::DECIMAL);
var_dump($fmt->format(23.25));
$f = new NumberFormatter('hu_HU', NumberFormatter::PERCENT, '#,##0%');
var_dump($f->format(0.26));
?>
==DONE==
--EXPECTF--
string(%d) "5,50 kr%A"
string(%d) "5,50 kr%A"
string(%d) "5,00 kr%A"
string(5) "23,25"
string(3) "26%"
==DONE==
--TEST--
Bug #70484 selectordinal doesn't work with named parameters
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
if (version_compare(INTL_ICU_VERSION, '5.0') < 0)
die('skip for ICU 5.0+');
--FILE--
<?php
$locale = array("de", "fr", "en", "ru",);
$data = array(42, 42.42, 2147483643, 2147483643.12345, 5);
foreach ($locale as $lc) {
echo "$lc string key\n";
$m = new MessageFormatter($lc, "{n, selectordinal, =5 {five} zero {#-zero} one {#-one} two {#-two} few {#-few} many {#-many} other {#-other}}");
foreach ($data as $i) {
var_dump($m->format(array("n" => $i)));
if ($m->getErrorCode()) {
echo "$lc $i ", $m->getErrorMessage();
}
}
echo "\n";
echo "$lc numeric key\n";
$m = new MessageFormatter($lc, "{0, selectordinal, =5 {five} zero {#-zero} one {#-one} two {#-two} few {#-few} many {#-many} other {#-other}}");
foreach ($data as $i) {
var_dump($m->format(array($i)));
if ($m->getErrorCode()) {
echo "$lc $i ", $m->getErrorMessage();
}
}
echo "\n";
}
?>
==DONE==
--EXPECT--
de string key
string(8) "42-other"
string(11) "42,42-other"
string(19) "2.147.483.643-other"
string(23) "2.147.483.643,123-other"
string(4) "five"
de numeric key
string(8) "42-other"
string(11) "42,42-other"
string(19) "2.147.483.643-other"
string(23) "2.147.483.643,123-other"
string(4) "five"
fr string key
string(8) "42-other"
string(11) "42,42-other"
string(22) "2 147 483 643-other"