Skip to content

Commit

Permalink
[FIXED JENKINS-43404] Escape/unescape strings being evaluated
Browse files Browse the repository at this point in the history
Not doing this resulted in unescaped double quotes and therefore
errors, so let's make sure we always escape strings when they're
passed in to be evaluated and unescape them after the evaluation.
  • Loading branch information
abayer committed Apr 6, 2017
1 parent 863bcdc commit efc64be
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 8 deletions.
Expand Up @@ -29,6 +29,7 @@ import com.google.common.cache.CacheBuilder
import com.google.common.cache.CacheLoader
import com.google.common.cache.LoadingCache;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import groovy.json.StringEscapeUtils
import hudson.ExtensionList
import hudson.model.Describable
import hudson.model.Descriptor
Expand Down Expand Up @@ -68,7 +69,6 @@ import org.jenkinsci.plugins.workflow.graphanalysis.LinearBlockHoppingScanner
import org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode
import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode
import org.jenkinsci.plugins.workflow.graph.FlowNode
import org.jenkinsci.plugins.workflow.job.WorkflowJob
import org.jenkinsci.plugins.workflow.job.WorkflowRun
import org.jenkinsci.plugins.workflow.steps.StepDescriptor
import org.jenkinsci.plugins.workflow.support.steps.StageStep
Expand Down Expand Up @@ -319,9 +319,9 @@ public class Utils {
String toEval = s ?: ""
if (!toEval.startsWith('"') || !toEval.endsWith('"')) {
if (toEval.indexOf('\n') == -1) {
toEval = '"' + toEval + '"';
toEval = '"' + StringEscapeUtils.escapeJava(toEval) + '"';
} else {
toEval = '"""' + toEval + '"""';
toEval = '"""' + StringEscapeUtils.escapeJava(toEval) + '"""';
}
}

Expand Down
Expand Up @@ -24,6 +24,7 @@
package org.jenkinsci.plugins.pipeline.modeldefinition.model

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import groovy.json.StringEscapeUtils
import hudson.EnvVars
import hudson.model.Run
import hudson.model.TaskListener
Expand Down Expand Up @@ -258,6 +259,6 @@ public class Environment implements Serializable {
String toRun = Utils.prepareForEvalToString(script)
SecureGroovyScript toExec = new SecureGroovyScript(toRun, true)
.configuring(ApprovalContext.create().withCurrentUser())
return toExec.evaluate(this.class.getClassLoader(), binding)
return StringEscapeUtils.unescapeJava((String)toExec.evaluate(this.class.getClassLoader(), binding))
}
}
Expand Up @@ -25,6 +25,7 @@ package org.jenkinsci.plugins.pipeline.modeldefinition

import com.cloudbees.groovy.cps.NonCPS
import com.cloudbees.groovy.cps.impl.CpsClosure
import groovy.json.StringEscapeUtils
import hudson.FilePath
import hudson.Launcher
import hudson.model.Result
Expand Down Expand Up @@ -214,7 +215,7 @@ public class ModelInterpreter implements Serializable {
for (int i = 0; i < envVars.size(); i++) {
// Evaluate to deal with any as-of-yet unresolved expressions.
String toEval = Utils.prepareForEvalToString(envVars.get(i))
evaledEnv.add((String)script.evaluate(toEval))
evaledEnv.add(StringEscapeUtils.unescapeJava((String)script.evaluate(toEval)))
}
return {
script.withEnv(evaledEnv) {
Expand Down Expand Up @@ -271,7 +272,7 @@ public class ModelInterpreter implements Serializable {
for (int i = 0; i < varsAndIds.size(); i++) {
String key = varsAndIds.get(i)?.get(0)
if (key != null) {
String id = (String)script.evaluate(Utils.prepareForEvalToString(varsAndIds.get(i)?.get(1)))
String id = StringEscapeUtils.unescapeJava((String)script.evaluate(Utils.prepareForEvalToString(varsAndIds.get(i)?.get(1))))

CredentialsBindingHandler handler = CredentialsBindingHandler.forId(id, currentBuild.rawBuild);
creds.put(key, new CredentialWrapper(id, handler.getWithCredentialsParameters(id)))
Expand Down
Expand Up @@ -25,6 +25,7 @@

package org.jenkinsci.plugins.pipeline.modeldefinition.when.impl

import groovy.json.StringEscapeUtils
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
import org.jenkinsci.plugins.pipeline.modeldefinition.when.DeclarativeStageConditionalScript
import org.jenkinsci.plugins.workflow.cps.CpsScript
Expand All @@ -37,8 +38,8 @@ class EnvironmentConditionalScript extends DeclarativeStageConditionalScript<Env

@Override
public boolean evaluate() {
String n = (String)script.evaluate(Utils.prepareForEvalToString(describable.getName()))
String v = (String)script.evaluate(Utils.prepareForEvalToString(describable.getValue()))
String n = StringEscapeUtils.unescapeJava((String)script.evaluate(Utils.prepareForEvalToString(describable.getName())))
String v = StringEscapeUtils.unescapeJava((String)script.evaluate(Utils.prepareForEvalToString(describable.getValue())))
return describable.environmentMatches(v, (String)script.getProperty("env").getProperty(n))
}
}
Expand Up @@ -116,6 +116,15 @@ public void envDotCrossRef() throws Exception {
.go();
}

@Issue("JENKINS-43404")
@Test
public void envQuotesInQuotes() throws Exception {
expect("envQuotesInQuotes")
.logContains("[Pipeline] { (foo)",
"GRADLE_OPTIONS is --no-daemon --rerun-tasks -PBUILD_NUMBER=1 -PBRANCH=\"master\"")
.go();
}

@Issue("JENKINS-41890")
@Test
public void environmentWithWorkspace() throws Exception {
Expand Down
@@ -0,0 +1,45 @@
/*
* The MIT License
*
* Copyright (c) 2017, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

pipeline {
agent any

environment {
// Regrettably needed since GitSampleRepoRule doesn't set BRANCH_NAME.
BRANCH_NAME = "master"

GRADLE_OPTIONS = "--no-daemon --rerun-tasks -PBUILD_NUMBER=${env.BUILD_NUMBER} -PBRANCH=\"${env.BRANCH_NAME}\""
}

stages {
stage("foo") {
steps {
echo "GRADLE_OPTIONS is ${env.GRADLE_OPTIONS}"
}
}
}
}



0 comments on commit efc64be

Please sign in to comment.