llvm.org GIT mirror llvm / ac23fcd
[MSan] Make sure variadic function arguments do not overflow __msan_va_arg_tls Turns out that calling a variadic function with too many (e.g. >100 i64's) arguments overflows __msan_va_arg_tls, which leads to smashing other TLS data with function argument shadow values. getShadow() already checks for kParamTLSSize and returns clean shadow if the argument does not fit, so just skip storing argument shadow for such arguments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341525 91177308-0d34-0410-b5e6-96231b3b80d8 Alexander Potapenko 1 year, 1 month ago
7 changed file(s) with 219 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
33173317 assert(A->getType()->isPointerTy());
33183318 Type *RealTy = A->getType()->getPointerElementType();
33193319 uint64_t ArgSize = DL.getTypeAllocSize(RealTy);
3320 Value *ShadowBase =
3321 getShadowPtrForVAArgument(RealTy, IRB, OverflowOffset);
3320 Value *ShadowBase = getShadowPtrForVAArgument(
3321 RealTy, IRB, OverflowOffset, alignTo(ArgSize, 8));
33223322 OverflowOffset += alignTo(ArgSize, 8);
3323 if (!ShadowBase)
3324 continue;
33233325 Value *ShadowPtr, *OriginPtr;
33243326 std::tie(ShadowPtr, OriginPtr) =
33253327 MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), kShadowTLSAlignment,
33363338 Value *ShadowBase;
33373339 switch (AK) {
33383340 case AK_GeneralPurpose:
3339 ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, GpOffset);
3341 ShadowBase =
3342 getShadowPtrForVAArgument(A->getType(), IRB, GpOffset, 8);
33403343 GpOffset += 8;
33413344 break;
33423345 case AK_FloatingPoint:
3343 ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, FpOffset);
3346 ShadowBase =
3347 getShadowPtrForVAArgument(A->getType(), IRB, FpOffset, 16);
33443348 FpOffset += 16;
33453349 break;
33463350 case AK_Memory:
33483352 continue;
33493353 uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
33503354 ShadowBase =
3351 getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset);
3355 getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset, 8);
33523356 OverflowOffset += alignTo(ArgSize, 8);
33533357 }
33543358 // Take fixed arguments into account for GpOffset and FpOffset,
33553359 // but don't actually store shadows for them.
33563360 if (IsFixed)
33573361 continue;
3362 if (!ShadowBase)
3363 continue;
33583364 IRB.CreateAlignedStore(MSV.getShadow(A), ShadowBase,
33593365 kShadowTLSAlignment);
33603366 }
33663372
33673373 /// Compute the shadow address for a given va_arg.
33683374 Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
3369 int ArgOffset) {
3375 unsigned ArgOffset, unsigned ArgSize) {
3376 // Make sure we don't overflow __msan_va_arg_tls.
3377 if (ArgOffset + ArgSize > kParamTLSSize)
3378 return nullptr;
33703379 Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
33713380 Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
33723381 return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
34823491 if (ArgSize < 8)
34833492 VAArgOffset += (8 - ArgSize);
34843493 }
3485 Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset);
3494 Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset, ArgSize);
34863495 VAArgOffset += ArgSize;
34873496 VAArgOffset = alignTo(VAArgOffset, 8);
3497 if (!Base)
3498 continue;
34883499 IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
34893500 }
34903501
34963507
34973508 /// Compute the shadow address for a given va_arg.
34983509 Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
3499 int ArgOffset) {
3510 unsigned ArgOffset, unsigned ArgSize) {
3511 // Make sure we don't overflow __msan_va_arg_tls.
3512 if (ArgOffset + ArgSize > kParamTLSSize)
3513 return nullptr;
35003514 Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
35013515 Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
35023516 return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
36273641 Value *Base;
36283642 switch (AK) {
36293643 case AK_GeneralPurpose:
3630 Base = getShadowPtrForVAArgument(A->getType(), IRB, GrOffset);
3644 Base = getShadowPtrForVAArgument(A->getType(), IRB, GrOffset, 8);
36313645 GrOffset += 8;
36323646 break;
36333647 case AK_FloatingPoint:
3634 Base = getShadowPtrForVAArgument(A->getType(), IRB, VrOffset);
3648 Base = getShadowPtrForVAArgument(A->getType(), IRB, VrOffset, 8);
36353649 VrOffset += 16;
36363650 break;
36373651 case AK_Memory:
36403654 if (IsFixed)
36413655 continue;
36423656 uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
3643 Base = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset);
3657 Base = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset,
3658 alignTo(ArgSize, 8));
36443659 OverflowOffset += alignTo(ArgSize, 8);
36453660 break;
36463661 }
36483663 // bother to actually store a shadow.
36493664 if (IsFixed)
36503665 continue;
3666 if (!Base)
3667 continue;
36513668 IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
36523669 }
36533670 Constant *OverflowSize =
36573674
36583675 /// Compute the shadow address for a given va_arg.
36593676 Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
3660 int ArgOffset) {
3677 unsigned ArgOffset, unsigned ArgSize) {
3678 // Make sure we don't overflow __msan_va_arg_tls.
3679 if (ArgOffset + ArgSize > kParamTLSSize)
3680 return nullptr;
36613681 Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
36623682 Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
36633683 return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
38623882 ArgAlign = 8;
38633883 VAArgOffset = alignTo(VAArgOffset, ArgAlign);
38643884 if (!IsFixed) {
3865 Value *Base = getShadowPtrForVAArgument(RealTy, IRB,
3866 VAArgOffset - VAArgBase);
3867 Value *AShadowPtr, *AOriginPtr;
3868 std::tie(AShadowPtr, AOriginPtr) = MSV.getShadowOriginPtr(
3869 A, IRB, IRB.getInt8Ty(), kShadowTLSAlignment, /*isStore*/ false);
3870
3871 IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr,
3872 kShadowTLSAlignment, ArgSize);
3885 Value *Base = getShadowPtrForVAArgument(
3886 RealTy, IRB, VAArgOffset - VAArgBase, ArgSize);
3887 if (Base) {
3888 Value *AShadowPtr, *AOriginPtr;
3889 std::tie(AShadowPtr, AOriginPtr) =
3890 MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(),
3891 kShadowTLSAlignment, /*isStore*/ false);
3892
3893 IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr,
3894 kShadowTLSAlignment, ArgSize);
3895 }
38733896 }
38743897 VAArgOffset += alignTo(ArgSize, 8);
38753898 } else {
38973920 }
38983921 if (!IsFixed) {
38993922 Base = getShadowPtrForVAArgument(A->getType(), IRB,
3900 VAArgOffset - VAArgBase);
3901 IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
3923 VAArgOffset - VAArgBase, ArgSize);
3924 if (Base)
3925 IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
39023926 }
39033927 VAArgOffset += ArgSize;
39043928 VAArgOffset = alignTo(VAArgOffset, 8);
39163940
39173941 /// Compute the shadow address for a given va_arg.
39183942 Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
3919 int ArgOffset) {
3943 unsigned ArgOffset, unsigned ArgSize) {
3944 // Make sure we don't overflow __msan_va_arg_tls.
3945 if (ArgOffset + ArgSize > kParamTLSSize)
3946 return nullptr;
39203947 Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
39213948 Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
39223949 return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
7373 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 56
7474 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 192
7575 ; CHECK: store {{.*}} 8, {{.*}} @__msan_va_arg_overflow_size_tls
76
77 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
78 ; passed to a variadic function.
79
80 define dso_local i64 @many_args() {
81 entry:
82 %ret = call i64 (i64, ...) @sum(i64 120,
83 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
84 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
85 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
86 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
87 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
88 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
89 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
90 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
91 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
92 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
93 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
94 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
95 )
96 ret i64 %ret
97 }
98
99 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
100 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
101 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
102 declare i64 @sum(i64 %n, ...)
5252 ; CHECK: store i64 0, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @__msan_va_arg_tls, i32 0, i32 0), align 8
5353 ; CHECK: store i64 0, i64* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to i64*), align 8
5454 ; CHECK: store {{.*}} 16, {{.*}} @__msan_va_arg_overflow_size_tls
55
56 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
57 ; passed to a variadic function.
58 define dso_local i64 @many_args() {
59 entry:
60 %ret = call i64 (i64, ...) @sum(i64 120,
61 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
62 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
63 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
64 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
65 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
66 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
67 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
68 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
69 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
70 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
71 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
72 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
73 )
74 ret i64 %ret
75 }
76
77 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
78 ; CHECK-LABEL: @many_args
79 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
80 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
81 declare i64 @sum(i64 %n, ...)
5151 ; CHECK: store i64 0, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @__msan_va_arg_tls, i32 0, i32 0), align 8
5252 ; CHECK: store i64 0, i64* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to i64*), align 8
5353 ; CHECK: store {{.*}} 16, {{.*}} @__msan_va_arg_overflow_size_tls
54
55 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
56 ; passed to a variadic function.
57 define dso_local i64 @many_args() {
58 entry:
59 %ret = call i64 (i64, ...) @sum(i64 120,
60 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
61 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
62 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
63 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
64 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
65 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
66 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
67 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
68 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
69 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
70 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
71 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
72 )
73 ret i64 %ret
74 }
75
76 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
77 ; CHECK-LABEL: @many_args
78 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
79 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
80 declare i64 @sum(i64 %n, ...)
110110 ; CHECK: [[SHADOW:%[0-9]+]] = bitcast [4 x i64]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to [4 x i64]*)
111111 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHADOW]], i8* align 8 {{.*}}, i64 32, i1 false)
112112 ; CHECK: store {{.*}} 40, {{.*}} @__msan_va_arg_overflow_size_tls
113
114
115 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
116 ; passed to a variadic function.
117 define dso_local i64 @many_args() {
118 entry:
119 %ret = call i64 (i64, ...) @sum(i64 120,
120 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
121 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
122 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
123 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
124 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
125 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
126 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
127 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
128 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
129 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
130 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
131 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
132 )
133 ret i64 %ret
134 }
135
136 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
137 ; CHECK-LABEL: @many_args
138 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
139 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
140 declare i64 @sum(i64 %n, ...)
9494 ; CHECK: [[SHADOW:%[0-9]+]] = bitcast [4 x i64]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to [4 x i64]*)
9595 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHADOW]], i8* align 8 {{.*}}, i64 32, i1 false)
9696 ; CHECK: store {{.*}} 40, {{.*}} @__msan_va_arg_overflow_size_tls
97
98 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
99 ; passed to a variadic function.
100 define dso_local i64 @many_args() {
101 entry:
102 %ret = call i64 (i64, ...) @sum(i64 120,
103 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
104 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
105 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
106 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
107 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
108 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
109 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
110 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
111 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
112 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
113 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
114 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
115 )
116 ret i64 %ret
117 }
118
119 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
120 ; CHECK-LABEL: @many_args
121 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
122 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
123 declare i64 @sum(i64 %n, ...)
0 ; RUN: opt < %s -msan -msan-check-access-address=0 -S 2>&1 | FileCheck %s
1
2 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
3 ; passed to a variadic function.
4
5 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6 target triple = "x86_64-unknown-linux-gnu"
7
8 define dso_local i64 @many_args() {
9 entry:
10 %ret = call i64 (i64, ...) @sum(i64 120,
11 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
12 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
13 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
14 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
15 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
16 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
17 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
18 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
19 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
20 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
21 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
22 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
23 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
24 )
25 ret i64 %ret
26 }
27
28 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
29 ; CHECK-LABEL: @many_args
30 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
31 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
32 declare i64 @sum(i64 %n, ...)