From 0d59b4c9ec72a0cfa183694830e2c7477df5d640 Mon Sep 17 00:00:00 2001 From: Paolo Di Tommaso Date: Sat, 11 Mar 2023 09:55:21 +0100 Subject: [PATCH] Fix special chars escaping in container env Signed-off-by: Paolo Di Tommaso --- .../nextflow/processor/TaskProcessor.groovy | 3 ++- .../processor/TaskProcessorTest.groovy | 7 +++++-- .../nf-commons/src/main/nextflow/Const.groovy | 4 ++-- .../src/main/nextflow/util/Escape.groovy | 6 ++++++ .../src/test/nextflow/util/EscapeTest.groovy | 20 +++++++++++++++++++ 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy b/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy index ebfcb220cd..85924e200c 100644 --- a/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy @@ -100,6 +100,7 @@ import nextflow.script.params.ValueOutParam import nextflow.util.ArrayBag import nextflow.util.BlankSeparatedList import nextflow.util.CacheHelper +import nextflow.util.Escape import nextflow.util.LockManager import nextflow.util.LoggerHelper import nextflow.util.TestOnly @@ -1961,7 +1962,7 @@ class TaskProcessor { } else { // escape both wrapping double quotes and the dollar var placeholder - script << /export $name="${value.replace('$','\\$')}"/ + script << /export $name="${Escape.variable(value)}"/ } } script << '' diff --git a/modules/nextflow/src/test/groovy/nextflow/processor/TaskProcessorTest.groovy b/modules/nextflow/src/test/groovy/nextflow/processor/TaskProcessorTest.groovy index 879e51f381..983fda1a59 100644 --- a/modules/nextflow/src/test/groovy/nextflow/processor/TaskProcessorTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/processor/TaskProcessorTest.groovy @@ -779,9 +779,12 @@ class TaskProcessorTest extends Specification { .stripIndent().leftTrim() when: - env = TaskProcessor.bashEnvironmentScript([PATH: 'foo:$PATH'], true) + env = TaskProcessor.bashEnvironmentScript([PATH: 'foo:$PATH', HOLA: 'one|two'], true) then: - env.trim() == 'export PATH="foo:\\$PATH"' + env == '''\ + export PATH="foo:\\$PATH" + export HOLA="one\\|two" + '''.stripIndent() env.charAt(env.size()-1) == '\n' as char when: diff --git a/modules/nf-commons/src/main/nextflow/Const.groovy b/modules/nf-commons/src/main/nextflow/Const.groovy index 7a9fda8143..b9f23fa912 100644 --- a/modules/nf-commons/src/main/nextflow/Const.groovy +++ b/modules/nf-commons/src/main/nextflow/Const.groovy @@ -58,12 +58,12 @@ class Const { /** * The app build time as linux/unix timestamp */ - static public final long APP_TIMESTAMP = 1677436983659 + static public final long APP_TIMESTAMP = 1678524585748 /** * The app build number */ - static public final int APP_BUILDNUM = 5845 + static public final int APP_BUILDNUM = 5846 /** * The app build time string relative to UTC timezone diff --git a/modules/nf-commons/src/main/nextflow/util/Escape.groovy b/modules/nf-commons/src/main/nextflow/util/Escape.groovy index 7d6a7f01b5..8e1372efce 100644 --- a/modules/nf-commons/src/main/nextflow/util/Escape.groovy +++ b/modules/nf-commons/src/main/nextflow/util/Escape.groovy @@ -32,6 +32,8 @@ class Escape { private static List SPECIAL_CHARS = ["'", '"', ' ', '(', ')', '\\', '!', '&', '|', '<', '>', '`', ':'] + private static List VAR_CHARS = ['$', "'", '"', '(', ')', '\\', '&', '|', '<', '>', '`'] + private static List WILDCARDS = ["*", "?", "{", "}", "[", "]", "'", '"', ' ', '(', ')', '\\', '!', '&', '|', '<', '>', '`', ':'] private static String replace(List special, String str, boolean doNotEscapeComplement=false) { @@ -104,4 +106,8 @@ class Escape { .replaceAll('\f',/\\f/) } + + static String variable(String val) { + replace(VAR_CHARS, val, false) + } } diff --git a/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy b/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy index 2b06feb148..c73f3acf10 100644 --- a/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy +++ b/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy @@ -95,4 +95,24 @@ class EscapeTest extends Specification { 'foo\f' | 'foo\\f' 'foo\r' | 'foo\\r' } + + def 'should escape special char' () { + expect: + Escape.variable(STR) == EXPECT + where: + STR | EXPECT + 'foo' | 'foo' + 'foo[x]bar' | 'foo[x]bar' + 'foo ' | 'foo ' + 'foo:bar' | 'foo:bar' + 'foo!bar' | 'foo!bar' + 'foo[!x]bar'| 'foo[!x]bar' + and: + '$foo' | '\\$foo' + 'foo|bar' | 'foo\\|bar' + 'foo`bar' | 'foo\\`bar' + 'foo&bar' | 'foo\\&bar' + 'foo(x)bar' | 'foo\\(x\\)bar' + 'foobar' | 'foo\\bar' + } }