Skip to content

UB in php_url_decode_ex #21738

@xfourj

Description

@xfourj

Description

Consider the following snippet within php_url_decode_ex at ext/standard/url.c :

else if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1))
				 && isxdigit((int) *(data + 2))) {

In environments where char is signed by default—as is a common convention— high-bit bytes sign-extend to negative integers when being passed to isxdigit. That violates the ISO C standard's requirement for isxdigit in <ctype.h> to be represenetable as an unsigned char (0 to 255), which leads to UB.

Example (taking \x80 as the byte):

<?php
urldecode("%\x80");
?>

Resulted in this output:

(gdb) p *(data+1)
$1 = -128 '\200'

Note that for libraries that implement isxdigit via maps (similar to glibc), if no proper padding is done then OOB read might occur.

PHP Version

PHP 8.4+

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions