Skip to content

Conversation

@johnstevenson
Copy link
Contributor

An uninitialized php_stream_statbuf in php_stat (ext\standard\filestat.c) can cause random st_mode values when calling lstat on an NTFS junction.

The php_sys_stat_ex function (zend\zend_virtual_cwd.c) sets the st_mode for everything except a junction, so the uninitialized value is returned.

I have initialized the buffer in _php_stream_stat_path, since this function is called in several places.

Note that this anomaly has been "fixed" on master (e42e8b1) in that @weltling 's code in win32\ioutil.c initializes the individual stat members.

@johnstevenson
Copy link
Contributor Author

Some wacky CI test results. Travis passes/Appveyor times out? on the first commit, then Travis fails/Appveyor passes on the second commit (which makes an inconsequential change to a Windows only test).

@nikic
Copy link
Member

nikic commented Feb 2, 2019

Don't worry, AppVeyor timeouts are "normal" right now and the failing test on Travis is spurious.

This looks good to me, but cc @cmb69 @weltling for the Windows side (esp. the test).

@johnstevenson
Copy link
Contributor Author

Thanks @nikic

@cmb69
Copy link
Member

cmb69 commented Feb 3, 2019

Actually, we're hitting this:

#if 0 /* Not used yet */
else if(pbuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
buf->st_mode |=;
}
#endif

It might be worthwhile to actually implement support for IO_REPARSE_TAG_MOUNT_POINTs, and also to add an else clause which sets buf->st_mode (or to initialize it immediately before the if statement).

@johnstevenson
Copy link
Contributor Author

@cmb69 I didn't fix it there because the stat function calls come from main\streams\streams.c to either _php_stream_stat or _php_stream_stat_path. The former already initializes the buffer so it seemed sensible to make the latter do the same.

However, I can zero initialize buf->st_mode in zend\zend_virtual_cwd.c as well, if you wish (as per PHP-7.4). Please advise.

Regarding support for IO_REPARSE_TAG_MOUNT_POINT, this would be great, but it requires some thought about what to set st_mode to in such cases:

  • there is no S_IFJNC (or whatever) so anything used would be non-standard (S_IXJNC) and need to be documented. Also, because it is non-standard there would possibly also be a need for a new windows_is_junction function (or some such).

  • And if we did that, would we need to differentiate between junctions and mount points (S_IXMNT and windows_is_mount)?

I'm sure @weltling will have some ideas. My intention here was to supply a quick fix so that the data is consistent, but I will do anything I can to help.

@weltling
Copy link
Contributor

weltling commented Feb 5, 2019

Since it's a fix targeting 7.2, it seems to fine merge (probably should be 7.2 only). The handling of IO_REPARSE_TAG_MOUNT_POINT should target 7.4, if there should be an implementation. There are several irregularities with that, as @johnstevenson mentions, and there should be a lot of testing including network mounts, too.

Thanks.

@johnstevenson
Copy link
Contributor Author

Thanks @weltling But why "probably should be 7.2 only"?

The buffer is uninitialized in 7.3 as well.

@weltling
Copy link
Contributor

weltling commented Feb 5, 2019

@johnstevenson in 7.3+, any stat call should be running through the ioutil implementation. You mention it in the description actually. If it's not the case, probaly need to check as something should have been missed. Though it might bring regressions, in that case your patch should be ok for 7.3, too.

Thanks.

@johnstevenson
Copy link
Contributor Author

@weltling From what I can see the ioutil implementation (php_win32_ioutil_stat_ex_w) is not in 7.3. It is in master and 7.4 though.

@weltling
Copy link
Contributor

weltling commented Feb 5, 2019

@johnstevenson ah, indeed. Then 7.2 and 7.3 are good to go, and empty merge upwards :) The missing implementation is a separate thing anyway.

Thansk.

@nikic
Copy link
Member

nikic commented Feb 11, 2019

Merged as fe4d724 into 7.2+. I've merged this as-is up to master, as zeroing the struct seems like a good defensive practice independently of the specific issue encountered here.

@nikic nikic closed this Feb 11, 2019
@johnstevenson johnstevenson deleted the bug-77552 branch February 11, 2019 11:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants