Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
de89ce1b
Commit
de89ce1b
authored
Jun 17, 2021
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Support growing both 32- and 64-bit stacks.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
e91d19a5
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
63 additions
and
27 deletions
+63
-27
virtual.c
dlls/ntdll/unix/virtual.c
+63
-27
No files found.
dlls/ntdll/unix/virtual.c
View file @
de89ce1b
...
...
@@ -3131,29 +3131,67 @@ void virtual_map_user_shared_data(void)
}
struct
thread_stack_info
{
char
*
start
;
char
*
limit
;
char
*
end
;
SIZE_T
guaranteed
;
BOOL
is_wow
;
};
/***********************************************************************
* is_inside_thread_stack
*/
static
BOOL
is_inside_thread_stack
(
void
*
ptr
,
struct
thread_stack_info
*
stack
)
{
TEB
*
teb
=
NtCurrentTeb
();
WOW_TEB
*
wow_teb
=
get_wow_teb
(
teb
);
stack
->
start
=
teb
->
DeallocationStack
;
stack
->
limit
=
teb
->
Tib
.
StackLimit
;
stack
->
end
=
teb
->
Tib
.
StackBase
;
stack
->
guaranteed
=
max
(
teb
->
GuaranteedStackBytes
,
page_size
*
(
is_win64
?
2
:
1
)
);
stack
->
is_wow
=
FALSE
;
if
((
char
*
)
ptr
>
stack
->
start
&&
(
char
*
)
ptr
<=
stack
->
end
)
return
TRUE
;
if
(
!
wow_teb
)
return
FALSE
;
stack
->
start
=
ULongToPtr
(
wow_teb
->
DeallocationStack
);
stack
->
limit
=
ULongToPtr
(
wow_teb
->
Tib
.
StackLimit
);
stack
->
end
=
ULongToPtr
(
wow_teb
->
Tib
.
StackBase
);
stack
->
guaranteed
=
max
(
wow_teb
->
GuaranteedStackBytes
,
page_size
*
(
is_win64
?
1
:
2
)
);
stack
->
is_wow
=
TRUE
;
return
((
char
*
)
ptr
>
stack
->
start
&&
(
char
*
)
ptr
<=
stack
->
end
);
}
/***********************************************************************
* grow_thread_stack
*/
static
NTSTATUS
grow_thread_stack
(
char
*
page
)
static
NTSTATUS
grow_thread_stack
(
char
*
page
,
struct
thread_stack_info
*
stack_info
)
{
NTSTATUS
ret
=
0
;
size_t
guaranteed
=
max
(
NtCurrentTeb
()
->
GuaranteedStackBytes
,
page_size
*
(
is_win64
?
2
:
1
)
);
set_page_vprot_bits
(
page
,
page_size
,
0
,
VPROT_GUARD
);
mprotect_range
(
page
,
page_size
,
0
,
0
);
if
(
page
>=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
page_size
+
guaranteed
)
if
(
page
>=
stack_info
->
start
+
page_size
+
stack_info
->
guaranteed
)
{
set_page_vprot_bits
(
page
-
page_size
,
page_size
,
VPROT_COMMITTED
|
VPROT_GUARD
,
0
);
mprotect_range
(
page
-
page_size
,
page_size
,
0
,
0
);
}
else
/* inside guaranteed space -> overflow exception */
{
page
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
page_size
;
set_page_vprot_bits
(
page
,
guaranteed
,
VPROT_COMMITTED
,
VPROT_GUARD
);
mprotect_range
(
page
,
guaranteed
,
0
,
0
);
page
=
stack_info
->
start
+
page_size
;
set_page_vprot_bits
(
page
,
stack_info
->
guaranteed
,
VPROT_COMMITTED
,
VPROT_GUARD
);
mprotect_range
(
page
,
stack_info
->
guaranteed
,
0
,
0
);
ret
=
STATUS_STACK_OVERFLOW
;
}
NtCurrentTeb
()
->
Tib
.
StackLimit
=
page
;
if
(
stack_info
->
is_wow
)
{
WOW_TEB
*
wow_teb
=
get_wow_teb
(
NtCurrentTeb
()
);
wow_teb
->
Tib
.
StackLimit
=
PtrToUlong
(
page
);
}
else
NtCurrentTeb
()
->
Tib
.
StackLimit
=
page
;
return
ret
;
}
...
...
@@ -3171,14 +3209,14 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack )
vprot
=
get_page_vprot
(
page
);
if
(
!
is_inside_signal_stack
(
stack
)
&&
(
vprot
&
VPROT_GUARD
))
{
if
(
page
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
page
>=
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
struct
thread_stack_info
stack_info
;
if
(
!
is_inside_thread_stack
(
page
,
&
stack_info
)
)
{
set_page_vprot_bits
(
page
,
page_size
,
0
,
VPROT_GUARD
);
mprotect_range
(
page
,
page_size
,
0
,
0
);
ret
=
STATUS_GUARD_PAGE_VIOLATION
;
}
else
ret
=
grow_thread_stack
(
page
);
else
ret
=
grow_thread_stack
(
page
,
&
stack_info
);
}
else
if
(
err
&
EXCEPTION_WRITE_FAULT
)
{
...
...
@@ -3205,19 +3243,16 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack )
void
*
virtual_setup_exception
(
void
*
stack_ptr
,
size_t
size
,
EXCEPTION_RECORD
*
rec
)
{
char
*
stack
=
stack_ptr
;
struct
thread_stack_info
stack_info
;
if
(
is_inside_signal_stack
(
stack
))
{
ERR
(
"nested exception on signal stack in thread %04x addr %p stack %p (%p-%p-%p)
\n
"
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
abort_thread
(
1
);
}
if
(
stack
-
size
>
stack
||
/* check for overflow in subtraction */
stack
<=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
||
stack
>
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
)
if
(
!
is_inside_thread_stack
(
stack
,
&
stack_info
))
{
if
(
is_inside_signal_stack
(
stack
))
{
ERR
(
"nested exception on signal stack in thread %04x addr %p stack %p
\n
"
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
);
abort_thread
(
1
);
}
WARN
(
"exception outside of stack limits in thread %04x addr %p stack %p (%p-%p-%p)
\n
"
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
...
...
@@ -3226,19 +3261,20 @@ void *virtual_setup_exception( void *stack_ptr, size_t size, EXCEPTION_RECORD *r
stack
-=
size
;
if
(
stack
<
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
)
if
(
stack
<
stack_info
.
start
+
4096
)
{
/* stack overflow on last page, unrecoverable */
UINT
diff
=
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
+
4096
-
stack
;
UINT
diff
=
stack_info
.
start
+
4096
-
stack
;
ERR
(
"stack overflow %u bytes in thread %04x addr %p stack %p (%p-%p-%p)
\n
"
,
diff
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
NtCurrentTeb
()
->
DeallocationStack
,
NtCurrentTeb
()
->
Tib
.
StackLimit
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
diff
,
GetCurrentThreadId
(),
rec
->
ExceptionAddress
,
stack
,
stack_info
.
start
,
stack_info
.
limit
,
stack_info
.
end
);
abort_thread
(
1
);
}
else
if
(
stack
<
(
char
*
)
NtCurrentTeb
()
->
Tib
.
StackL
imit
)
else
if
(
stack
<
stack_info
.
l
imit
)
{
mutex_lock
(
&
virtual_mutex
);
/* no need for signal masking inside signal handler */
if
((
get_page_vprot
(
stack
)
&
VPROT_GUARD
)
&&
grow_thread_stack
(
ROUND_ADDR
(
stack
,
page_mask
)))
if
((
get_page_vprot
(
stack
)
&
VPROT_GUARD
)
&&
grow_thread_stack
(
ROUND_ADDR
(
stack
,
page_mask
),
&
stack_info
))
{
rec
->
ExceptionCode
=
STATUS_STACK_OVERFLOW
;
rec
->
NumberParameters
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment