This commit is contained in:
Sergey
2017-03-02 17:31:05 -08:00
11 changed files with 164 additions and 54 deletions

View File

@ -8,19 +8,10 @@ addons:
language: java
jdk: oraclejdk8
before_install:
- bash .travis/setup-secrets.sh
- bash .travis/install-configure-maven.sh
- export M2_HOME=$HOME/apache-maven-3.3.9
- export PATH=$HOME/apache-maven-3.3.9/bin:${PATH}
- openssl aes-256-cbc -K $encrypted_5630fbebf057_key -iv $encrypted_5630fbebf057_iv -in .travis/secrets.tar.enc -out .travis/secrets.tar -d
- pushd .travis && tar xfv secrets.tar && popd
- mkdir -p "$HOME/.ssh"
- chmod 700 "$HOME/.ssh"
- mv .travis/id_rsa "$HOME/.ssh/id_rsa"
- chmod 600 "$HOME/.ssh/id_rsa"
- mkdir -p "$HOME/.gpg"
- gpg --batch --import .travis/release-signing-key-82DE7BE82166E84E.gpg
- rm .travis/secrets.tar
- rm .travis/release-signing-key-82DE7BE82166E84E.gpg
install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
before_script: true
script:

View File

@ -0,0 +1,43 @@
#
# Helper functions to run a chatty, long task in the background,
# redirecting the output to file and keep travis happy by regularly
# writing to the log.
#
# This is to workaround the travis log length limit of 4MB
# Solution from http://stackoverflow.com/questions/26082444/how-to-work-around-travis-cis-4mb-output-limit/26082445#26082445
#
# Source this file into the shell script, that needs it.
#
# expected variables
# Name | Example Value
# PING_SLEEP | 30s
# BUILD_OUTPUT | /tmp/build-step-logfile.out
# PING_PID_FILE | /tmp/build-step-ping.pid
touch $BUILD_OUTPUT
dump_output() {
echo Tailing the last 100 lines of output:
tail -100 $BUILD_OUTPUT
}
kill_ping() {
if [ -e $PING_PID_FILE ]; then
PING_LOOP_PID=$(cat $PING_PID_FILE)
kill $PING_LOOP_PID
rm $PING_PID_FILE
fi
}
error_handler() {
kill_ping
echo ERROR: An error was encountered with the build.
dump_output
exit 1
}
# If an error occurs, run our error handler to output a tail of the build
trap 'error_handler' ERR
# Set up a repeating loop to send some output to Travis.
bash -c "while true; do echo \$(date) - building ...; sleep $PING_SLEEP; done" &
PING_LOOP_PID=$!
echo "$PING_LOOP_PID" > $PING_PID_FILE

View File

@ -5,11 +5,19 @@ VERSION=$(mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non
echo "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}"
if [[ "$VERSION" != *-SNAPSHOT && "$TRAVIS_TAG" != "" ]]; then
# release build
mvn deploy -Possrh,pmd-release -B -V
else
elif [[ "$VERSION" == *-SNAPSHOT ]]; then
# snapshot build
mvn deploy -Possrh -B -V
else
# other build. Can happen during release: the commit with a non snapshot version is built, but not from the tag.
mvn verify -Possrh -B -V
# we stop here - no need to execute further steps
exit 0
fi
bash .travis/build-site.sh
# create pmd-doc archive
@ -33,6 +41,6 @@ fi
if [[ "$VERSION" == *-SNAPSHOT && "$TRAVIS_BRANCH" == "master" ]]; then
# only do a clean build for sonar, if we are executing a snapshot build, otherwise we can't reuse the build from above for the release
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar -Dsonar.host.url=https://sonarqube.com -Dsonar.login=${SONAR_TOKEN} -B -V
bash .travis/build-sonar.sh
fi

View File

@ -1,41 +1,11 @@
#!/bin/bash
set -ev
# Do not log the output, to avoid the travis log length limit of 4MB
# Solution from http://stackoverflow.com/questions/26082444/how-to-work-around-travis-cis-4mb-output-limit/26082445#26082445
export PING_SLEEP=30s
export BUILD_OUTPUT=/tmp/build-site.out
export PING_PID_FILE=/tmp/build-site-ping.pid
touch $BUILD_OUTPUT
dump_output() {
echo Tailing the last 500 lines of output:
tail -500 $BUILD_OUTPUT
}
kill_ping() {
if [ -e $PING_PID_FILE ]; then
PING_LOOP_PID=$(cat $PING_PID_FILE)
kill $PING_LOOP_PID
rm $PING_PID_FILE
fi
}
error_handler() {
kill_ping
echo ERROR: An error was encountered with the build.
dump_output
exit 1
}
# If an error occurs, run our error handler to output a tail of the build
trap 'error_handler' ERR
# Set up a repeating loop to send some output to Travis.
bash -c "while true; do echo \$(date) - building ...; sleep $PING_SLEEP; done" &
PING_LOOP_PID=$!
echo "$PING_LOOP_PID" > $PING_PID_FILE
source .travis/background-job-funcs.sh
# Run the build, redirect output into the file
mvn site site:stage -Psite -B -V >> $BUILD_OUTPUT 2>&1

18
.travis/build-sonar.sh Normal file
View File

@ -0,0 +1,18 @@
#!/bin/bash
set -ev
export PING_SLEEP=30s
export BUILD_OUTPUT=/tmp/build-sonar.out
export PING_PID_FILE=/tmp/build-sonar-ping.pid
source .travis/background-job-funcs.sh
# Run the build, redirect output into the file
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar -Dsonar.host.url=https://sonarqube.com -Dsonar.login=${SONAR_TOKEN} -B -V >> $BUILD_OUTPUT 2>&1
# The build finished without returning an error so dump a tail of the output
dump_output
# nicely terminate the ping output loop
kill_ping

19
.travis/setup-secrets.sh Normal file
View File

@ -0,0 +1,19 @@
#!/bin/bash
set -ev
if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "${TRAVIS_SECURE_ENV_VARS}" != "true" ]; then
echo "Not setting up secrets (TRAVIS_PULL_REQUEST=${TRAVIS_PULL_REQUEST} TRAVIS_SECURE_ENV_VARS=${TRAVIS_SECURE_ENV_VARS})."
exit 0
fi
openssl aes-256-cbc -K $encrypted_5630fbebf057_key -iv $encrypted_5630fbebf057_iv -in .travis/secrets.tar.enc -out .travis/secrets.tar -d
pushd .travis && tar xfv secrets.tar && popd
mkdir -p "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
mv .travis/id_rsa "$HOME/.ssh/id_rsa"
chmod 600 "$HOME/.ssh/id_rsa"
mkdir -p "$HOME/.gpg"
gpg --batch --import .travis/release-signing-key-82DE7BE82166E84E.gpg
rm .travis/secrets.tar
rm .travis/release-signing-key-82DE7BE82166E84E.gpg

View File

@ -57,6 +57,8 @@ import com.google.common.collect.ListMultimap;
*/
public class ApexCRUDViolationRule extends AbstractApexRule {
private static final Pattern VOID_OR_STRING_PATTERN = Pattern.compile("^(string|void)$", Pattern.CASE_INSENSITIVE);
private static final Pattern SELECT_FROM_PATTERN = Pattern.compile("^[\\S|\\s]+?FROM[\\s]+?(\\S+)",
Pattern.CASE_INSENSITIVE);
private final HashMap<String, String> varToTypeMapping = new HashMap<>();
private final ListMultimap<String, String> typeToDMLOperationMapping = ArrayListMultimap.create();
@ -480,6 +482,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
private void checkForAccessibility(final ASTSoqlExpression node, Object data) {
final boolean isCount = node.getNode().getCanonicalQuery().startsWith("SELECT COUNT()");
final String typeFromSOQL = getTypeFromSOQLQuery(node);
final HashSet<ASTMethodCallExpression> prevCalls = getPreviousMethodCalls(node);
for (ASTMethodCallExpression prevCall : prevCalls) {
@ -510,7 +513,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
.append(":").append(type);
if (!isGetter) {
validateCRUDCheckPresent(node, data, ANY, typeCheck.toString());
validateCRUDCheckPresent(node, data, ANY, typeFromSOQL == null ? typeCheck.toString() : typeFromSOQL);
}
}
@ -523,7 +526,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
if (varToTypeMapping.containsKey(variableWithClass)) {
String type = varToTypeMapping.get(variableWithClass);
if (!isGetter) {
validateCRUDCheckPresent(node, data, ANY, type);
validateCRUDCheckPresent(node, data, ANY, typeFromSOQL == null ? type : typeFromSOQL);
}
}
}
@ -533,11 +536,23 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
final ASTReturnStatement returnStatement = node.getFirstParentOfType(ASTReturnStatement.class);
if (returnStatement != null) {
if (!isGetter) {
validateCRUDCheckPresent(node, data, ANY, returnType == null ? "" : returnType);
String retType = typeFromSOQL == null ? returnType : typeFromSOQL;
validateCRUDCheckPresent(node, data, ANY, retType == null ? "" : retType);
}
}
}
private String getTypeFromSOQLQuery(final ASTSoqlExpression node) {
final String canonQuery = node.getNode().getCanonicalQuery();
Matcher m = SELECT_FROM_PATTERN.matcher(canonQuery);
while (m.find()) {
return new StringBuffer().append(node.getNode().getDefiningType().getApexName()).append(":")
.append(m.group(1)).toString();
}
return null;
}
private String getReturnType(final ASTMethod method) {
return new StringBuilder().append(method.getNode().getDefiningType().getApexName()).append(":")
.append(method.getNode().getMethodInfo().getEmitSignature().getReturnType().getApexName()).toString();

View File

@ -2,6 +2,37 @@
<test-data>
<test-code>
<description>Proper CRUD checks for Aggregate Result</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public void justGiveMeFoo() {
if (Opportunity.sObjectType.getDescribe().isAccessible()) {
return;
}
AggregateResult[] test = [SELECT Id FROM Opportunity];
}
}
]]></code>
</test-code>
<test-code>
<description>Proper CRUD checks for Aggregate Result return</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public AggregateResult[] justGiveMeFoo() {
if (Opportunity.sObjectType.getDescribe().isAccessible()) {
return null;
}
return [SELECT Id FROM Opportunity];
}
}
]]></code>
</test-code>
<test-code>
<description>Not a getter</description>
<expected-problems>1</expected-problems>
@ -688,7 +719,7 @@ public class Foo {
}
]]></code>
</test-code>
<test-code>
<description>Field detection</description>
<expected-problems>1</expected-problems>
@ -703,5 +734,4 @@ public class MyProfilePageController {
]]></code>
</test-code>
</test-data>

View File

@ -235,6 +235,7 @@ public class VfUnescapeElRule extends AbstractVfRule {
case "$remoteaction":
return true;
default:
}
}
@ -385,9 +386,9 @@ public class VfUnescapeElRule extends AbstractVfRule {
case "id":
case "size":
case "caseNumber":
return true;
return true;
default:
}
}
if (child instanceof ASTDotExpression) {

View File

@ -8,7 +8,7 @@
<name>PMD</name>
<description>
PMD is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports Java, JavaScript, Salesforce.com Apex, PLSQL, Apache Velocity, XML, XSL.
PMD is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports Java, JavaScript, Salesforce.com Apex, PLSQL, Salesforce.com Visualforce, Apache Velocity, XML, XSL.
Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code in Java, C, C++, C#, Groovy, PHP, Ruby, Fortran, JavaScript, PLSQL, Apache Velocity, Scala, Objective C, Matlab, Python, Go, Swift and Salesforce.com Apex.
</description>
@ -1039,7 +1039,6 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<module>pmd-java</module>
<module>pmd-javascript</module>
<module>pmd-jsp</module>
<module>pmd-visualforce</module>
<module>pmd-matlab</module>
<module>pmd-objectivec</module>
<module>pmd-perl</module>
@ -1049,6 +1048,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<module>pmd-ruby</module>
<module>pmd-swift</module>
<module>pmd-test</module>
<module>pmd-visualforce</module>
<module>pmd-vm</module>
<module>pmd-xml</module>
</modules>

View File

@ -4,7 +4,8 @@
The PMD team is pleased to announce PMD 5.6.0.
The most significant changes are on analysis performance and a whole new **Apex Security Rule Set**.
The most significant changes are on analysis performance, support for Salesforce's Visualforce language
a whole new **Apex Security Rule Set**.
We have added initial support for **incremental analysis**. The experimental feature allows
PMD to cache analysis results between executions to speed up the analysis for all
@ -29,6 +30,7 @@ making it over 500X faster, and `PreserveStackTrace` which is now 7X faster.
* [New and noteworthy](#New_and_noteworthy)
* [Incremental Analysis](#Incremental_Analysis)
* [Visualforce Support](#Visualforce_support)
* [Apex Security Rule Set](#Apex_Security_Rule_Set)
* [New Rules](#New_Rules)
* [Modified Rules](#Modified_Rules)
@ -41,7 +43,7 @@ making it over 500X faster, and `PreserveStackTrace` which is now 7X faster.
#### Incremental Analysis
PMD now support incremental analysis. Analysis results can be cached and reused between runs.
PMD now supports incremental analysis. Analysis results can be cached and reused between runs.
This allows PMD to skip files without violations that have remained unchanged. In future releases,
we plan to extend this behavior to unchanged files with violations too.
@ -71,6 +73,18 @@ For Ant, a new `cacheLocation` attribute has been added. For instance:
</target>
```
#### Visualforce Support
Salesforce developers rejoice. To out growing Apex support we have added full Visualforce support.
Both CPD and PD are available. So far only a security ruleset is available (`vf-security`).
##### Visualforce Security Rule Set
###### VfUnescapeEl
The rule looks for Expression Language occurances printing unescaped values from the backend. These
could lead to XSS attacks.
#### Apex Security Rule Set
A new ruleset focused on security has been added, consisting of a wide range of rules
@ -410,4 +424,5 @@ For example:
* [#266](https://github.com/pmd/pmd/pull/266): \[java] corrected invalid reporting of LoD violation
* [#268](https://github.com/pmd/pmd/pull/268): \[apex] Support safe escaping via String method
* [#273](https://github.com/pmd/pmd/pull/273): \[apex] Shade jackson on apex
* [#280](https://github.com/pmd/pmd/pull/280): \[apex] Support for Aggregate Result in CRUD rules