Make WordPress Core

Opened 10 years ago

Closed 9 years ago

#28015 closed defect (bug) (fixed)

esc_url_raw (esc_url) throw "Uninitialized string offset: 0" with invalid chars

Reported by: mmems's profile mmems Owned by: johnbillion's profile johnbillion
Milestone: 4.4 Priority: normal
Severity: normal Version: 3.3
Component: Formatting Keywords: has-patch commit
Focuses: Cc:

Description

esc_url_raw('"^[]<>{}`');

Will throw "Uninitialized string offset: 0" because the length of resulting string (after filtering all invalid chars) is not tested before check if it's a relative URL

if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) ...
-----------------------------------------------------^

Attachments (5)

28015.diff (828 bytes) - added by jesin 10 years ago.
Check if $url is empty after sanitization before checking its first character
28015.2.diff (814 bytes) - added by jesin 10 years ago.
Use substr() to select the first character of $url
28015.3.diff (977 bytes) - added by jesin 10 years ago.
Slight modification to 28015.diff
28015.4.diff (1.3 KB) - added by jesin 9 years ago.
Refreshed 28015.3.diff and added an unit test
28015.5.diff (1.1 KB) - added by johnbillion 9 years ago.

Download all attachments as: .zip

Change History (13)

@jesin
10 years ago

Check if $url is empty after sanitization before checking its first character

@jesin
10 years ago

Use substr() to select the first character of $url

#1 @jesin
10 years ago

  • Version changed from 3.9 to 3.3

The second patch is cleaner and does the same thing without adding additional conditions like empty().

The substr() function was used before 3.2. Please check if the patch works for all kinds of input.

#2 @mmems
10 years ago

The error disappear now, but:

esc_url_raw('"^[]<>{}`');
// now returns: "http://"

Maybe the emptiness test should be after chars filtering :

$url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
$strip = array('%0d', '%0a', '%0D', '%0A');
$url = _deep_replace($strip, $url);
$url = str_replace(';//', '://', $url);
if ( '' == $url )
	return $url;

Instead of:

if ( '' == $url )
	return $url;
$url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
$strip = array('%0d', '%0a', '%0D', '%0A');
$url = _deep_replace($strip, $url);
$url = str_replace(';//', '://', $url);

@jesin
10 years ago

Slight modification to 28015.diff

#3 @jesin
10 years ago

The third patch should fix it. Let me know if it works for you.

#4 @mmems
10 years ago

It's ok now (for my following test case "<>[\]^`{})

#5 @jesin
10 years ago

  • Keywords has-patch added

#6 @johnbillion
9 years ago

  • Keywords needs-unit-tests needs-patch added; has-patch removed
  • Milestone changed from Awaiting Review to 4.4
  • Owner set to johnbillion
  • Status changed from new to accepted

@jesin
9 years ago

Refreshed 28015.3.diff and added an unit test

@johnbillion
9 years ago

#7 @johnbillion
9 years ago

  • Keywords has-patch commit added; needs-unit-tests needs-patch removed

In 28015.5.diff: If a URL is so malformed that it contains only characters which get stripped out, then the function should bail out early, as it does for an empty URL.

#8 @johnbillion
9 years ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 33923:

Bail out early from esc_url() if the URL becomes empty after stripping out disallowed characters.

Fixes #28015
Props jesin for the unit test

Note: See TracTickets for help on using tickets.