@@ -197,9 +197,19 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
197197 const Pointer &A = getParam<Pointer>(Frame, 0 );
198198 const Pointer &B = getParam<Pointer>(Frame, 1 );
199199
200- if (ID == Builtin::BIstrcmp)
200+ if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp )
201201 diagnoseNonConstexprBuiltin (S, OpPC, ID);
202202
203+ uint64_t Limit = ~static_cast <uint64_t >(0 );
204+ if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp)
205+ Limit = peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )))
206+ .getZExtValue ();
207+
208+ if (Limit == 0 ) {
209+ pushInteger (S, 0 , Call->getType ());
210+ return true ;
211+ }
212+
203213 if (!CheckLive (S, OpPC, A, AK_Read) || !CheckLive (S, OpPC, B, AK_Read))
204214 return false ;
205215
@@ -212,7 +222,11 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
212222 unsigned IndexA = A.getIndex ();
213223 unsigned IndexB = B.getIndex ();
214224 int32_t Result = 0 ;
215- for (;; ++IndexA, ++IndexB) {
225+ uint64_t Steps = 0 ;
226+ for (;; ++IndexA, ++IndexB, ++Steps) {
227+
228+ if (Steps >= Limit)
229+ break ;
216230 const Pointer &PA = A.atIndex (IndexA);
217231 const Pointer &PB = B.atIndex (IndexB);
218232 if (!CheckRange (S, OpPC, PA, AK_Read) ||
@@ -1873,6 +1887,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
18731887 break ;
18741888 case Builtin::BI__builtin_strcmp:
18751889 case Builtin::BIstrcmp:
1890+ case Builtin::BI__builtin_strncmp:
1891+ case Builtin::BIstrncmp:
18761892 if (!interp__builtin_strcmp (S, OpPC, Frame, F, Call))
18771893 return false ;
18781894 break ;
0 commit comments