Skip to content

Commit 37c5a13

Browse files
jordikroonalexdowad
authored andcommitted
replace alloca with do_alloca in mb_guess_encoding_for_strings
This avoids a crash in cases where the list of candidate encodings is so huge that alloca would fail. Such crashes have been observed when the list of encodings was larger than around 208,000 entries.
1 parent 84bfe2f commit 37c5a13

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ PHP NEWS
2727
. Fixed bug GH-21097 (Accessing Dom\Node properties can can throw TypeError).
2828
(ndossche)
2929

30+
- MBString:
31+
. Fixed bug GH-21223; mb_guess_encoding no longer crashes when passed huge
32+
list of candidate encodings (with 200,000+ entries). (Jordi Kroon)
33+
3034
- Opcache:
3135
. Fixed bug GH-20718 ("Insufficient shared memory" when using JIT on Solaris).
3236
(Petr Sumbera)

ext/mbstring/mbstring.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3376,15 +3376,17 @@ MBSTRING_API const mbfl_encoding* mb_guess_encoding_for_strings(const unsigned c
33763376
return *elist;
33773377
}
33783378

3379-
/* Allocate on stack; when we return, this array is automatically freed */
3380-
struct candidate *array = alloca(elist_size * sizeof(struct candidate));
3379+
/* Allocate on stack or heap */
3380+
ALLOCA_FLAG(use_heap)
3381+
struct candidate *array = do_alloca(elist_size * sizeof(struct candidate), use_heap);
33813382
elist_size = init_candidate_array(array, elist_size, elist, strings, str_lengths, n, strict, order_significant);
33823383

33833384
while (n--) {
33843385
start_string(array, elist_size, strings[n], str_lengths[n]);
33853386
elist_size = count_demerits(array, elist_size, strict);
33863387
if (elist_size == 0) {
33873388
/* All candidates were eliminated */
3389+
free_alloca(array, use_heap);
33883390
return NULL;
33893391
}
33903392
}
@@ -3396,7 +3398,10 @@ MBSTRING_API const mbfl_encoding* mb_guess_encoding_for_strings(const unsigned c
33963398
best = i;
33973399
}
33983400
}
3399-
return array[best].enc;
3401+
3402+
const mbfl_encoding *result = array[best].enc;
3403+
free_alloca(array, use_heap);
3404+
return result;
34003405
}
34013406

34023407
/* When doing 'strict' detection, any string which is invalid in the candidate encoding

ext/mbstring/tests/gh21223.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-21223 (Stack overflow in mb_guess_encoding called via mb_detect_encoding)
3+
--EXTENSIONS--
4+
mbstring
5+
--FILE--
6+
<?php
7+
$str = "hello";
8+
9+
$list = [];
10+
for ($i = 0; $i < 500000; $i++) {
11+
$list[] = "UTF-8";
12+
}
13+
14+
var_dump(mb_detect_encoding($str, $list, false));
15+
echo "Done";
16+
?>
17+
--EXPECT--
18+
string(5) "UTF-8"
19+
Done

0 commit comments

Comments
 (0)