When (m * m) overflows, the search range is still cut by half if no return, even through the wrong half may be cut. So, the infinite loop is not caused by overflow of (m * m), at least directly. It is instead caused by overflow of indices, i.e., l, r, m. See the example below: (m * m) still overflows, but no infinite loop, just yields wrong answer.

In summary, overflow of (m * m) causes overflow of indices, thus cause infinite loop indirectly. In this sense, the accepted answer is at best incomplete, if not misleading.

I post my multiplication- and division-based implementations in case they may be of help.

class Solution {
public:
int sqrt(int x) {
if(x == 0 || x == 1){
return x;
}
long l = 1, r = x, res;
while(l <= r){
long mid = (l + r)/2;
int m = mid;
if(m * m == x){
return mid;
}else if(m * m > x){
r = mid - 1;
}else{
l = mid + 1;
res = mid;
}
}
return res;
}
};