As Mark Dickinson mentioned in the comment, math libraries tend to provide a hypot function.
The wikipedia article actually addresses the overflow/underflow issue.
https://en.wikipedia.org/wiki/Hypot
From the article:
The difficulty with the naive implementation is that x2 or y2 may overflow or underflow, unless the intermediate result is computed with extended precision. A common implementation technique is to exchange the values, if necessary, so that |x| ≥ |y|, and then use the equivalent form:

The computation of y/x cannot overflow. If y/x underflows, the final result is equal to |x|, which is correct within the precision of the calculation. The square root is computed of a value between 1 and 2. Finally, the multiplication by |x| cannot underflow, and overflows only when the result is too large to represent.