Description

In ext/filter/sanitizing_filters.c, the php_filter_encode_url function leaves the 255th byte (0xFF) of a transient array uninitialized. An array of 256 bytes is populated using memset(tmp, 1, sizeof(tmp) - 1), resulting in tmp[255] remaining uninitialized. When FILTER_SANITIZE_ENCODED is applied, this array acts as a lookup table to determine whether an input byte should be percent-encoded. Consequently, whether the byte 0xFF is encoded or left as-is depends on whatever value happened to be on the stack.

Proof of concept

<?php
/*
 * FILTER_SANITIZE_ENCODED uninitialized read (ext/filter/sanitizing_filters.c:73).
 *
 * php_filter_encode_url() does:
 *     unsigned char tmp[256];
 *     memset(tmp, 1, sizeof(tmp) - 1);   // sets tmp[0..254] = 1, leaves tmp[255] UNINIT
 *     ...
 *     if (tmp[*s]) { percent-encode } else { keep }
 *
 * So byte 0xFF (index 255) is read UNINITIALIZED: whether it is percent-encoded
 * depends on whatever was on the stack. Every other byte is encoded
 * deterministically. Effect: inconsistent URL-encoding of 0xFF (low severity;
 * no crash / no memory corruption, just UB + nondeterministic sanitizing).
 *
 * Run:  php poc.php
 *   expect: 0xFF kept RAW (ff...) while 0xFE is correctly percent-encoded (%FE)
 */
$out = filter_var("\xff\xfeabc", FILTER_SANITIZE_ENCODED);
echo "in : ", bin2hex("\xff\xfeabc"), "\n";
echo "out: ", bin2hex($out), "\n";
echo "0xFF was kept raw and 0xFE was percent-encoded => tmp[255] read uninitialized.\n";

Running the script results in:

in : fffe616263
out: ff254645616263
0xFF was kept raw and 0xFE was percent-encoded => tmp[255] read uninitialized.

Impact

The impact is low. No crashes or memory corruption can occur as a result of this bug. The sole impact is nondeterministic sanitizing of the 0xFF byte, which leads to inconsistent URL-encoding based on uninitialized stack data unless it smartly gets used among other vulnerabilities in a chain.

Solution

Replace sizeof(tmp) - 1 with sizeof(tmp) in the memset call in ext/filter/sanitizing_filters.c to fully initialize the lookup table.