1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
windows 10 display scale will cause an exception
Description of problem:
windows dispaly sacle 150% or higher, windows system will exception
Steps to reproduce:
1. windows dispaly sacle 150%
Additional information:
- code in: qemu/hw/display/qxl-render.c
static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
QXLDataChunk *chunk, uint32_t group_id)
{
uint32_t max_chunks = 32;
size_t offset = 0;
size_t bytes;
for (;;) {
bytes = MIN(size - offset, chunk->data_size);
memcpy(dest + offset, chunk->data, bytes);
offset += bytes;
if (offset == size) {
return;
}
chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id,
sizeof(QXLDataChunk) + chunk->data_size);
**// get next chunk, but the chunk size use current chunk's data size, not next chunk's data size!!!!**
**// if next chunk alloc size < current chunk's data size, there will be exception **
if (!chunk) {
return;
}
max_chunks--;
if (max_chunks == 0) {
return;
}
}
}
- code in: qxl_wddm_dod/QXLDod.cpp exist next chunk alloc size < current chunk's data size
NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
{
.....
res = (Resource *)AllocMem(MSPACE_TYPE_VRAM, CURSOR_ALLOC_SIZE, TRUE); // here we all the first QXLDataChunk , and alloc_size = (CURSOR_ALLOC_SIZE - sizeof(Resource) - sizeof(InternalCursor)) = 8118
.....
for (; src != src_end; src += pSetPointerShape->Pitch) {
if (!PutBytesAlign(&chunk, &now, &end, src, line_size, PAGE_SIZE - PAGE_SIZE % line_size, NULL)) { // in this function ,we will alloc next QXLDataChunk
..........
break;
}
}
}
BOOLEAN QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
UINT8 **end_ptr, UINT8 *src, int size,
size_t alloc_size, PLIST_ENTRY pDelayed)
{
.....
size_t maxAllocSize = BITS_BUF_MAX - BITS_BUF_MAX % size;
alloc_size = MIN(alloc_size, maxAllocSize);
void *ptr = AllocMem(MSPACE_TYPE_VRAM, alloc_size + sizeof(QXLDataChunk), bForced); *** //here will alloc next QXLDataChunk and alloc_size = (PAGE_SIZE - PAGE_SIZE % line_size) = 3876 ****
}
eg:
dispaly sacle 150% ,mouse size will bu change to 57* 55 ,rgba data size = 12540, we need three QXLDataChunk
QXLDataChunk* first;
first->data_size = 8118;
first->prev_chunk = 0;
first->next_chunk=second;
first->data = [alloc_size(8118), data_size(8118)]
QXLDataChunk* second;
second->data_size = 3876;
second->prev_chunk = first;
second->next_chunk=third;
second->data = [alloc_size(3876), data_size(3876)]
QXLDataChunk* third;
third->data_size = 546;
third->prev_chunk =second;
third->next_chunk=0;
third->data = [alloc_size(3876), data_size(546)]
chunk = first;
qxl_phys2virt(qxl, second, group_id, sizeof(QXLDataChunk) + 8118)
this size [sizeof(QXLDataChunk) + 8118] > second QXLDataChunk's alloc size , will cause qxl_get_check_slot_offset check fail
for second QXLDataChunk, we actual alloc size is (sizeof(QXLDataChunk) + 3876), but we assign (8118 + sizeof(QXLDataChunk)) will cause an exception
suggest code :
static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
QXLDataChunk *chunk, uint32_t group_id)
{
uint32_t max_chunks = 32;
size_t offset = 0;
size_t bytes;
QXLPHYSICAL next_chunk_phys = 0;
for (;;) {
bytes = MIN(size - offset, chunk->data_size);
memcpy(dest + offset, chunk->data, bytes);
offset += bytes;
if (offset == size) {
return;
}
next_chunk_phys = chunk->next_chunk;
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
sizeof(QXLDataChunk)); // fist time, only get the next chunk's data size;
if (!chunk) {
return;
}
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
sizeof(QXLDataChunk) + chunk->data_size); // second time, check data size and get data;
if (!chunk) {
return;
}
max_chunks--;
if (max_chunks == 0) {
return;
}
}
}
|