Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sniff Generic.Files.FilePermissions to check if file is executable #2582

Merged
merged 9 commits into from
Nov 12, 2019
Merged

Add sniff Generic.Files.FilePermissions to check if file is executable #2582

merged 9 commits into from
Nov 12, 2019

Conversation

MasterOdin
Copy link
Contributor

Closes #1808.

Adds Sniff to detect if a file is executable or not.

Tested this manually to check behavior for a file marked as:

  • 400
  • 500
  • 410
  • 401
  • 644
  • 755

Not sure how I might add an automated test for this sniff. Also, errors for this sniff would be easily fixable, but I'm not sure how I would register a fix in the Fixer since it doesn't change any tokens, and I couldn't find an example anywhere.

@MasterOdin MasterOdin changed the title Add sniff to check if file is executable Add sniff Generic.Files.FileExtension to check if file is executable Aug 11, 2019
@MasterOdin MasterOdin changed the title Add sniff Generic.Files.FileExtension to check if file is executable Add sniff Generic.Files.FilePermissions to check if file is executable Aug 11, 2019
Copy link
Contributor

@jrfnl jrfnl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To test this sniff, you could add two different test case files with basically just a PHP open tag in each of them.
One should have a valid permission, one an invalid one.

You can then use a switch on the received file name in the test file to get it working.
See:

public function getErrorList($testFile='')
{
switch ($testFile) {
case 'EndFileNewlineUnitTest.3.inc':
case 'EndFileNewlineUnitTest.3.js':
case 'EndFileNewlineUnitTest.3.css':
case 'EndFileNewlineUnitTest.4.inc':
return [2 => 1];
default:
return [];
}//end switch
}//end getErrorList()

*/
public function register()
{
return [T_OPEN_TAG];
Copy link
Contributor

@jrfnl jrfnl Aug 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to add T_OPEN_TAG_WITH_ECHO as well to also examine files which only use the short echo PHP tag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the other File standards seem to use a similar register. Would it make sense to also update those to also have that tag? I'm fine with just adding it here though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that depends on the individual sniff and should probably be done in a separate PR in that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within just Generic, it includes all the other sniffs that test for the beginning of a file:

  • EndFileNewlineSniff
  • EndFileNoNewlineSniff
  • LineEndingsSniff
  • LineLengthSniff
  • LowercasedFilenameSniff

Agreed that fixing them would be a separate PR, just trying to clarify what the expected style though as I'm not well-versed enough in this project to know when to use one or both.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without looking at the sniffs you've listed - IMO the consideration here would be "does this rule apply to all PHP files or just to PHP-only files ?"

If the rule applies only to PHP-only files, then don't add it.
If the rule applies to PHP-only files as well as mixed HTML/PHP files, then yes, it should be added.

$perms = fileperms($phpcsFile->getFilename());

if (($perms & 0x0040) !== 0 || ($perms & 0x0008) !== 0 || ($perms & 0x0001) !== 0) {
$error = "A PHP file must not be executable";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions/remarks:

  1. The error message says must, the documentation says should. Possibly friendlier: doesn't need ?
  2. Should this be a warning or an error ?
  3. Would it be helpful to end-users to know what the permission found was ? I.e. ... be executable. Found file permission set to %s, where %s would be replaced by passing the found file permission in $data to the addError()/addWarning() method.
  4. As a PHP file can mix PHP with HTML, the open tag may not be on the first line of the file and the way the error is now thrown, the error wouldn't be thrown on line 1 either.
    Would it be better to always throw this error on line 1 of a file (just pass token 0 to do so) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Agreed to changing it to should and the must was on an original draft that I changed in the docs, but forgot to change it here. Can change this here and in docs to doesn't need, but I think it depends on if this is an error or a warning.
  2. Personally, for my work, I'd like this to be an error, but can change if requested and just set the severity in the ruleset.xml
  3. Agreed
  4. Thanks for this, I did not consider that. Fixed.

@MasterOdin
Copy link
Contributor Author

MasterOdin commented Aug 11, 2019

Thank you for your comments/review. I've addressed some of the comments I could and asked for clarification on some points. Added some tests per your suggestion, will see if they commit with the correct set of permissions in Travis.

@gsherwood gsherwood modified the milestone: 3.5.0 Sep 17, 2019
@gsherwood
Copy link
Member

I've just got around to testing this sniff and came across a problem. It doesn't work with the caching system in PHPCS.

PHPCS checks that the file contents (and names) of the files it is checking haven't changed before using the cache, but it doesn't detect permission changes. So that means that when you fix the perms on the file, running PHPCS again still shows the same error.

I've removed this from the 3.5.0 release so I can have more of a think about it. I'm not sure if I should include file perm checking in the cache just in case this sniff is used, or if the sniff should be able to signal that it makes the request uncacheable in some way. Or some other option.

The sniff and tests work great though. Thanks.

@gsherwood gsherwood added this to the 3.5.1 milestone Sep 20, 2019
@MasterOdin
Copy link
Contributor Author

From my standpoint, I would think that including file permissions in the cache details would probably be the most straightforward approach and would probably not affect that many people (as I assume that most people are not changing the permissions of files with any great frequency), while also still making this type of sniff benefit from having the cache, which I'd imagine would be useful for very large codebases.

@gsherwood gsherwood modified the milestones: 3.5.1, 3.5.2 Oct 1, 2019
gsherwood added a commit that referenced this pull request Nov 12, 2019
gsherwood added a commit that referenced this pull request Nov 12, 2019
@gsherwood gsherwood merged commit bf168df into squizlabs:master Nov 12, 2019
@gsherwood
Copy link
Member

I've merged this in. Thanks a lot for the PR.

I ended up renaming the sniff because I thought it sounded too generic, as if it would provide you the ability to check file permissions based on whatever your standard is. It is now called Generic.Files.ExecutableFile instead, so it is limited to checking the executable flag on a file.

I modified the core cache code to include the permissions of a file in its hash so that this sniff works correctly with the existing cache feature. It didn't appear to add much time to the run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Test for file execute bit
3 participants