36
36
from clusterfuzz ._internal .bot .tasks import setup
37
37
from clusterfuzz ._internal .bot .tasks import task_creation
38
38
from clusterfuzz ._internal .bot .tasks import trials
39
+ from clusterfuzz ._internal .bot .tasks .utasks import fuzz_task_knobs
39
40
from clusterfuzz ._internal .bot .tasks .utasks import uworker_handle_errors
40
41
from clusterfuzz ._internal .bot .tasks .utasks import uworker_io
41
42
from clusterfuzz ._internal .build_management import build_manager
44
45
from clusterfuzz ._internal .crash_analysis .stack_parsing import stack_analyzer
45
46
from clusterfuzz ._internal .datastore import data_handler
46
47
from clusterfuzz ._internal .datastore import data_types
47
- from clusterfuzz ._internal .datastore import ndb_utils
48
48
from clusterfuzz ._internal .fuzzing import corpus_manager
49
49
from clusterfuzz ._internal .fuzzing import fuzzer_selection
50
- from clusterfuzz ._internal .fuzzing import gesture_handler
51
50
from clusterfuzz ._internal .fuzzing import leak_blacklist
52
51
from clusterfuzz ._internal .google_cloud_utils import big_query
53
52
from clusterfuzz ._internal .google_cloud_utils import blobs
64
63
from clusterfuzz .fuzz import engine
65
64
from clusterfuzz .stacktraces .__init__ import CrashInfo
66
65
67
- SelectionMethod = collections .namedtuple ('SelectionMethod' ,
68
- 'method_name probability' )
69
-
70
- DEFAULT_CHOOSE_PROBABILITY = 9 # 10%
71
66
FUZZER_METADATA_REGEX = re .compile (r'metadata::(\w+):\s*(.*)' )
72
67
FUZZER_FAILURE_THRESHOLD = 0.33
73
- MAX_GESTURES = 30
74
68
MAX_NEW_CORPUS_FILES = 500
75
- SELECTION_METHOD_DISTRIBUTION = [
76
- SelectionMethod ('default' , .7 ),
77
- SelectionMethod ('multi_armed_bandit' , .3 )
78
- ]
79
69
THREAD_WAIT_TIMEOUT = 1
80
70
81
71
@@ -102,33 +92,12 @@ class FuzzErrorCode:
102
92
'timeout_multiplier' , 'test_timeout' , 'thread_wait_timeout' ,
103
93
'data_directory'
104
94
])
105
- Redzone = collections .namedtuple ('Redzone' , ['size' , 'weight' ])
106
95
107
96
GenerateBlackboxTestcasesResult = collections .namedtuple (
108
97
'GenerateBlackboxTestcasesResult' ,
109
98
['success' , 'testcase_file_paths' , 'fuzzer_metadata' ])
110
99
111
100
112
- def do_multiarmed_bandit_strategy_selection (uworker_env ):
113
- """Set multi-armed bandit strategy selection during preprocessing. Set
114
- multi-armed bandit strategy selection distribution as an environment variable
115
- so we can access it in launcher."""
116
- # TODO: Remove environment variable once fuzzing engine refactor is
117
- # complete.
118
- if not environment .get_value (
119
- 'USE_BANDIT_STRATEGY_SELECTION' , env = uworker_env ):
120
- return
121
- selection_method = utils .random_weighted_choice (SELECTION_METHOD_DISTRIBUTION ,
122
- 'probability' )
123
- environment .set_value ('STRATEGY_SELECTION_METHOD' ,
124
- selection_method .method_name , uworker_env )
125
- distribution = get_strategy_distribution_from_ndb ()
126
- if not distribution :
127
- return
128
- environment .set_value ('STRATEGY_SELECTION_DISTRIBUTION' , distribution ,
129
- uworker_env )
130
-
131
-
132
101
def has_standard_build ():
133
102
if environment .platform () == 'FUCHSIA' :
134
103
return False
@@ -663,135 +632,13 @@ def get_testcases(testcase_count, testcase_directory, data_directory):
663
632
generated_testcase_string )
664
633
665
634
666
- def pick_gestures (test_timeout ):
667
- """Return a list of random gestures."""
668
- if not environment .get_value ('ENABLE_GESTURES' , True ):
669
- # Gestures disabled.
670
- return []
671
-
672
- # Probability of choosing gestures.
673
- if utils .random_number (0 , DEFAULT_CHOOSE_PROBABILITY ):
674
- return []
675
-
676
- gesture_count = utils .random_number (1 , MAX_GESTURES )
677
- gestures = gesture_handler .get_gestures (gesture_count )
678
- if not gestures :
679
- return []
680
-
681
- # Pick a random trigger time to run the gesture at.
682
- min_gesture_time = int (
683
- utils .random_element_from_list ([0.25 , 0.50 , 0.50 , 0.50 ]) * test_timeout )
684
- max_gesture_time = test_timeout - 1
685
- gesture_time = utils .random_number (min_gesture_time , max_gesture_time )
686
-
687
- gestures .append ('Trigger:%d' % gesture_time )
688
- return gestures
689
-
690
-
691
- def pick_redzone ():
692
- """Return a random size for redzone."""
693
- thread_multiplier = environment .get_value ('THREAD_MULTIPLIER' , 1 )
694
-
695
- if thread_multiplier == 1 :
696
- redzone_list = [
697
- Redzone (16 , 1.0 ),
698
- Redzone (32 , 1.0 ),
699
- Redzone (64 , 0.5 ),
700
- Redzone (128 , 0.5 ),
701
- Redzone (256 , 0.25 ),
702
- Redzone (512 , 0.25 ),
703
- ]
704
- else :
705
- # For beefier boxes, prioritize using bigger redzones.
706
- redzone_list = [
707
- Redzone (16 , 0.25 ),
708
- Redzone (32 , 0.25 ),
709
- Redzone (64 , 0.50 ),
710
- Redzone (128 , 0.50 ),
711
- Redzone (256 , 1.0 ),
712
- Redzone (512 , 1.0 ),
713
- ]
714
-
715
- return utils .random_weighted_choice (redzone_list ).size
716
-
717
-
718
- def pick_ubsan_disabled (job_type ):
719
- """Choose whether to disable UBSan in an ASan+UBSan build."""
720
- # This is only applicable in an ASan build.
721
- memory_tool_name = environment .get_memory_tool_name (job_type )
722
- if memory_tool_name not in ['ASAN' , 'HWASAN' ]:
723
- return False
724
-
725
- # Check if UBSan is enabled in this ASan build. If not, can't disable it.
726
- if not environment .get_value ('UBSAN' ):
727
- return False
728
-
729
- return not utils .random_number (0 , DEFAULT_CHOOSE_PROBABILITY )
730
-
731
-
732
- def pick_timeout_multiplier ():
733
- """Return a random testcase timeout multiplier and adjust timeout."""
734
- fuzz_test_timeout = environment .get_value ('FUZZ_TEST_TIMEOUT' )
735
- custom_timeout_multipliers = environment .get_value (
736
- 'CUSTOM_TIMEOUT_MULTIPLIERS' )
737
- timeout_multiplier = 1.0
738
-
739
- use_multiplier = not utils .random_number (0 , DEFAULT_CHOOSE_PROBABILITY )
740
- if (use_multiplier and not fuzz_test_timeout and
741
- not custom_timeout_multipliers ):
742
- timeout_multiplier = utils .random_element_from_list ([0.5 , 1.5 , 2.0 , 3.0 ])
743
- elif use_multiplier and custom_timeout_multipliers :
744
- # Since they are explicitly set in the job definition, it is fine to use
745
- # custom timeout multipliers even in the case where FUZZ_TEST_TIMEOUT is
746
- # set.
747
- timeout_multiplier = utils .random_element_from_list (
748
- custom_timeout_multipliers )
749
-
750
- return timeout_multiplier
751
-
752
-
753
635
def set_test_timeout (timeout , multipler ):
754
636
"""Set the test timeout based on a timeout value and multiplier."""
755
637
test_timeout = int (timeout * multipler )
756
638
environment .set_value ('TEST_TIMEOUT' , test_timeout )
757
639
return test_timeout
758
640
759
641
760
- def pick_window_argument ():
761
- """Return a window argument with random size and x,y position."""
762
- default_window_argument = environment .get_value ('WINDOW_ARG' , '' )
763
- window_argument_change_chance = not utils .random_number (
764
- 0 , DEFAULT_CHOOSE_PROBABILITY )
765
-
766
- window_argument = ''
767
- if window_argument_change_chance :
768
- window_argument = default_window_argument
769
- if window_argument :
770
- width = utils .random_number (
771
- 100 , utils .random_element_from_list ([256 , 1280 , 2048 ]))
772
- height = utils .random_number (
773
- 100 , utils .random_element_from_list ([256 , 1024 , 1536 ]))
774
- left = utils .random_number (0 , width )
775
- top = utils .random_number (0 , height )
776
-
777
- window_argument = window_argument .replace ('$WIDTH' , str (width ))
778
- window_argument = window_argument .replace ('$HEIGHT' , str (height ))
779
- window_argument = window_argument .replace ('$LEFT' , str (left ))
780
- window_argument = window_argument .replace ('$TOP' , str (top ))
781
-
782
- # FIXME: Random seed is currently passed along to the next job
783
- # via WINDOW_ARG. Rename it without breaking existing tests.
784
- random_seed_argument = environment .get_value ('RANDOM_SEED' )
785
- if random_seed_argument :
786
- if window_argument :
787
- window_argument += ' '
788
- seed = utils .random_number (- 2147483648 , 2147483647 )
789
- window_argument += '%s=%d' % (random_seed_argument .strip (), seed )
790
-
791
- environment .set_value ('WINDOW_ARG' , window_argument )
792
- return window_argument
793
-
794
-
795
642
def truncate_fuzzer_output (output , limit ):
796
643
"""Truncate output in the middle according to limit."""
797
644
if len (output ) < limit :
@@ -1228,19 +1075,6 @@ def key_fn(crash):
1228
1075
return new_crash_count , known_crash_count , processed_groups
1229
1076
1230
1077
1231
- def get_strategy_distribution_from_ndb ():
1232
- """Queries and returns the distribution stored in the ndb table."""
1233
- query = data_types .FuzzStrategyProbability .query ()
1234
- distribution = []
1235
- for strategy_entry in list (ndb_utils .get_all_from_query (query )):
1236
- distribution .append ({
1237
- 'strategy_name' : strategy_entry .strategy_name ,
1238
- 'probability' : strategy_entry .probability ,
1239
- 'engine' : strategy_entry .engine
1240
- })
1241
- return distribution
1242
-
1243
-
1244
1078
def _get_issue_metadata_from_environment (variable_name ):
1245
1079
"""Get issue metadata from environment."""
1246
1080
values = str (environment .get_value_string (variable_name , '' )).split (',' )
@@ -1330,10 +1164,10 @@ def __init__(self, uworker_input, test_timeout):
1330
1164
self .uworker_input = uworker_input
1331
1165
1332
1166
# Set up randomly selected fuzzing parameters.
1333
- self .redzone = pick_redzone ()
1334
- self .disable_ubsan = pick_ubsan_disabled (self .job_type )
1335
- self .timeout_multiplier = pick_timeout_multiplier ()
1336
- self .window_argument = pick_window_argument ()
1167
+ self .redzone = fuzz_task_knobs . pick_redzone ()
1168
+ self .disable_ubsan = fuzz_task_knobs . pick_ubsan_disabled (self .job_type )
1169
+ self .timeout_multiplier = fuzz_task_knobs . pick_timeout_multiplier ()
1170
+ self .window_argument = fuzz_task_knobs . pick_window_argument ()
1337
1171
self .test_timeout = set_test_timeout (test_timeout , self .timeout_multiplier )
1338
1172
1339
1173
# Set up during run().
@@ -1666,8 +1500,8 @@ def do_blackbox_fuzzing(self, fuzzer, fuzzer_directory, job_type):
1666
1500
testcases_metadata [testcase_file_path ] = {}
1667
1501
1668
1502
# Pick up a gesture to run on the testcase.
1669
- testcases_metadata [testcase_file_path ]['gestures' ] = pick_gestures (
1670
- test_timeout )
1503
+ testcases_metadata [testcase_file_path ]['gestures' ] = (
1504
+ fuzz_task_knobs . pick_gestures ( test_timeout ) )
1671
1505
1672
1506
# Prepare selecting trials in main loop below.
1673
1507
trial_selector = trials .Trials ()
@@ -2071,7 +1905,7 @@ def _preprocess_get_fuzz_target(fuzzer_name, job_type):
2071
1905
def utask_preprocess (fuzzer_name , job_type , uworker_env ):
2072
1906
"""Preprocess untrusted task."""
2073
1907
setup_input = setup .preprocess_update_fuzzer_and_data_bundles (fuzzer_name )
2074
- do_multiarmed_bandit_strategy_selection (uworker_env )
1908
+ fuzz_task_knobs . do_multiarmed_bandit_strategy_selection (uworker_env )
2075
1909
environment .set_value ('PROJECT_NAME' , data_handler .get_project_name (job_type ),
2076
1910
uworker_env )
2077
1911
fuzz_target = _preprocess_get_fuzz_target (fuzzer_name , job_type )
0 commit comments