(CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description spids:[4]) 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 ops: [Op_DAmp] children: [ (C {(test_when_finished)} {(SQ <restore_base>)}) (C {(rm)} {(-f)} {($ VSub_Name '$base')}) ] ) ] 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 spids:[66]) op: Equal rhs: {($ VSub_Number '$1')} spids: [66] ) ] spids: [66] ) terminator: <Op_Semi ';'> ) (C {(shift)}) (AndOr ops: [Op_DAmp Op_DAmp Op_DAmp Op_DAmp] children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:sha1 spids:[73]) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (ForEach iter_name: i iter_words: [{($ VSub_Name '$pack_objects')}] do_arg_iter: F body: (DoGroup children: [(C {(echo)} {($ VSub_Name '$i')})] spids: [86 94] ) spids: [82 16777215] ) (C {(git)} {(pack-objects)} {(DQ ($ VSub_At '$@'))} {(.git/objects/pack/pack)} ) ] negated: F ) ] ) left_token: <Left_CommandSub '$('> spids: [74 109] ) } spids: [73] ) ] spids: [73] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:pack spids:[114]) op: Equal rhs: {(.git/objects/pack/pack-) ($ VSub_Name '$sha1') (.pack)} spids: [114] ) ] spids: [114] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:idx spids:[122]) op: Equal rhs: {(.git/objects/pack/pack-) ($ VSub_Name '$sha1') (.idx)} spids: [122] ) ] spids: [122] ) (C {(chmod)} {(Lit_Other '+') (w)} {($ VSub_Name '$pack')} {($ VSub_Name '$idx')}) (C {(test_when_finished)} {(SQ <'rm -f "$pack" "$idx"'>)}) ] ) ] 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: F ) ] 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)}) ] )