Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

parisc: avoid undefined shift in cnv_float.h

The attached change fixes a float conversion problem found running the
GCC testsuite with GCC configured with --with-arch=2.0.

The actual problem occurs for an exponent value of 63. This is the
maximum exponent value that can be passed. This causes a left shift by
32 in the else hunk of the macro. This causes undefined behavior and the
wrong value is returned for dresultB. The fix is the check "exponent <=
62". If the exponent is 63, dresultB is set to 0. The patch also
optimizes the operation a bit by copying "Sall(sgl_value) <<
SGL_EXP_LENGTH" to val, so that sgl_value is not modified.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

John David Anglin and committed by
Helge Deller
cabd91c3 d287b875

+5 -6
+5 -6
arch/parisc/math-emu/cnv_float.h
··· 347 347 Sgl_isinexact_to_fix(sgl_value,exponent) 348 348 349 349 #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ 350 - {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ 350 + {unsigned int val = Sall(sgl_value) << SGL_EXP_LENGTH; \ 351 351 if (exponent <= 31) { \ 352 - Dintp1(dresultA) = 0; \ 353 - Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ 352 + Dintp1(dresultA) = 0; \ 353 + Dintp2(dresultB) = val >> (31 - exponent); \ 354 354 } \ 355 355 else { \ 356 - Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ 357 - Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ 356 + Dintp1(dresultA) = val >> (63 - exponent); \ 357 + Dintp2(dresultB) = exponent <= 62 ? val << (exponent - 31) : 0; \ 358 358 } \ 359 - Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \ 360 359 } 361 360 362 361 #define Duint_setzero(dresultA,dresultB) \