Permalink
Browse files

[FIXED JENKINS-43404] Escape/unescape strings being evaluated

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 efc64bee6b98a5e1693a990b3203fc0a727bdb1b
@@ -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
@@ -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
@@ -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) + '"""';
}
}

@@ -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
@@ -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))
}
}
@@ -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
@@ -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) {
@@ -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)))
@@ -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
@@ -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))
}
}
@@ -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 {
@@ -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.