@@ -139,145 +139,137 @@ public class PostgreSQLSync: Module {
139139 // If not found (e.g., corpus import), use empty strings
140140 let programId = program. id. uuidString
141141 let ( stdout, stderr, fuzzout) = self . executionCache [ programId] ?? ( " " , " " , " " )
142-
143- // Clean up the cache entry immediately after use
144142 self . executionCache. removeValue ( forKey: programId)
145-
146- Task {
147- guard let fuzzerId = self . cachedFuzzerId else {
148- self . logger. error ( " Fuzzer ID not set - registration may have failed " )
149- return
150- }
151-
152- let programInput = try self . prepareProgramInput ( program: program, fuzzerId: fuzzerId, programId: programId)
153- await self . storage. addProgramToBatch ( programInput)
154-
155- if let execution = execution {
156- let outcomeId = DatabaseUtils . mapExecutionOutcome ( outcome: execution. outcome)
157143
158- // Determine if new edges were found
159- // Check if aspects is a CovEdgeSet to distinguish between:
160- // - New coverage edges (CovEdgeSet with count > 0)
161- // - Feedback/optimization delta only (basic ProgramAspects)
162- let isNewEdge : Bool
163- if let covEdgeSet = aspects as? CovEdgeSet {
164- isNewEdge = covEdgeSet. count > 0
165- } else {
166- isNewEdge = false
167- }
144+ guard let fuzzerId = self . cachedFuzzerId else {
145+ self . logger. error ( " Fuzzer ID not set - registration may have failed " )
146+ return
147+ }
168148
169- var coverageTotal : Double ? = nil
170- var edgesFound : Int ? = nil
171- var totalEdges : Int ? = nil
172- var turbofanOptimizationBits : Int64 ? = nil
173- var feedbackNexusCount : Int ? = nil
174-
175- if let evaluator = self . covEvaluator {
176- let totalEdgesCount = evaluator. getTotalEdgesCount ( )
177- totalEdges = Int ( totalEdgesCount)
178-
179- let foundEdgesCount = evaluator. getFoundEdgesCount ( )
180-
181- if totalEdgesCount > 0 {
182- coverageTotal = ( Double ( foundEdgesCount) / Double( totalEdgesCount) ) * 100
183- }
184-
185- if let covEdgeSet = aspects as? CovEdgeSet {
186- edgesFound = Int ( covEdgeSet. count)
187- } else {
188- edgesFound = 0
189- }
190-
191- turbofanOptimizationBits = Int64 ( evaluator. getTurbofanOptimizationBits ( ) )
192- feedbackNexusCount = Int ( evaluator. getFeedbackNexusCount ( ) )
193- }
194-
195- let executionInput = PostgresSQLStorage . ExecutionInput (
196- programHash: programInput. programHash,
197- executionOutcomeId: outcomeId,
198- coverageTotal: coverageTotal,
199- edgesFound: edgesFound,
200- totalEdges: totalEdges,
201- isNewEdge: isNewEdge,
202- stdout: stdout,
203- stderr: stderr,
204- fuzzout: fuzzout,
205- turbofanOptimizationBits: turbofanOptimizationBits,
206- feedbackNexusCount: feedbackNexusCount,
207- createdAt: Date ( )
208- )
209- await self . storage. addExecutionToBatch ( executionInput)
210-
211- // TODO Aleksi: This is a bit too verbose, maybe only log every x times
212- //if self.enableLogging {
213- // let edgeInfo = isNewEdge ? " with new edges" : " (feedback/optimization delta only)"
214- // self.logger.verbose("Added interesting program and execution to batch\(edgeInfo)")
215- //}
216- }
149+ let programInput : PostgresSQLStorage . ProgramInput
150+ do {
151+ programInput = try self . prepareProgramInput ( program: program, fuzzerId: fuzzerId, programId: programId)
152+ } catch {
153+ self . logger. error ( " Failed to prepare program input: \( error) " )
154+ return
217155 }
218- }
219-
220- fuzzer. registerEventListener ( for: fuzzer. events. CrashFound) { ev in
221- let program = ev. program
222- let behaviour = ev. behaviour // .deterministic or .flaky
223- let isUnique = ev. isUnique
224-
225- // Retrieve cached execution outputs using program ID
226- // For crashes, stderr will contain the crash stacktrace and signal info
227- let programId = program. id. uuidString
228- let ( stdout, stderr, fuzzout) = self . executionCache [ programId] ?? ( " " , " " , " " )
229-
230- // Clean up the cache entry immediately after use
231- self . executionCache. removeValue ( forKey: programId)
232-
233- Task {
234- guard let fuzzerId = self . cachedFuzzerId else {
235- self . logger. error ( " Fuzzer ID not set - registration may have failed " )
236- return
156+
157+ var executionInput : PostgresSQLStorage . ExecutionInput ? = nil
158+ if let execution = execution {
159+ // Determine if new edges were found
160+ // Check if aspects is a CovEdgeSet to distinguish between:
161+ // - New coverage edges (CovEdgeSet with count > 0)
162+ // - Feedback/optimization delta only (basic ProgramAspects)
163+ let isNewEdge : Bool
164+ if let covEdgeSet = aspects as? CovEdgeSet {
165+ isNewEdge = covEdgeSet. count > 0
166+ } else {
167+ isNewEdge = false
237168 }
238169
239- let programInput = try self . prepareProgramInput ( program: program, fuzzerId: fuzzerId, programId: programId)
240- await self . storage. addProgramToBatch ( programInput)
241-
242- // Get coverage metrics if available (crashes may still have coverage)
243170 var coverageTotal : Double ? = nil
244171 var edgesFound : Int ? = nil
245172 var totalEdges : Int ? = nil
246173 var turbofanOptimizationBits : Int64 ? = nil
247174 var feedbackNexusCount : Int ? = nil
248-
175+
249176 if let evaluator = self . covEvaluator {
250177 let totalEdgesCount = evaluator. getTotalEdgesCount ( )
251178 totalEdges = Int ( totalEdgesCount)
252-
253179 let foundEdgesCount = evaluator. getFoundEdgesCount ( )
254-
255180 if totalEdgesCount > 0 {
256181 coverageTotal = ( Double ( foundEdgesCount) / Double( totalEdgesCount) ) * 100
257182 }
258-
259- // For crashes, we don't have new edge information in the same way
260- edgesFound = Int ( foundEdgesCount)
261-
183+ if let covEdgeSet = aspects as? CovEdgeSet {
184+ edgesFound = Int ( covEdgeSet. count)
185+ } else {
186+ edgesFound = 0
187+ }
262188 turbofanOptimizationBits = Int64 ( evaluator. getTurbofanOptimizationBits ( ) )
263189 feedbackNexusCount = Int ( evaluator. getFeedbackNexusCount ( ) )
264190 }
265-
266- // Create execution record with outcome_id = 1 (Crashed)
267- let executionInput = PostgresSQLStorage . ExecutionInput (
191+
192+ executionInput = PostgresSQLStorage . ExecutionInput (
268193 programHash: programInput. programHash,
269- executionOutcomeId: 1 , // Crashed
194+ executionOutcomeId: DatabaseUtils . mapExecutionOutcome ( outcome : execution . outcome ) ,
270195 coverageTotal: coverageTotal,
271196 edgesFound: edgesFound,
272197 totalEdges: totalEdges,
273- isNewEdge: false , // Crashes don't contribute new edges
198+ isNewEdge: isNewEdge ,
274199 stdout: stdout,
275- stderr: stderr, // Contains crash stacktrace and signal info
200+ stderr: stderr,
276201 fuzzout: fuzzout,
277202 turbofanOptimizationBits: turbofanOptimizationBits,
278203 feedbackNexusCount: feedbackNexusCount,
279204 createdAt: Date ( )
280205 )
206+ }
207+ Task {
208+ await self . storage. addProgramToBatch ( programInput)
209+ if let executionInput = executionInput {
210+ await self . storage. addExecutionToBatch ( executionInput)
211+ }
212+ }
213+ }
214+
215+ fuzzer. registerEventListener ( for: fuzzer. events. CrashFound) { ev in
216+ let program = ev. program
217+ let behaviour = ev. behaviour // .deterministic or .flaky
218+ let isUnique = ev. isUnique
219+
220+ // Retrieve cached execution outputs using program ID
221+ // For crashes, stderr will contain the crash stacktrace and signal info
222+ let programId = program. id. uuidString
223+ let ( stdout, stderr, fuzzout) = self . executionCache [ programId] ?? ( " " , " " , " " )
224+ self . executionCache. removeValue ( forKey: programId)
225+
226+ guard let fuzzerId = self . cachedFuzzerId else {
227+ self . logger. error ( " Fuzzer ID not set - registration may have failed " )
228+ return
229+ }
230+
231+ let programInput : PostgresSQLStorage . ProgramInput
232+ do {
233+ programInput = try self . prepareProgramInput ( program: program, fuzzerId: fuzzerId, programId: programId)
234+ } catch {
235+ self . logger. error ( " Failed to prepare program input: \( error) " )
236+ return
237+ }
238+
239+ // Get coverage metrics if available (crashes may still have coverage)
240+ var coverageTotal : Double ? = nil
241+ var totalEdges : Int ? = nil
242+ var turbofanOptimizationBits : Int64 ? = nil
243+ var feedbackNexusCount : Int ? = nil
244+
245+ if let evaluator = self . covEvaluator {
246+ let totalEdgesCount = evaluator. getTotalEdgesCount ( )
247+ totalEdges = Int ( totalEdgesCount)
248+ let foundEdgesCount = evaluator. getFoundEdgesCount ( )
249+ if totalEdgesCount > 0 {
250+ coverageTotal = ( Double ( foundEdgesCount) / Double( totalEdgesCount) ) * 100
251+ }
252+ turbofanOptimizationBits = Int64 ( evaluator. getTurbofanOptimizationBits ( ) )
253+ feedbackNexusCount = Int ( evaluator. getFeedbackNexusCount ( ) )
254+ }
255+
256+ let executionInput = PostgresSQLStorage . ExecutionInput (
257+ programHash: programInput. programHash,
258+ executionOutcomeId: 1 , // Crashed
259+ coverageTotal: coverageTotal,
260+ edgesFound: nil , // Crashes don't contribute new edges
261+ totalEdges: totalEdges,
262+ isNewEdge: false , // Crashes don't contribute new edges
263+ stdout: stdout,
264+ stderr: stderr, // Contains crash stacktrace and signal info
265+ fuzzout: fuzzout,
266+ turbofanOptimizationBits: turbofanOptimizationBits,
267+ feedbackNexusCount: feedbackNexusCount,
268+ createdAt: Date ( )
269+ )
270+ // TODO Aleksi: Store the crash on disk as well
271+ Task {
272+ await self . storage. addProgramToBatch ( programInput)
281273 await self . storage. addExecutionToBatch ( executionInput)
282274
283275 if self . enableLogging {
@@ -289,7 +281,7 @@ public class PostgreSQLSync: Module {
289281 }
290282
291283 // Periodic Flush
292- fuzzer. timers. scheduleTask ( every: 15 * Minutes) {
284+ fuzzer. timers. scheduleTask ( every: 2 * Minutes) {
293285 Task {
294286 do {
295287 try await self . storage. flushBatches ( )
@@ -463,8 +455,4 @@ public class PostgreSQLSync: Module {
463455 parentHash: parentHash
464456 )
465457 }
466-
467- private func prepareExecutionInput( ) {
468-
469- }
470458}
0 commit comments