WordPress.org

Make WordPress Core

Opened 14 months ago

Last modified 7 months ago

#20560 new defect (bug)

url_to_postid() string matching is not strict enough, can lead to incorrect results

Reported by: gradyetc Owned by:
Priority: normal Milestone: Future Release
Component: Query Version: 3.0
Severity: normal Keywords: has-patch
Cc: gcorne@…

Description

I have been working on a plugin that uses url_to_postid() to automatically translate user generated links to internal links utilizing post ID in order to protect against potential permalink changes.

A bug was reported that involved a link to an external location being translated to an internal link (with post ID) by the plugin.

The current site: http://www.example.com/test

The attempted link: http://www.example.com/test-research

Where test-research is an entirely different site on our multi-site install.

Upon investigation, the source of the problem was an overly generous strpos() check in url_to_postid(), starting at line 322:

if ( false !== strpos($url, home_url()) ) {
	// Chop off http://domain.com
	$url = str_replace(home_url(), '', $url);
} else {
	// Chop off /path/to/blog
	$home_path = parse_url(home_url());
	$home_path = isset( $home_path['path'] ) ? $home_path['path'] : '' ;
	$url = str_replace($home_path, '', $url);
}

As home_url() does not append a trailing slash, the link passed that check and was incorrectly processed. The logic inside that if block resulted in -research being passed as a pagename to WP_Query, which happened to turn up a matching post ID on this particular site.

I have a proposed patch, which I will attach to this ticket asap.

Attachments (3)

20560.diff (1.2 KB) - added by gradyetc 14 months ago.
20876.diff (1.2 KB) - added by gradyetc 13 months ago.
Updated patch -- replaces trailingslashit() with home_url('/')
test_includes_rewrite.diff (2.6 KB) - added by gradyetc 11 months ago.
Added test to expose bug for non-multisite installation

Download all attachments as: .zip

Change History (12)

gradyetc14 months ago

comment:1 SergeyBiryukov14 months ago

  • Keywords has-patch added

comment:2 nacin13 months ago

  • Keywords needs-unit-tests added
  • Version changed from 3.4 to 3.0

Definitely not new - home_url() was I think 3.0, so we can go with that.

home_url( '/' ) can be used as an alternative to trailingslashit().

Looks good. Unit tests would be nice.

gradyetc13 months ago

Updated patch -- replaces trailingslashit() with home_url('/')

comment:3 gradyetc13 months ago

  • Keywords needs-unit-tests removed

Thanks for the response -- I have updated my patch to use home_url('/') instead of trailingslashit() per your recommendation.

I have also attached a new unit test case file for url_to_postid(). AFAICT no file existed to test anything in wp-includes/rewrite.php, so I made a new one and put in a few tests for url_to_postid().

The exact nature of this bug made it a bit tricky to test against, as it takes somewhat of a perfect storm to occur (non-root/subdirectory site url path, specific post names existing, etc.). As a result, the test against this bug requires the -m (multisite) switch to be on, though the bug itself is not limited to multi-site installs.

I am open to suggestions on how to improve that, but at least for now I think it's better than what existed before...

comment:4 gcorne11 months ago

  • Cc gcorne@… added

comment:5 gradyetc11 months ago

I have updated the previously attached unit tests patch to work with the recently updated test framework. My comment above comment above remains relevant.

Version 0, edited 11 months ago by gradyetc (next)

comment:6 SergeyBiryukov11 months ago

  • Milestone changed from Awaiting Review to 3.5

gradyetc11 months ago

Added test to expose bug for non-multisite installation

comment:7 ryan8 months ago

  • Keywords commit added

comment:8 nacin7 months ago

I think the only change that actually needs to occur is ( false !== strpos( $url, home_url() ) ). Should this become ( false !== strpos( trailingslashit( $url ), home_url( '/' ) ) )? We don't want to avoid matching a URL that is the same as the home_url() but minus the trailing slash (as the examples in the ticket description, ironically).

comment:9 nacin7 months ago

  • Keywords commit removed
  • Milestone changed from 3.5 to Future Release
Note: See TracTickets for help on using tickets.