# Symlinks in / don't work

- Thread: https://externals.io/message/57553
- Original archive: https://news-web.php.net/php.internals/57553
- Started by Rasmus Lerdorf on 2012-01-28T23:06:08+00:00
- Messages: 2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #57553 — Rasmus Lerdorf — 2012-01-28T23:06:08+00:00

URL: https://externals.io/message/57553#57553

Hey Dmitry, could you take a look at this one. I think this is mostly
your code and I am a bit lost in the path manipulation that is going on
here. This is bug https://bugs.php.net/51860 and it can be reproduced
from cli like this:

% cd /
% ln -s / phptest
% echo "OK" > /phpfile
% echo '<?php include "/phptest/phpfile";' > /phpinc

% php /phptest/phpinc

And you will see that it can't find /phptest/phpfile

But magically if you run it like this:

% php phptest/phpinc

it works fine.

The problem is that /phptest gets cached without the directory bit set.
And when we read it back from the cache and see it isn't a directory we
obviously don't think it can contain a file. It works in the second case
because of what is probably a secondary bug and that is that it ends up
caching //phptest instead of /phptest. So in that case there is a cache
miss on the include and it doesn't fail. However, if you add a second
include that includes another file from /phptest then the first include
would have caused /phptest to get cached and the second include will
then fail.

If you do this exact same test from /foo instead of from / then
/foo/phptest which in this case is a symlink to /foo correctly gets
cached with directory=1.

So somewhere in the while(1) loop logic in tsrm_realpath_r() we fail to
get to the point where we stat / and set the directory bit.

Obviously if someone else wants to fire up gdb to find the likely
off-by-one error that is causing this, please do.

-Rasmus

---

## #57564 — Dmitry Stogov — 2012-01-30T07:42:03+00:00

URL: https://externals.io/message/57553#57564 · In reply to: #57553

Hi Rasmus,

I've reproduced it and will take a deeper look a bit later today.

Thanks. Dmitry.


> Hey Dmitry, could you take a look at this one. I think this is mostly
> your code and I am a bit lost in the path manipulation that is going on
> here. This is bug https://bugs.php.net/51860 and it can be reproduced
> from cli like this:
>
> % cd /
> % ln -s / phptest
> % echo "OK">  /phpfile
> % echo '<?php include "/phptest/phpfile";'>  /phpinc
>
> % php /phptest/phpinc
>
> And you will see that it can't find /phptest/phpfile
>
> But magically if you run it like this:
>
> % php phptest/phpinc
>
> it works fine.
>
> The problem is that /phptest gets cached without the directory bit set.
> And when we read it back from the cache and see it isn't a directory we
> obviously don't think it can contain a file. It works in the second case
> because of what is probably a secondary bug and that is that it ends up
> caching //phptest instead of /phptest. So in that case there is a cache
> miss on the include and it doesn't fail. However, if you add a second
> include that includes another file from /phptest then the first include
> would have caused /phptest to get cached and the second include will
> then fail.
>
> If you do this exact same test from /foo instead of from / then
> /foo/phptest which in this case is a symlink to /foo correctly gets
> cached with directory=1.
>
> So somewhere in the while(1) loop logic in tsrm_realpath_r() we fail to
> get to the point where we stat / and set the directory bit.
>
> Obviously if someone else wants to fire up gdb to find the likely
> off-by-one error that is causing this, please do.
>
> -Rasmus
