s390: Fix undefined behaviour in feenableexcept, fedisableexcept [BZ #30960]
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Testing passed
|
redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
fail
|
Patch failed to apply
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
fail
|
Patch failed to apply
|
Commit Message
If feenableexcept or fedisableexcept gets excepts=FE_INVALID=0x80
as input, we have a signed left shift: 0x80 << 24 which is not
representable as int and thus is undefined behaviour according to
C standard.
This patch casts excepts as unsigned int before shifting, which is
defined.
For me, the observed undefined behaviour is that the shift is done
with "unsigned"-instructions, which is exactly what we want.
Furthermore, I don't get any exception-flags.
After the fix, the code is using the same instruction sequence as
before.
---
sysdeps/s390/fpu/fedisblxcpt.c | 3 ++-
sysdeps/s390/fpu/feenablxcpt.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
Comments
On Okt 18 2023, Stefan Liebler wrote:
> diff --git a/sysdeps/s390/fpu/fedisblxcpt.c b/sysdeps/s390/fpu/fedisblxcpt.c
> index 728f103f43..84b2c5e64a 100644
> --- a/sysdeps/s390/fpu/fedisblxcpt.c
> +++ b/sysdeps/s390/fpu/fedisblxcpt.c
> @@ -26,7 +26,8 @@ fedisableexcept (int excepts)
>
> _FPU_GETCW (temp);
> old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT;
> - new_flags = (temp & (~((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT)));
> + new_flags = (temp & (~(((unsigned int) excepts & FE_ALL_EXCEPT)
> + << FPC_EXCEPTION_MASK_SHIFT)));
There is a redundant pair of parens around the ~ operator that makes the
whole expression more difficult to read. Please consider removing it.
> _FPU_SETCW (new_flags);
>
> return old_exc;
> diff --git a/sysdeps/s390/fpu/feenablxcpt.c b/sysdeps/s390/fpu/feenablxcpt.c
> index 0807e610a2..76d25316f4 100644
> --- a/sysdeps/s390/fpu/feenablxcpt.c
> +++ b/sysdeps/s390/fpu/feenablxcpt.c
> @@ -26,7 +26,8 @@ feenableexcept (int excepts)
>
> _FPU_GETCW (temp);
> old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT;
> - new_flags = (temp | ((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT));
> + new_flags = (temp | ((unsigned int) (excepts & FE_ALL_EXCEPT)
> + << FPC_EXCEPTION_MASK_SHIFT));
> _FPU_SETCW (new_flags);
>
> return old_exc;
Please place the cast consistently (either inside or outside the
(excepts & FE_ALL_EXCEPT) expression). Ok with that change.
On 19.10.23 10:48, Andreas Schwab wrote:
> On Okt 18 2023, Stefan Liebler wrote:
>
>> diff --git a/sysdeps/s390/fpu/fedisblxcpt.c b/sysdeps/s390/fpu/fedisblxcpt.c
>> index 728f103f43..84b2c5e64a 100644
>> --- a/sysdeps/s390/fpu/fedisblxcpt.c
>> +++ b/sysdeps/s390/fpu/fedisblxcpt.c
>> @@ -26,7 +26,8 @@ fedisableexcept (int excepts)
>>
>> _FPU_GETCW (temp);
>> old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT;
>> - new_flags = (temp & (~((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT)));
>> + new_flags = (temp & (~(((unsigned int) excepts & FE_ALL_EXCEPT)
>> + << FPC_EXCEPTION_MASK_SHIFT)));
>
> There is a redundant pair of parens around the ~ operator that makes the
> whole expression more difficult to read. Please consider removing it.
>
>> _FPU_SETCW (new_flags);
>>
>> return old_exc;
>> diff --git a/sysdeps/s390/fpu/feenablxcpt.c b/sysdeps/s390/fpu/feenablxcpt.c
>> index 0807e610a2..76d25316f4 100644
>> --- a/sysdeps/s390/fpu/feenablxcpt.c
>> +++ b/sysdeps/s390/fpu/feenablxcpt.c
>> @@ -26,7 +26,8 @@ feenableexcept (int excepts)
>>
>> _FPU_GETCW (temp);
>> old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT;
>> - new_flags = (temp | ((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT));
>> + new_flags = (temp | ((unsigned int) (excepts & FE_ALL_EXCEPT)
>> + << FPC_EXCEPTION_MASK_SHIFT));
>> _FPU_SETCW (new_flags);
>>
>> return old_exc;
>
> Please place the cast consistently (either inside or outside the
> (excepts & FE_ALL_EXCEPT) expression). Ok with that change.
>
Thanks for the review. I've just committed it with your two mentioned
changes.
Thanks,
Stefan
@@ -26,7 +26,8 @@ fedisableexcept (int excepts)
_FPU_GETCW (temp);
old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT;
- new_flags = (temp & (~((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT)));
+ new_flags = (temp & (~(((unsigned int) excepts & FE_ALL_EXCEPT)
+ << FPC_EXCEPTION_MASK_SHIFT)));
_FPU_SETCW (new_flags);
return old_exc;
@@ -26,7 +26,8 @@ feenableexcept (int excepts)
_FPU_GETCW (temp);
old_exc = (temp & FPC_EXCEPTION_MASK) >> FPC_EXCEPTION_MASK_SHIFT;
- new_flags = (temp | ((excepts & FE_ALL_EXCEPT) << FPC_EXCEPTION_MASK_SHIFT));
+ new_flags = (temp | ((unsigned int) (excepts & FE_ALL_EXCEPT)
+ << FPC_EXCEPTION_MASK_SHIFT));
_FPU_SETCW (new_flags);
return old_exc;