Skip to content

Commit 8d2a70a

Browse files
committed
Add checkbox and new field 'untrusted' in fuzzer
1 parent d792998 commit 8d2a70a

5 files changed

Lines changed: 90 additions & 2 deletions

File tree

src/appengine/handlers/fuzzers.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ def apply_fuzzer_changes(self, fuzzer, upload_info):
174174
timeout = self._get_integer_value('timeout')
175175
max_testcases = self._get_integer_value('max_testcases')
176176
external_contribution = request.get('external_contribution', False)
177+
untrusted = request.get('untrusted', False)
177178
differential = request.get('differential', False)
178179
environment_string = request.get('additional_environment_string')
179180
data_bundle_name = request.get('data_bundle_name')
@@ -193,6 +194,7 @@ def apply_fuzzer_changes(self, fuzzer, upload_info):
193194
fuzzer.sample_testcase = None
194195
fuzzer.console_output = None
195196
fuzzer.external_contribution = bool(external_contribution)
197+
fuzzer.untrusted = bool(untrusted)
196198
fuzzer.differential = bool(differential)
197199
fuzzer.additional_environment_string = environment_string
198200
fuzzer.timestamp = datetime.datetime.now(tz=datetime.timezone.utc).replace(
@@ -208,6 +210,16 @@ def apply_fuzzer_changes(self, fuzzer, upload_info):
208210
if launcher_script:
209211
fuzzer.launcher_script = launcher_script
210212

213+
if fuzzer.untrusted:
214+
for job_name in jobs:
215+
job = data_types.Job.query(data_types.Job.name == job_name).get()
216+
if not job:
217+
raise helpers.EarlyExitError(f'Job {job_name} not found.', 400)
218+
if job.platform.lower() != 'linux':
219+
raise helpers.EarlyExitError(
220+
f'Untrusted fuzzers can only be run on Linux jobs. '
221+
f'Job "{job_name}" has platform "{job.platform}".', 400)
222+
211223
fuzzer.put()
212224

213225
fuzzer_selection.update_mappings_for_fuzzer(fuzzer)

src/appengine/private/components/fuzzers-page/edit-form.html

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,16 @@
220220
</div>
221221
<div class="inline narrow">
222222
<paper-checkbox checked="{{fuzzer.external_contribution}}">External contribution</paper-checkbox>
223+
</div>
224+
<div class="inline narrow">
225+
<paper-checkbox checked="{{fuzzer.untrusted}}">Untrusted</paper-checkbox>
226+
</div>
223227

224-
<!-- TODO: Re-enable after the differential fuzzing is implemented.
228+
<!-- TODO: Re-enable after the differential fuzzing is implemented.
229+
<div class="inline narrow">
225230
<paper-checkbox checked="{{fuzzer.differential}}">Differential fuzzer</paper-checkbox>
226-
-->
227231
</div>
232+
-->
228233
</ajax-dialog>
229234
<iron-ajax
230235
id="ajaxFinish"
@@ -257,6 +262,7 @@
257262
'max_testcases',
258263
'name',
259264
'timeout',
265+
'untrusted',
260266
],
261267
},
262268
file: Object,

src/clusterfuzz/_internal/datastore/data_types.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ class Fuzzer(Model):
353353
# Does it run un-trusted content ? Examples including running live sites.
354354
untrusted_content = ndb.BooleanProperty(default=False)
355355

356+
# Is this fuzzer untrusted? (VRP support)
357+
untrusted = ndb.BooleanProperty(default=False)
358+
356359
# Data bundle name.
357360
data_bundle_name = ndb.StringProperty(default='')
358361

src/clusterfuzz/_internal/tests/appengine/handlers/fuzzers_test.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def test_update_fuzzer(self):
179179
'additional_environment_string': 'args=123',
180180
'data_bundle_name': 'test_bundle',
181181
'external_contribution': True,
182+
'untrusted': False,
182183
'executable_path': 'executable',
183184
'last_edited_by': 'editor@example.com',
184185
'launcher_script': 'launcher',
@@ -188,3 +189,68 @@ def test_update_fuzzer(self):
188189
'source': 'original@example.com',
189190
'timeout': 30,
190191
})
192+
193+
def test_update_fuzzer_untrusted_success(self):
194+
"""Test updating a fuzzer to untrusted with a Linux job succeeds."""
195+
# Create a Linux job.
196+
job = data_types.Job(name='linux_job', platform='LINUX')
197+
job.put()
198+
199+
fuzzer_name = 'test_fuzzer'
200+
fuzzer = data_types.Fuzzer(
201+
name=fuzzer_name,
202+
jobs=[],
203+
revision=1,
204+
source='original@example.com',
205+
timeout=10,
206+
)
207+
fuzzer.put()
208+
209+
request_payload = {
210+
'csrf_token': form.generate_csrf_token(),
211+
'key': fuzzer.key.id(),
212+
'name': fuzzer_name,
213+
'untrusted': True,
214+
'jobs': ['linux_job'],
215+
}
216+
217+
resp = self.app.post_json('/fuzzers/edit', request_payload)
218+
self.assertEqual(302, resp.status_int) # Redirects to /fuzzers
219+
220+
fuzzer = fuzzer.key.get()
221+
self.assertTrue(fuzzer.untrusted)
222+
self.assertEqual(fuzzer.jobs, ['linux_job'])
223+
224+
def test_update_fuzzer_untrusted_failure_non_linux(self):
225+
"""Test updating a fuzzer to untrusted with a non-Linux job fails."""
226+
# Create a Windows job.
227+
job = data_types.Job(name='windows_job', platform='WINDOWS')
228+
job.put()
229+
230+
fuzzer_name = 'test_fuzzer'
231+
fuzzer = data_types.Fuzzer(
232+
name=fuzzer_name,
233+
jobs=[],
234+
revision=1,
235+
source='original@example.com',
236+
timeout=10,
237+
)
238+
fuzzer.put()
239+
240+
request_payload = {
241+
'csrf_token': form.generate_csrf_token(),
242+
'key': fuzzer.key.id(),
243+
'name': fuzzer_name,
244+
'untrusted': True,
245+
'jobs': ['windows_job'],
246+
}
247+
248+
resp = self.app.post_json(
249+
'/fuzzers/edit', request_payload, expect_errors=True)
250+
self.assertEqual(400, resp.status_int)
251+
self.assertIn('Untrusted fuzzers can only be run on Linux jobs',
252+
resp.normal_body.decode())
253+
254+
# Verify fuzzer was not updated to untrusted.
255+
fuzzer = fuzzer.key.get()
256+
self.assertFalse(fuzzer.untrusted)

src/clusterfuzz/_internal/tests/core/datastore/data_types_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def test_get_config_dict(self):
5656
'revision': 3,
5757
'source': 'author',
5858
'last_edited_by': 'editor',
59+
'untrusted': False,
5960
},
6061
config_dict,
6162
)

0 commit comments

Comments
 (0)