Bug 60745 - __mpn_construct_double not signal safe (compiler bug)
Summary: __mpn_construct_double not signal safe (compiler bug)
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: glibc (Show other bugs)
(Show other bugs)
Version: 7.2
Hardware: i386 Linux
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Brian Brock
Depends On:
TreeView+ depends on / blocked
Reported: 2002-03-05 21:17 UTC by John Reiser
Modified: 2016-11-24 15:11 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2002-03-05 21:17:42 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

External Trackers
Tracker ID Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2002:056 contract SHIPPED_LIVE GNU C Library bugfix update 2002-04-02 05:00:00 UTC

Description John Reiser 2002-03-05 21:17:36 UTC
Description of Problem:
In glibc-2.2.4-19.3, __mpn_construct_double has been compiled incorrectly.
The generated code stores and fetches at addresses below the stack pointer.
If a signal is delivered at just the right time, then the result of
__mpn_construct_double will be bad because the storage is overwritten by
signal delivery.  __mpn_construct_double is used by strtod [for certain[
and *scanf [probably].

Version-Release number of selected component (if applicable):

How Reproducible:
Inspect code using gdb.

Steps to Reproduce:
gdb /lib/libc.so.6
x/35i __mpn_construct_double

gdb /lib/i686/libc.so.6
x/35i __mpn_construct_double

Actual Results:
for i686 [i386 is same except begins at 0x55810]:
0x55740 <__mpn_construct_double>:	push   %ebp
0x55741 <__mpn_construct_double+1>:	mov    %esp,%ebp
0x55743 <__mpn_construct_double+3>:	mov    0x10(%ebp),%eax
0x55746 <__mpn_construct_double+6>:	push   %edi
0x55747 <__mpn_construct_double+7>:	mov    %edi,%edx
0x55749 <__mpn_construct_double+9>:	and    $0x7fffffff,%edx
0x5574f <__mpn_construct_double+15>:	push   %esi     ## frame size is 8 bytes
0x55750 <__mpn_construct_double+16>:	shl    $0x1f,%eax
0x55753 <__mpn_construct_double+19>:	mov    0x8(%ebp),%ecx
0x55756 <__mpn_construct_double+22>:	mov    %edx,%edi
0x55758 <__mpn_construct_double+24>:	or     %eax,%edi
0x5575a <__mpn_construct_double+26>:	mov    0xc(%ebp),%eax
0x5575d <__mpn_construct_double+29>:	mov    %edi,%edx
0x5575f <__mpn_construct_double+31>:	and    $0x800fffff,%edx
0x55765 <__mpn_construct_double+37>:	add    $0x3ff,%eax
0x5576a <__mpn_construct_double+42>:	and    $0x7ff,%eax
0x5576f <__mpn_construct_double+47>:	mov    (%ecx),%esi
0x55771 <__mpn_construct_double+49>:	shl    $0x14,%eax
0x55774 <__mpn_construct_double+52>:	mov    %edx,%edi
0x55776 <__mpn_construct_double+54>:	mov    0x4(%ecx),%edx
0x55779 <__mpn_construct_double+57>:	or     %eax,%edi
0x5577b <__mpn_construct_double+59>:	mov    %esi,0xfffffff0(%ebp)  ## requires
16 bytes of local stack frame
#         change above to                  pushl %edi; pushl %esi; nop
0x5577e <__mpn_construct_double+62>:	mov    %edi,%eax
0x55780 <__mpn_construct_double+64>:	and    $0xfffff,%edx
0x55786 <__mpn_construct_double+70>:	pop    %esi
#         change above to                  nop
0x55787 <__mpn_construct_double+71>:	and    $0xfff00000,%eax
0x5578c <__mpn_construct_double+76>:	mov    %eax,%edi
0x5578e <__mpn_construct_double+78>:	or     %edx,%edi
0x55790 <__mpn_construct_double+80>:	mov    %edi,0xfffffff4(%ebp)
0x55793 <__mpn_construct_double+83>:	pop    %edi
#         change above to                  nop
0x55794 <__mpn_construct_double+84>:	fldl   0xfffffff0(%ebp)
#   change to  popl %esi; popl %edi; popl %esi; popl %edi; popl %ebp; ret; nop;
nop; nop
0x55797 <__mpn_construct_double+87>:	pop    %ebp
0x55798 <__mpn_construct_double+88>:	ret    
0x55799 <__mpn_construct_double+89>:	lea    0x0(%esi,1),%esi
0x557a0<__mpn_construct_long_double>:	push   %ebp

Expected Results:

Additional Information:
As a workaround, the code can be binary patched in place as noted above.
The gdb commands for i386 on a writable file would be
set *(char *)0x5584b=0x57
set *(char *)0x5584c=0x56
set *(char *)0x5584d=0x90

set *(char *)0x55856=0x90

set *(char *)0x55863=0x90

set *(char *)0x55867=0x5e
set *(char *)0x55868=0x5f
set *(char *)0x55869=0x5e
set *(char *)0x5586a=0x5f
set *(char *)0x5586b=0x5d
set *(char *)0x5586c=0xc3
set *(char *)0x5586d=0x90
set *(char *)0x5586e=0x90
set *(char *)0x5586f=0x90

Comment 1 Jakub Jelinek 2002-04-05 09:13:22 UTC
Should be fixed in glibc-2.2.4-24.

Note You need to log in before you can comment on or make changes to this bug.