-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
207 lines (195 loc) · 10.1 KB
/
Linux-samples-gfx.yml
File metadata and controls
207 lines (195 loc) · 10.1 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
name: CI Linux samples/gfx
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
permissions:
contents: read
env:
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
jobs:
samples-gfx:
name: Build and run samples/gfx
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y build-essential
- name: Checkout
uses: actions/checkout@v3
- name: Build and run vulkan_extension_count_test (ASan)
shell: bash
working-directory: samples/gfx/vulkan_extension_count
run: |
set -eu
# Regression test for the heap-overflow fix in
# gfx/common/vulkan_common.c::vulkan_find_device_extensions.
# Pre-fix the function appended the required-extension list
# twice -- once via memcpy at the top of the body, then
# again in a per-element loop -- consuming
# (count_initial + 2*num_required + num_optional) slots in
# the caller's buffer. vulkan_context_create_device_wrapper
# sized its malloc for (count_initial + num_required +
# num_optional) entries, so a libretro core using the Vulkan
# HW context-negotiation interface against a GPU exposing at
# least one optional extension hit a one-element heap-buffer-
# overflow (8 bytes on 64-bit) at the end of the malloc'd
# block. Build under AddressSanitizer so any reintroduction
# of the duplicate write is caught at the bounds level. If
# vulkan_common.c amends the append-to-enabled[] block, the
# verbatim copy in vulkan_extension_count_test.c must follow.
make clean all SANITIZER=address
test -x vulkan_extension_count_test
timeout 60 ./vulkan_extension_count_test
echo "[pass] vulkan_extension_count_test"
- name: Build and run vulkan_swapchain_clamp_test (ASan)
shell: bash
working-directory: samples/gfx/vulkan_swapchain_clamp
run: |
set -eu
# Regression test for the unclamped-swapchain-image-count
# fix in gfx/common/vulkan_common.c::vulkan_create_swapchain.
# Pre-fix the two vkGetSwapchainImagesKHR calls (count
# query + image fill) had no clamp between them, so a driver
# returning more than VULKAN_MAX_SWAPCHAIN_IMAGES (8) images
# on the second call wrote past context.swapchain_images[8]
# and every loop bounded by num_swapchain_images walked past
# its compile-time-sized companion array (~12 such loops
# across init/deinit/textures/buffers/descriptor pools/
# command buffers/readback and direct vk->swapchain[i]
# uses). Build under AddressSanitizer so any reintroduction
# of either the request-side or the post-create clamp is
# caught at the bounds level. If vulkan_common.c amends
# the cap or the post-create clamp, the verbatim copies in
# vulkan_swapchain_clamp_test.c must follow.
make clean all SANITIZER=address
test -x vulkan_swapchain_clamp_test
timeout 60 ./vulkan_swapchain_clamp_test
echo "[pass] vulkan_swapchain_clamp_test"
- name: Build and run vulkan_texture_size_test (ASan)
shell: bash
working-directory: samples/gfx/vulkan_texture_size
run: |
set -eu
# Regression test for the 32-bit-overflow fix in
# gfx/drivers/vulkan.c::vulkan_create_texture's staging-
# buffer sizing. Pre-fix the buffer_info.size calculation
# (buffer_width * height) was unsigned*unsigned in 32-bit
# before being widened to VkDeviceSize on assignment. With
# dimensions large enough to wrap (e.g. 65536x16385x4 ->
# 0x1_0004_0000 truncates to 0x40000), the staging buffer
# was malloc'd at the wrapped (small) size while the per-row
# upload memcpy loop walked the full width x height,
# writing past the mapped region into adjacent heap memory.
# Reachable from libretro cores supplying oversized
# retro_framebuffer dimensions and from vulkan_load_texture
# / vulkan_set_texture_frame. Build under AddressSanitizer
# so any reintroduction of the 32-bit arithmetic is caught
# at the bounds level. If vulkan.c amends the size
# calculation or upload-loop strides, the verbatim copies
# in vulkan_texture_size_test.c must follow.
make clean all SANITIZER=address
test -x vulkan_texture_size_test
timeout 60 ./vulkan_texture_size_test
echo "[pass] vulkan_texture_size_test"
- name: Build and run slang_texture_index_bounds_test (ASan)
shell: bash
working-directory: samples/gfx/slang_texture_index_bounds
run: |
set -eu
# Regression test for the texture-semantic index-bounds
# fix in gfx/drivers_shader/slang_process.cpp::
# validate_texture_semantic_index(). Pre-fix only
# SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT was bounded against
# reflection->pass_number; ORIGINAL_HISTORY, PASS_FEEDBACK
# and USER had no upper bound on their array index. The
# index suffix in arrayed semantic names like
# `OriginalHistory42` is parsed via strtoul in
# slang_name_to_texture_semantic_array() and propagates
# into the downstream resize_minimum() calls in
# set_ubo_texture_offset() and the direct sampler-binding
# loop. A malicious slang shader declaring
# `OriginalHistory4294967294` makes std::vector::resize
# request ~128 GiB, throwing std::bad_alloc which
# propagates unhandled out of the filter-chain create
# path, terminating the process. Reachable from any
# malicious slang preset (downloaded via Online Updater
# or shipped third-party). Build under AddressSanitizer
# so any reintroduction is caught at the bounds level.
# If slang_process.cpp amends the cap table or the
# dispatch structure, the verbatim copy in
# slang_texture_index_bounds_test.c must follow.
make clean all SANITIZER=address
test -x slang_texture_index_bounds_test
timeout 60 ./slang_texture_index_bounds_test
echo "[pass] slang_texture_index_bounds_test"
- name: Build and run vulkan_mailbox_init_leak_test (ASan + LSan)
shell: bash
working-directory: samples/gfx/vulkan_mailbox_init_leak
run: |
set -eu
# Regression test for the partial-init leak fix in
# gfx/common/vulkan_common.c::vulkan_emulated_mailbox_init.
# Pre-fix the function had three sequential allocations
# (scond_new, slock_new, sthread_create) and on any of the
# latter two failures returned `false` directly, leaking
# the already-allocated cond and/or lock. Both production
# call sites in vulkan_create_swapchain ignore the return
# value, so an init failure also left vk->mailbox.lock ==
# NULL and vk->mailbox.cond == NULL while VK_DATA_FLAG_
# EMULATING_MAILBOX was still set, setting up a NULL-deref
# the next time vulkan_acquire_next_image routed into
# vulkan_emulated_mailbox_acquire_next_image (slock_lock
# on a NULL pointer). Fix routes every early failure
# through `goto error` to a single deinit call, which is
# null-safe and ends with a memset, leaving the struct in
# the same shape the deinit-on-shutdown path produces and
# tripping the existing `mailbox.swapchain == VK_NULL_
# HANDLE` guard at vulkan_acquire_next_image. Build under
# AddressSanitizer with leak detection so any
# reintroduction is caught at the leak level. If
# vulkan_common.c amends the init or deinit, the verbatim
# copies in vulkan_mailbox_init_leak_test.c must follow.
make clean all SANITIZER=address
test -x vulkan_mailbox_init_leak_test
ASAN_OPTIONS=detect_leaks=1 timeout 60 \
./vulkan_mailbox_init_leak_test
echo "[pass] vulkan_mailbox_init_leak_test"
- name: Build and run vulkan_ctx_double_free_test (ASan)
shell: bash
working-directory: samples/gfx/vulkan_ctx_double_free
run: |
set -eu
# Regression test for the double-free / use-after-free
# fix in the Vulkan context drivers' set_video_mode error
# paths: gfx/drivers_context/wayland_vk_ctx.c,
# w_vk_ctx.c, x_vk_ctx.c. Pre-fix each set_video_mode
# called its own destroy()/destroy_resources()+free() on
# ctx_data before returning false; the caller in
# gfx/drivers/vulkan.c::vulkan_init then ran
# vulkan_free()->ctx_driver->destroy(ctx_data) on the
# already-freed pointer (UAF read of struct fields, then
# a second free of the same allocation). Reachable from
# vulkan_surface_create() failure (missing extension /
# driver issue), Wayland's set_video_mode_common_*
# helpers failing, X11's XGetVisualInfo returning NULL,
# or win32_set_video_mode failing. Cocoa (cocoa_vk_ctx)
# and Android (android_vk_ctx) already handle this
# correctly by returning false without freeing -- the
# fix makes Wayland/Win32/X11 match. Build under
# AddressSanitizer so any reintroduction is caught at
# the bounds level (UAF + double-free both fire). If
# any of the three context drivers amends the
# set_video_mode error path to once again destroy
# ctx_data, the verbatim copy in
# vulkan_ctx_double_free_test.c must follow.
make clean all SANITIZER=address
test -x vulkan_ctx_double_free_test
timeout 60 ./vulkan_ctx_double_free_test
echo "[pass] vulkan_ctx_double_free_test"