From 0849d583f33db1f8dc75d5fbd7d2f517fe932c64 Mon Sep 17 00:00:00 2001 From: Paolo Di Tommaso Date: Mon, 6 Dec 2021 18:02:58 +0100 Subject: [PATCH] Improve paths validation --- .../src/main/nextflow/file/FileHelper.groovy | 6 +++++- .../src/main/nextflow/util/Escape.groovy | 9 +++++++++ .../test/nextflow/file/FileHelperTest.groovy | 20 ++++++++++++++++++- .../src/test/nextflow/util/EscapeTest.groovy | 13 ++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/modules/nf-commons/src/main/nextflow/file/FileHelper.groovy b/modules/nf-commons/src/main/nextflow/file/FileHelper.groovy index b782ffb403..4b9812b2b8 100644 --- a/modules/nf-commons/src/main/nextflow/file/FileHelper.groovy +++ b/modules/nf-commons/src/main/nextflow/file/FileHelper.groovy @@ -249,6 +249,10 @@ class FileHelper { static Path asPath( String str ) { if( !str ) throw new IllegalArgumentException("Path string cannot be empty") + if( str != Bolts.leftTrim(str) ) + throw new IllegalArgumentException("Path string cannot start with blank or a special characters -- Offending path: '${Escape.blanks(str)}'") + if( str != Bolts.rightTrim(str) ) + throw new IllegalArgumentException("Path string cannot ends with blank or a special characters -- Offending path: '${Escape.blanks(str)}'") if( !str.contains(':/') ) { return Paths.get(str) @@ -267,7 +271,7 @@ class FileHelper { return result } - asPath(toPathURI(str)) + return asPath(toPathURI(str)) } static private Map PLUGINS_MAP = [s3:'nf-amazon', gs:'nf-google', az:'nf-azure'] diff --git a/modules/nf-commons/src/main/nextflow/util/Escape.groovy b/modules/nf-commons/src/main/nextflow/util/Escape.groovy index a66f4983f6..08a5c3eca4 100644 --- a/modules/nf-commons/src/main/nextflow/util/Escape.groovy +++ b/modules/nf-commons/src/main/nextflow/util/Escape.groovy @@ -95,4 +95,13 @@ class Escape { loc = loc.substring(0,loc.length()-1) return prefix + path(loc) } + + static String blanks(String str) { + str + .replaceAll('\n',/\\n/) + .replaceAll('\t',/\\t/) + .replaceAll('\r',/\\r/) + .replaceAll('\f',/\\f/) + + } } diff --git a/modules/nf-commons/src/test/nextflow/file/FileHelperTest.groovy b/modules/nf-commons/src/test/nextflow/file/FileHelperTest.groovy index 42e11b7cf3..6e3054fae1 100644 --- a/modules/nf-commons/src/test/nextflow/file/FileHelperTest.groovy +++ b/modules/nf-commons/src/test/nextflow/file/FileHelperTest.groovy @@ -61,8 +61,26 @@ class FileHelperTest extends Specification { when: FileHelper.asPath('file://some/file.txt') then: - thrown(IllegalArgumentException) + def e = thrown(IllegalArgumentException) + e.message == 'Malformed file URI: file://some/file.txt -- It must start either with a `file:/` or `file:///` prefix' + when: + FileHelper.asPath('') + then: + e = thrown(IllegalArgumentException) + e.message == 'Path string cannot be empty' + + when: + FileHelper.asPath('\n/some/file.txt') + then: + e = thrown(IllegalArgumentException) + e.message == "Path string cannot start with blank or a special characters -- Offending path: '\\n/some/file.txt'" + + when: + FileHelper.asPath('/some/file.txt\n') + then: + e = thrown(IllegalArgumentException) + e.message == "Path string cannot ends with blank or a special characters -- Offending path: '/some/file.txt\\n'" } def 'should strip query params from http files' () { diff --git a/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy b/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy index df851a0d51..f5a0510b4c 100644 --- a/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy +++ b/modules/nf-commons/src/test/nextflow/util/EscapeTest.groovy @@ -20,6 +20,7 @@ package nextflow.util import java.nio.file.Paths import spock.lang.Specification +import spock.lang.Unroll /** * @@ -82,4 +83,16 @@ class EscapeTest extends Specification { Escape.cli('nextflow','--foo','a[!b-c]') == "nextflow --foo 'a[!b-c]'" } + @Unroll + def 'should escape blanks' () { + expect: + Escape.blanks(STR) == EXPECT + where: + STR | EXPECT + 'foo ' | 'foo ' + 'foo\n' | 'foo\\n' + 'foo\t' | 'foo\\t' + 'foo\f' | 'foo\\f' + 'foo\r' | 'foo\\r' + } }