Skip to content

Commit bf363ad

Browse files
nielsdosremicollet
authored andcommitted
Fix GHSA-g665-fm4p-vhff: OOB access in ldap_escape
(cherry picked from commit f9ecf90070a11dad09ca7671a712f81cc2a7d52f) (cherry picked from commit 9f367d8) (cherry picked from commit 50e9e72) (cherry picked from commit 9822bfa) (cherry picked from commit f8756a7) (cherry picked from commit c8a7aed) (cherry picked from commit 0ad928e)
1 parent da023a8 commit bf363ad

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

ext/ldap/ldap.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060

6161
#include "ext/standard/php_string.h"
6262
#include "ext/standard/info.h"
63+
#include "Zend/zend_exceptions.h"
6364

6465
#ifdef HAVE_LDAP_SASL_H
6566
#include <sasl.h>
@@ -2648,7 +2649,12 @@ static void php_ldap_do_escape(const zend_bool *map, const char *value, size_t v
26482649
size_t len = 0;
26492650

26502651
for (i = 0; i < valuelen; i++) {
2651-
len += (map[(unsigned char) value[i]]) ? 3 : 1;
2652+
size_t addend = (map[(unsigned char) value[i]]) ? 3 : 1;
2653+
if (len > INT_MAX - addend) {
2654+
*result = NULL;
2655+
return;
2656+
}
2657+
len += addend;
26522658
}
26532659

26542660
(*result) = (char *) safe_emalloc_string(1, len, 1);
@@ -2715,6 +2721,11 @@ PHP_FUNCTION(ldap_escape)
27152721

27162722
php_ldap_do_escape(map, value, valuelen, &result, &resultlen);
27172723

2724+
if (UNEXPECTED(!result)) {
2725+
zend_throw_exception(NULL, "Argument #1 ($value) is too long", 0 TSRMLS_CC);
2726+
return;
2727+
}
2728+
27182729
RETURN_STRINGL(result, resultlen, 0);
27192730
}
27202731

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
GHSA-g665-fm4p-vhff (OOB access in ldap_escape)
3+
--EXTENSIONS--
4+
ldap
5+
--INI--
6+
memory_limit=-1
7+
--SKIPIF--
8+
<?php
9+
if (PHP_INT_SIZE !== 4) die("skip only for 32-bit");
10+
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
11+
?>
12+
--FILE--
13+
<?php
14+
try {
15+
ldap_escape(' '.str_repeat("#", 1431655758), "", LDAP_ESCAPE_DN);
16+
} catch (Exception $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
20+
try {
21+
ldap_escape(str_repeat("#", 1431655758).' ', "", LDAP_ESCAPE_DN);
22+
} catch (Exception $e) {
23+
echo $e->getMessage(), "\n";
24+
}
25+
?>
26+
--EXPECT--
27+
ldap_escape(): Argument #1 ($value) is too long
28+
ldap_escape(): Argument #1 ($value) is too long
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GHSA-g665-fm4p-vhff (OOB access in ldap_escape)
3+
--EXTENSIONS--
4+
ldap
5+
--INI--
6+
memory_limit=-1
7+
--SKIPIF--
8+
<?php
9+
if (PHP_INT_SIZE !== 4) die("skip only for 32-bit");
10+
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
11+
?>
12+
--FILE--
13+
<?php
14+
try {
15+
ldap_escape(str_repeat("*", 1431655759), "", LDAP_ESCAPE_FILTER);
16+
} catch (Exception $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
20+
// would allocate a string of length 2
21+
try {
22+
ldap_escape(str_repeat("*", 1431655766), "", LDAP_ESCAPE_FILTER);
23+
} catch (Exception $e) {
24+
echo $e->getMessage(), "\n";
25+
}
26+
?>
27+
--EXPECT--
28+
ldap_escape(): Argument #1 ($value) is too long
29+
ldap_escape(): Argument #1 ($value) is too long

0 commit comments

Comments
 (0)