Okay, the reason is in cms/class.tslib_fe.php: 1230
function checkPagerecordForIncludeSection($row) {
return (!$row['extendToSubpages'] || $this->checkEnableFields($row)) ? 1 : 0;
}
This check is plainly wrong, here is the fail-scenario:
Rootline:
1: not protected
`-- 2: fe_group, no extendTo
`-- 3: fe_group, extendTo enabled
`-- 4: not protected
We access '4' directly:
- sys_page->getPage returns the entry (not protected)
- checkRootlineForIncludeSection() returns:
TRUE, TRUE, FALSE, TRUE for non-removal
- the page displayed is the last in the rootLine, which is '2', which is wrong!
We access '3' directly:
- sys_page->getPage returns no entry
- getPageAndRootline() takes over the search for the next valid page and correctly removes 2, 3, 4
- the page displayed is the last in the rootLine, which is '1'
It can be seen that getPageAndRootline() itself does the job just fine, checkRootlineForIncludeSection() is just a post-function for cases that are a bit more complex, especially trying to cover extendTo cases. I asume from that one-liner that the initial intention is to not return FALSE for un-protected pages (those that do not have fe_groups). Reconstructing that initial intention the function should be:
function checkPagerecordForIncludeSection($row) {
return (!$row['fe_group'] || $this->checkEnableFields($row)) ? 1 : 0;
}
instead.
It makes no sense to bind access-restriction to the pure existance of the extendTo-flag!
Patch attached and verified under the given fail-case. Acessing '2', '3' or '4' all drop to '1' now. If logged-in, they all allow correct access.