(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>})
  ]
)