(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:test_description) op: assign_op.Equal rhs: {(SQ <'paths written by git-apply cannot escape the working tree'>)} spids: [4] ) ] ) (C {<.>} {<'./test-lib.sh'>}) (C {<test_expect_success>} {(SQ <'bump git repo one level down'>)} {(SQ <'\n'> <'\tmkdir inside &&\n'> <'\tmv .git inside/ &&\n'> <'\tcd inside\n'>)} ) (command.ShFunction name: mkpatch_add body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (C {<rm>} {<-f>} { (DQ (braced_var_sub token: <Id.VSub_Number 2> suffix_op: (suffix_op.Unary tok: <Id.VTest_ColonHyphen ':-'> arg_word: {($ Id.VSub_Number '$1')} ) ) ) } ) (command.Simple words: [{<cat>}] redirects: [ (redir op: <Id.Redir_DLessDash '<<-'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 85 stdin_parts: [ <'diff --git a/'> ($ Id.VSub_Number '$1') <' b/'> ($ Id.VSub_Number '$1') <'\n'> <'new file mode 100644\n'> <'index 0000000..53c74cd\n'> <'--- /dev/null\n'> <'+++ b/'> ($ Id.VSub_Number '$1') <'\n'> <'@@ -0,0 +1 @@\n'> <'+evil\n'> ] ) ) ] do_fork: T ) ] ) ] ) ) (command.ShFunction name: mkpatch_del body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (command.Simple words: [{<echo>} {<evil>}] redirects: [ (redir op: <Id.Redir_Great '>'> loc: (redir_loc.Fd fd:1) arg: { (DQ (braced_var_sub token: <Id.VSub_Number 2> suffix_op: (suffix_op.Unary tok: <Id.VTest_ColonHyphen ':-'> arg_word: {($ Id.VSub_Number '$1')} ) ) ) } ) ] do_fork: T ) (command.Simple words: [{<cat>}] redirects: [ (redir op: <Id.Redir_DLessDash '<<-'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 132 stdin_parts: [ <'diff --git a/'> ($ Id.VSub_Number '$1') <' b/'> ($ Id.VSub_Number '$1') <'\n'> <'deleted file mode 100644\n'> <'index 53c74cd..0000000\n'> <'--- a/'> ($ Id.VSub_Number '$1') <'\n'> <'+++ /dev/null\n'> <'@@ -1 +0,0 @@\n'> <'-evil\n'> ] ) ) ] do_fork: T ) ] ) ] ) ) (command.ShFunction name: mkpatch_symlink body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (C {<rm>} {<-f>} {(DQ ($ Id.VSub_Number '$1'))}) (command.Simple words: [{<cat>}] redirects: [ (redir op: <Id.Redir_DLessDash '<<-'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {<EOF>} here_end_span_id: 204 stdin_parts: [ <'diff --git a/'> ($ Id.VSub_Number '$1') <' b/'> ($ Id.VSub_Number '$1') <'\n'> <'new file mode 120000\n'> <'index 0000000..'> (command_sub left_token: <Id.Left_DollarParen '$('> child: (command.Pipeline children: [ (C {<printf>} {(DQ <'%s'>)} {(DQ ($ Id.VSub_Number '$2'))}) (C {<git>} {<hash-object>} {<--stdin>}) ] negated: F ) ) <'\n'> <'--- /dev/null\n'> <'+++ b/'> ($ Id.VSub_Number '$1') <'\n'> <'@@ -0,0 +1 @@\n'> <'+'> ($ Id.VSub_Number '$2') <'\n'> <Id.Lit_BadBackslash '\\'> <' No newline at end of file\n'> ] ) ) ] do_fork: T ) ] ) ] ) ) (C {<test_expect_success>} {(SQ <'cannot create file containing ..'>)} { (SQ <'\n'> <'\tmkpatch_add ../foo >patch &&\n'> <'\ttest_must_fail git apply patch &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {(SQ <'can create file containing .. with --unsafe-paths'>)} { (SQ <'\n'> <'\tmkpatch_add ../foo >patch &&\n'> <'\tgit apply --unsafe-paths patch &&\n'> <'\ttest_path_is_file ../foo\n'> ) } ) (C {<test_expect_success>} {(SQ <'cannot create file containing .. (index)'>)} { (SQ <'\n'> <'\tmkpatch_add ../foo >patch &&\n'> <'\ttest_must_fail git apply --index patch &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {(SQ <'cannot create file containing .. with --unsafe-paths (index)'>)} { (SQ <'\n'> <'\tmkpatch_add ../foo >patch &&\n'> <'\ttest_must_fail git apply --index --unsafe-paths patch &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {(SQ <'cannot delete file containing ..'>)} { (SQ <'\n'> <'\tmkpatch_del ../foo >patch &&\n'> <'\ttest_must_fail git apply patch &&\n'> <'\ttest_path_is_file ../foo\n'> ) } ) (C {<test_expect_success>} {(SQ <'can delete file containing .. with --unsafe-paths'>)} { (SQ <'\n'> <'\tmkpatch_del ../foo >patch &&\n'> <'\tgit apply --unsafe-paths patch &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {(SQ <'cannot delete file containing .. (index)'>)} { (SQ <'\n'> <'\tmkpatch_del ../foo >patch &&\n'> <'\ttest_must_fail git apply --index patch &&\n'> <'\ttest_path_is_file ../foo\n'> ) } ) (C {<test_expect_success>} {<SYMLINKS>} {(SQ <'symlink escape via ..'>)} { (SQ <'\n'> <'\t{\n'> <'\t\tmkpatch_symlink tmp .. &&\n'> <'\t\tmkpatch_add tmp/foo ../foo\n'> <'\t} >patch &&\n'> <'\ttest_must_fail git apply patch &&\n'> <'\ttest_path_is_missing tmp &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {<SYMLINKS>} {(SQ <'symlink escape via .. (index)'>)} { (SQ <'\n'> <'\t{\n'> <'\t\tmkpatch_symlink tmp .. &&\n'> <'\t\tmkpatch_add tmp/foo ../foo\n'> <'\t} >patch &&\n'> <'\ttest_must_fail git apply --index patch &&\n'> <'\ttest_path_is_missing tmp &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {<SYMLINKS>} {(SQ <'symlink escape via absolute path'>)} { (SQ <'\n'> <'\t{\n'> <'\t\tmkpatch_symlink tmp "$(pwd)" &&\n'> <'\t\tmkpatch_add tmp/foo ../foo\n'> <'\t} >patch &&\n'> <'\ttest_must_fail git apply patch &&\n'> <'\ttest_path_is_missing tmp &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_expect_success>} {<SYMLINKS>} {(SQ <'symlink escape via absolute path (index)'>)} { (SQ <'\n'> <'\t{\n'> <'\t\tmkpatch_symlink tmp "$(pwd)" &&\n'> <'\t\tmkpatch_add tmp/foo ../foo\n'> <'\t} >patch &&\n'> <'\ttest_must_fail git apply --index patch &&\n'> <'\ttest_path_is_missing tmp &&\n'> <'\ttest_path_is_missing ../foo\n'> ) } ) (C {<test_done>}) ] )