Files
clang-p2996/compiler-rt/lib/builtins/fp_fixint_impl.inc
Karl-Johan Karlsson 831b509d5f [builtins] Fix signed integer overflows in fp_fixint_impl.inc
When compiling the builtins with the undefined behavior sanitizer and running
testcases you end up with the following warning:

UBSan: fp_fixint_impl.inc:39:42: left shift of 8388608 by 40 places cannot be represented in type 'fixint_t' (aka 'long long')
UBSan: fp_fixint_impl.inc:39:17: signed integer overflow: -1 * -9223372036854775808 cannot be represented in type 'fixint_t' (aka 'long long')

This can be avoided by doing the shift and the multiplication in a matching
unsigned variant of the type.

The added test only trigger the intended signed overflow case when the builtins
are built with -D__SOFTFP__.

This was found in an out of tree target.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D159069
2023-08-31 10:08:15 +02:00

41 lines
1.5 KiB
C

//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements float to integer conversion for the
// compiler-rt library.
//
//===----------------------------------------------------------------------===//
#include "fp_lib.h"
static __inline fixint_t __fixint(fp_t a) {
const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2);
const fixint_t fixint_min = -fixint_max - 1;
// Break a into sign, exponent, significand parts.
const rep_t aRep = toRep(a);
const rep_t aAbs = aRep & absMask;
const fixint_t sign = aRep & signBit ? -1 : 1;
const int exponent = (aAbs >> significandBits) - exponentBias;
const rep_t significand = (aAbs & significandMask) | implicitBit;
// If exponent is negative, the result is zero.
if (exponent < 0)
return 0;
// If the value is too large for the integer type, saturate.
if ((unsigned)exponent >= sizeof(fixint_t) * CHAR_BIT)
return sign == 1 ? fixint_max : fixint_min;
// If 0 <= exponent < significandBits, right shift to get the result.
// Otherwise, shift left.
if (exponent < significandBits)
return sign * (significand >> (significandBits - exponent));
else
return sign * ((fixuint_t)significand << (exponent - significandBits));
}