(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(SQ <"bounds-checking of access to mmapped on-disk file formats">)}
          spids: [4]
        )
      ]
      spids: [4]
    )
    (C {(.)} {(./test-lib.sh)})
    (FuncDef
      name: clear_base
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (C {(test_when_finished)} {(SQ <restore_base>)})
                (C {(rm)} {(-f)} {($ VSub_Name "$base")})
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [19]
        )
      spids: [14 18]
    )
    (FuncDef
      name: restore_base
      body: 
        (BraceGroup
          children: [(C {(cp)} {(base-backup/) (Lit_Other "*")} {(.git/objects/pack/)})]
          spids: [45]
        )
      spids: [40 44]
    )
    (FuncDef
      name: do_pack
      body: 
        (BraceGroup
          children: [
            (Sentence
              child: 
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:pack_objects)
                      op: Equal
                      rhs: {($ VSub_Number "$1")}
                      spids: [66]
                    )
                  ]
                  spids: [66]
                )
              terminator: <Op_Semi ";">
            )
            (C {(shift)})
            (AndOr
              children: [
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:sha1)
                      op: Equal
                      rhs: 
                        {
                          (CommandSubPart
                            command_list: 
                              (CommandList
                                children: [
                                  (Pipeline
                                    children: [
                                      (ForEach
                                        iter_name: i
                                        iter_words: [{($ VSub_Name "$pack_objects")}]
                                        do_arg_iter: False
                                        body: 
                                          (DoGroup
                                            children: [(C {(echo)} {($ VSub_Name "$i")})]
                                            spids: [86 94]
                                          )
                                        spids: [82 -1]
                                      )
                                      (C {(git)} {(pack-objects)} {(DQ ($ VSub_At "$@"))} 
                                        {(.git/objects/pack/pack)}
                                      )
                                    ]
                                    negated: False
                                  )
                                ]
                              )
                            left_token: <Left_CommandSub "$(">
                            spids: [74 109]
                          )
                        }
                      spids: [73]
                    )
                  ]
                  spids: [73]
                )
                (AndOr
                  children: [
                    (Assignment
                      keyword: Assign_None
                      pairs: [
                        (assign_pair
                          lhs: (LhsName name:pack)
                          op: Equal
                          rhs: {(.git/objects/pack/pack-) ($ VSub_Name "$sha1") (.pack)}
                          spids: [114]
                        )
                      ]
                      spids: [114]
                    )
                    (AndOr
                      children: [
                        (Assignment
                          keyword: Assign_None
                          pairs: [
                            (assign_pair
                              lhs: (LhsName name:idx)
                              op: Equal
                              rhs: {(.git/objects/pack/pack-) ($ VSub_Name "$sha1") (.idx)}
                              spids: [122]
                            )
                          ]
                          spids: [122]
                        )
                        (AndOr
                          children: [
                            (C {(chmod)} {(Lit_Other "+") (w)} {($ VSub_Name "$pack")} 
                              {($ VSub_Name "$idx")}
                            )
                            (C {(test_when_finished)} {(SQ <"rm -f \"$pack\" \"$idx\"">)})
                          ]
                          op_id: Op_DAmp
                        )
                      ]
                      op_id: Op_DAmp
                    )
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [63]
        )
      spids: [58 62]
    )
    (FuncDef
      name: munge
      body: 
        (BraceGroup
          children: [
            (Pipeline
              children: [
                (C {(printf)} {(DQ ($ VSub_Number "$3"))})
                (C {(dd)} {(Lit_VarLike "of=") (DQ ($ VSub_Number "$1"))} {(Lit_VarLike "bs=") (1)} 
                  {(Lit_VarLike "conv=") (notrunc)} {(Lit_VarLike "seek=") ($ VSub_Number "$2")}
                )
              ]
              negated: False
            )
          ]
          spids: [156]
        )
      spids: [151 155]
    )
    (FuncDef
      name: ofs_table
      body: 
        (BraceGroup
          children: [
            (C {(echo)} 
              {
                (ArithSubPart
                  anode: 
                    (ArithBinary
                      op_id: Arith_Plus
                      left: 
                        (ArithBinary
                          op_id: Arith_Plus
                          left: 
                            (ArithBinary
                              op_id: Arith_Plus
                              left: 
                                (ArithBinary
                                  op_id: Arith_Plus
                                  left: (ArithWord w:{(Lit_Digits 4)})
                                  right: (ArithWord w:{(Lit_Digits 4)})
                                )
                              right: 
                                (ArithBinary
                                  op_id: Arith_Star
                                  left: (ArithWord w:{(Lit_Digits 4)})
                                  right: (ArithWord w:{(Lit_Digits 256)})
                                )
                            )
                          right: 
                            (ArithBinary
                              op_id: Arith_Star
                              left: (ArithWord w:{(Lit_Digits 20)})
                              right: (ArithWord w:{($ VSub_Number "$1")})
                            )
                        )
                      right: 
                        (ArithBinary
                          op_id: Arith_Star
                          left: (ArithWord w:{(Lit_Digits 4)})
                          right: (ArithWord w:{($ VSub_Number "$1")})
                        )
                    )
                  spids: [217 242]
                )
              }
            )
          ]
          spids: [212]
        )
      spids: [207 211]
    )
    (FuncDef
      name: extended_table
      body: 
        (BraceGroup
          children: [
            (C {(echo)} 
              {
                (ArithSubPart
                  anode: 
                    (ArithBinary
                      op_id: Arith_Plus
                      left: 
                        (ArithWord
                          w: 
                            {
                              (CommandSubPart
                                command_list: 
                                  (CommandList
                                    children: [(C {(ofs_table)} {(DQ ($ VSub_Number "$1"))})]
                                  )
                                left_token: <Left_CommandSub "$(">
                                spids: [257 263]
                              )
                            }
                        )
                      right: 
                        (ArithBinary
                          op_id: Arith_Star
                          left: (ArithWord w:{(Lit_Digits 4)})
                          right: (ArithWord w:{($ VSub_Number "$1")})
                        )
                    )
                  spids: [256 271]
                )
              }
            )
          ]
          spids: [251]
        )
      spids: [246 250]
    )
    (C {(test_expect_success)} {(SQ <"set up base packfile and variables">)} 
      {
        (SQ <"\n"> <"\t# the hash of this content starts with ff, which\n"> 
          <"\t# makes some later computations much simpler\n"> <"\techo 74 >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit -m base &&\n"> <"\tgit repack -ad &&\n"> 
          <"\tbase=$(echo .git/objects/pack/*) &&\n"> <"\tchmod +w $base &&\n"> <"\tmkdir base-backup &&\n"> <"\tcp $base base-backup/ &&\n"> 
          <"\tobject=$(git rev-parse HEAD:file)\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"pack/index object count mismatch">)} 
      {
        (SQ <"\n"> <"\tdo_pack $object &&\n"> <"\tmunge $pack 8 \"\\377\\0\\0\\0\" &&\n"> 
          <"\tclear_base &&\n"> <"\n"> <"\t# We enumerate the objects from the completely-fine\n"> 
          <"\t# .idx, but notice later that the .pack is bogus\n"> <"\t# and fail to show any data.\n"> <"\techo \"$object missing\" >expect &&\n"> 
          <"\tgit cat-file --batch-all-objects --batch-check >actual &&\n"> <"\ttest_cmp expect actual &&\n"> <"\n"> 
          <"\t# ...and here fail to load the object (without segfaulting),\n"> <"\t# but fallback to a good copy if available.\n"> 
          <"\ttest_must_fail git cat-file blob $object &&\n"> <"\trestore_base &&\n"> <"\tgit cat-file blob $object >actual &&\n"> <"\ttest_cmp file actual &&\n"> 
          <"\n"> <"\t# ...and make sure that index-pack --verify, which has its\n"> 
          <"\t# own reading routines, does not segfault.\n"> <"\ttest_must_fail git index-pack --verify $pack\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"matched bogus object count">)} 
      {
        (SQ <"\n"> <"\tdo_pack $object &&\n"> <"\tmunge $pack 8 \"\\377\\0\\0\\0\" &&\n"> 
          <"\tmunge $idx $((255 * 4)) \"\\377\\0\\0\\0\" &&\n"> <"\tclear_base &&\n"> <"\n"> <"\t# Unlike above, we should notice early that the .idx is totally\n"> 
          <"\t# bogus, and not even enumerate its contents.\n"> <"\t>expect &&\n"> <"\tgit cat-file --batch-all-objects --batch-check >actual &&\n"> 
          <"\ttest_cmp expect actual &&\n"> <"\n"> <"\t# But as before, we can do the same object-access checks.\n"> 
          <"\ttest_must_fail git cat-file blob $object &&\n"> <"\trestore_base &&\n"> <"\tgit cat-file blob $object >actual &&\n"> <"\ttest_cmp file actual &&\n"> 
          <"\n"> <"\ttest_must_fail git index-pack --verify $pack\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bogus object offset (v1)">)} 
      {
        (SQ <"\n"> <"\tdo_pack $object --index-version=1 &&\n"> 
          <"\tmunge $idx $((4 * 256)) \"\\377\\0\\0\\0\" &&\n"> <"\tclear_base &&\n"> <"\ttest_must_fail git cat-file blob $object &&\n"> 
          <"\ttest_must_fail git index-pack --verify $pack\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bogus object offset (v2, no msb)">)} 
      {
        (SQ <"\n"> <"\tdo_pack $object --index-version=2 &&\n"> 
          <"\tmunge $idx $(ofs_table 1) \"\\0\\377\\0\\0\" &&\n"> <"\tclear_base &&\n"> <"\ttest_must_fail git cat-file blob $object &&\n"> 
          <"\ttest_must_fail git index-pack --verify $pack\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bogus offset into v2 extended table">)} 
      {
        (SQ <"\n"> <"\tdo_pack $object --index-version=2 &&\n"> 
          <"\tmunge $idx $(ofs_table 1) \"\\377\\0\\0\\0\" &&\n"> <"\tclear_base &&\n"> <"\ttest_must_fail git cat-file blob $object &&\n"> 
          <"\ttest_must_fail git index-pack --verify $pack\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bogus offset inside v2 extended table">)} 
      {
        (SQ <"\n"> <"\t# We need two objects here, so we can plausibly require\n"> 
          <"\t# an extended table (if the first object were larger than 2^31).\n"> <"\tdo_pack \"$object $(git rev-parse HEAD)\" --index-version=2 &&\n"> <"\n"> 
          <"\t# We have to make extra room for the table, so we cannot\n"> <"\t# just munge in place as usual.\n"> <"\t{\n"> 
          <"\t\tdd if=$idx bs=1 count=$(($(ofs_table 2) + 4)) &&\n"> <"\t\tprintf \"\\200\\0\\0\\0\" &&\n"> <"\t\tprintf \"\\377\\0\\0\\0\\0\\0\\0\\0\" &&\n"> 
          <"\t\tdd if=$idx bs=1 skip=$(extended_table 2)\n"> <"\t} >tmp &&\n"> <"\tmv tmp \"$idx\" &&\n"> <"\tclear_base &&\n"> 
          <"\ttest_must_fail git cat-file blob $object &&\n"> <"\ttest_must_fail git index-pack --verify $pack\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bogus OFS_DELTA in packfile">)} 
      {
        (SQ <"\n"> <"\t# Generate a pack with a delta in it.\n"> 
          <"\tbase=$(test-genrandom foo 3000 | git hash-object --stdin -w) &&\n"> <"\tdelta=$(test-genrandom foo 2000 | git hash-object --stdin -w) &&\n"> 
          <"\tdo_pack \"$base $delta\" --delta-base-offset &&\n"> <"\trm -f .git/objects/??/* &&\n"> <"\n"> <"\t# Double check that we have the delta we expect.\n"> 
          <"\techo $base >expect &&\n"> <"\techo $delta | git cat-file --batch-check=\"%(deltabase)\" >actual &&\n"> 
          <"\ttest_cmp expect actual &&\n"> <"\n"> <"\t# Now corrupt it. We assume the varint size for the delta is small\n"> 
          <"\t# enough to fit in the first byte (which it should be, since it\n"> <"\t# is a pure deletion from the base), and that original ofs_delta\n"> 
          <"\t# takes 2 bytes (which it should, as it should be ~3000).\n"> <"\tofs=$(git show-index <$idx | grep $delta | cut -d\" \" -f1) &&\n"> 
          <"\tmunge $pack $(($ofs + 1)) \"\\177\\377\" &&\n"> <"\ttest_must_fail git cat-file blob $delta >/dev/null\n">
        )
      }
    )
    (C {(test_done)})
  ]
)