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